From d4b1f5f197461a2bbdc319abd15b6bb349784c08 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Sun, 22 Oct 2023 16:47:38 +0200 Subject: [PATCH 001/107] Update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 8b1d6803..cdf538c8 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 8b1d68032087288839a7162cc12bcde812672d72 +Subproject commit cdf538c8adbb7dc2ab515bbf203f54ab2552dfc7 From 46511c7385b8fa695787e7e938d83963dce4f116 Mon Sep 17 00:00:00 2001 From: rpls Date: Tue, 24 Oct 2023 05:47:25 +0200 Subject: [PATCH 002/107] Small overhaul of OpenCM3 code, rework Nucleo-L4R5ZI target a bit, and add CW308T-STM32F415 target (#259) * Only compile the specific libopencm3 library needed * Add experimental support for CW308T-STM32F415 * Shut up the linker errors * Shut up unused parameter warning * Fix Keccaktest bin generation * Update libopencm3 * Adapt to renamed constants * Compile the board test with fast and slow clock * Use wrapped symbols instead of overriding * Overhaul clocking for L4R5ZI board --- common/hal-opencm3.c | 129 ++++++++++++++++++++++++++++++++++++----- common/test.c | 6 +- common/testfast.c | 1 + interface.py | 4 +- libopencm3 | 2 +- mk/cw308t-stm32f3.mk | 1 + mk/cw308t-stm32f415.mk | 14 +++++ mk/nucleo-l476rg.mk | 1 + mk/nucleo-l4r5zi.mk | 4 ++ mk/opencm3.mk | 10 +++- mk/stm32f4discovery.mk | 2 + mk/tests.mk | 11 +++- 12 files changed, 164 insertions(+), 21 deletions(-) create mode 120000 common/testfast.c create mode 100644 mk/cw308t-stm32f415.mk diff --git a/common/hal-opencm3.c b/common/hal-opencm3.c index a760656e..a27ceba7 100644 --- a/common/hal-opencm3.c +++ b/common/hal-opencm3.c @@ -56,6 +56,17 @@ const struct rcc_clock_scale benchmarkclock = { #include #include +#define SERIAL_GPIO GPIOA +#define SERIAL_USART USART1 +#define SERIAL_PINS (GPIO9 | GPIO10) +#define STM32 +#define CW_BOARD +#elif defined(STM32F415RGT6) +#include +#include +#include +#include + #define SERIAL_GPIO GPIOA #define SERIAL_USART USART1 #define SERIAL_PINS (GPIO9 | GPIO10) @@ -119,6 +130,7 @@ static void clock_setup(enum clock_mode clock) flash_prefetch_enable(); #elif defined(CW_BOARD) + (void) clock; /* Some STM32 Platform */ rcc_periph_clock_enable(RCC_GPIOH); rcc_osc_off(RCC_HSE); @@ -131,8 +143,13 @@ static void clock_setup(enum clock_mode clock) rcc_apb2_frequency = 7372800; _clock_freq = 7372800; rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); +#if defined(STM32F3) rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_NONE); rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_NONE); +#elif defined(STM32F4) + rcc_set_ppre1(RCC_CFGR_PPRE_DIV_NONE); + rcc_set_ppre2(RCC_CFGR_PPRE_DIV_NONE); +#endif rcc_set_sysclk_source(RCC_CFGR_SW_HSE); rcc_wait_for_sysclk_status(RCC_HSE); #elif defined(NUCLEO_BOARD) @@ -147,8 +164,8 @@ static void clock_setup(enum clock_mode clock) rcc_apb2_frequency = 16000000; _clock_freq = 16000000; rcc_set_hpre(RCC_CFGR_HPRE_NODIV); - rcc_set_ppre1(RCC_CFGR_PPRE1_NODIV); - rcc_set_ppre2(RCC_CFGR_PPRE2_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); flash_dcache_enable(); flash_icache_enable(); flash_set_ws(FLASH_ACR_LATENCY_0WS); @@ -165,8 +182,8 @@ static void clock_setup(enum clock_mode clock) rcc_apb2_frequency = 80000000; _clock_freq = 80000000; rcc_set_hpre(RCC_CFGR_HPRE_NODIV); - rcc_set_ppre1(RCC_CFGR_PPRE1_NODIV); - rcc_set_ppre2(RCC_CFGR_PPRE2_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); rcc_osc_off(RCC_PLL); while(rcc_is_osc_ready(RCC_PLL)); /* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 80MHz). */ @@ -189,24 +206,33 @@ static void clock_setup(enum clock_mode clock) rcc_periph_clock_enable(RCC_PWR); rcc_periph_clock_enable(RCC_SYSCFG); pwr_set_vos_scale(PWR_SCALE1); + /* The L4R5ZI chip also needs the R1MODE bit in PWR_CR5 register set, but + OpenCM3 doesn't support this yet. But luckily the default value for the bit + is 1. */ switch (clock) { case CLOCK_BENCHMARK: /* Benchmark straight from the HSI16 without prescaling */ rcc_osc_on(RCC_HSI16); rcc_wait_for_osc_ready(RCC_HSI16); - rcc_ahb_frequency = 16000000; - rcc_apb1_frequency = 16000000; - rcc_apb2_frequency = 16000000; - _clock_freq = 16000000; + rcc_ahb_frequency = 20000000; + rcc_apb1_frequency = 20000000; + rcc_apb2_frequency = 20000000; + _clock_freq = 20000000; rcc_set_hpre(RCC_CFGR_HPRE_NODIV); - rcc_set_ppre1(RCC_CFGR_PPRE1_NODIV); - rcc_set_ppre2(RCC_CFGR_PPRE2_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); + rcc_osc_off(RCC_PLL); + while(rcc_is_osc_ready(RCC_PLL)); + /* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 20MHz). */ + _rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 10, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV8); + /* Enable PLL oscillator and wait for it to stabilize. */ + rcc_osc_on(RCC_PLL); flash_dcache_enable(); flash_icache_enable(); flash_set_ws(FLASH_ACR_LATENCY_0WS); flash_prefetch_enable(); - rcc_set_sysclk_source(RCC_CFGR_SW_HSI16); - rcc_wait_for_sysclk_status(RCC_HSI16); + rcc_set_sysclk_source(RCC_CFGR_SW_PLL); + rcc_wait_for_sysclk_status(RCC_PLL); break; case CLOCK_FAST: default: @@ -217,12 +243,12 @@ static void clock_setup(enum clock_mode clock) rcc_apb2_frequency = 120000000; _clock_freq = 120000000; rcc_set_hpre(RCC_CFGR_HPRE_NODIV); - rcc_set_ppre1(RCC_CFGR_PPRE1_NODIV); - rcc_set_ppre2(RCC_CFGR_PPRE2_NODIV); + rcc_set_ppre1(RCC_CFGR_PPRE_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE_NODIV); rcc_osc_off(RCC_PLL); while(rcc_is_osc_ready(RCC_PLL)); /* Configure the PLL oscillator (use CUBEMX tool -> scale HSI16 to 120MHz). */ - _rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 2, 30, 2u, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV2); + _rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 1, 15, 2, RCC_PLLCFGR_PLLQ_DIV2, RCC_PLLCFGR_PLLR_DIV2); /* Enable PLL oscillator and wait for it to stabilize. */ rcc_osc_on(RCC_PLL); rcc_wait_for_osc_ready(RCC_PLL); @@ -235,7 +261,9 @@ static void clock_setup(enum clock_mode clock) break; } rcc_osc_on(RCC_HSI48); /* HSI48 must always be on for RNG */ + rcc_wait_for_osc_ready(RCC_HSI48); rcc_periph_clock_enable(RCC_RNG); + rcc_set_clock48_source(RCC_CCIPR_CLK48SEL_HSI48); rng_enable(); #else #error Unsupported platform @@ -358,3 +386,74 @@ size_t hal_get_stack_size(void) __asm__ volatile ("mov %0, sp" : "=r" (cur_stack)); return cur_stack - heap_end; } + +/* Implement some system calls to shut up the linker warnings */ + +#include +#undef errno +extern int errno; + +int __wrap__close(int fd) +{ + errno = ENOSYS; + (void) fd; + return -1; +} + +#include + +int __wrap__fstat(int fd, struct stat* buf) +{ + (void) fd; + (void) buf; + errno = ENOSYS; + return -1; +} + +int __wrap__getpid(void) +{ + errno = ENOSYS; + return -1; +} + +int __wrap__isatty(int file) +{ + (void) file; + errno = ENOSYS; + return 0; +} + +int __wrap__kill(int pid, int sig) +{ + (void) pid; + (void) sig; + errno = ENOSYS; + return -1; +} + +int __wrap__lseek(int fd, int ptr, int dir) +{ + (void) fd; + (void) ptr; + (void) dir; + errno = ENOSYS; + return -1; +} + +int __wrap__read(int fd, char* ptr, int len) +{ + (void) fd; + (void) ptr; + (void) len; + errno = ENOSYS; + return -1; +} + +int __wrap__write(int fd, const char* ptr, int len) +{ + (void) fd; + (void) ptr; + (void) len; + errno = ENOSYS; + return -1; +} diff --git a/common/test.c b/common/test.c index a2841081..d3878dda 100644 --- a/common/test.c +++ b/common/test.c @@ -124,9 +124,13 @@ static void memory_timing_test(void) } #endif +#ifndef CLOCK_TEST +#define CLOCK_TEST CLOCK_BENCHMARK +#endif + int main(void) { - hal_setup(CLOCK_FAST); + hal_setup(CLOCK_TEST); hal_send_str("Hello world"); send_unsigned("Stack Size", hal_get_stack_size()); unsigned rnd; diff --git a/common/testfast.c b/common/testfast.c new file mode 120000 index 00000000..aeebb262 --- /dev/null +++ b/common/testfast.c @@ -0,0 +1 @@ +test.c \ No newline at end of file diff --git a/interface.py b/interface.py index 25a6587e..3b83fa7c 100644 --- a/interface.py +++ b/interface.py @@ -10,7 +10,7 @@ def parse_arguments(): "-p", "--platform", help="The PQM4 platform", - choices=["stm32f4discovery", "nucleo-l476rg", "nucleo-l4r5zi", "cw308t-stm32f3", "mps2-an386"], + choices=["stm32f4discovery", "nucleo-l476rg", "nucleo-l4r5zi", "cw308t-stm32f3", "cw308t-stm32f415", "mps2-an386"], default="stm32f4discovery", ) parser.add_argument( @@ -39,7 +39,7 @@ def get_platform(args): elif args.platform == "nucleo-l4r5zi": bin_type = 'hex' platform = platforms.OpenOCD("st_nucleo_l4r5.cfg", args.uart) - elif args.platform == "cw308t-stm32f3": + elif args.platform in ["cw308t-stm32f3", "cw308t-stm32f415"]: bin_type = 'hex' platform = platforms.ChipWhisperer() elif args.platform == 'mps2-an386': diff --git a/libopencm3 b/libopencm3 index b1d8a4c5..1f3abd43 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit b1d8a4c546531d6a79f9a7be156205c6a40f215c +Subproject commit 1f3abd43763fa39d23e737602b6d0011a45c70b2 diff --git a/mk/cw308t-stm32f3.mk b/mk/cw308t-stm32f3.mk index b0cffedd..7aa3d846 100644 --- a/mk/cw308t-stm32f3.mk +++ b/mk/cw308t-stm32f3.mk @@ -1,4 +1,5 @@ DEVICE=stm32f303rct7 +OPENCM3_TARGET=lib/stm32/f3 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_sign/sphincs-haraka-256f% \ diff --git a/mk/cw308t-stm32f415.mk b/mk/cw308t-stm32f415.mk new file mode 100644 index 00000000..a3891bfe --- /dev/null +++ b/mk/cw308t-stm32f415.mk @@ -0,0 +1,14 @@ +DEVICE=stm32f415rgt6 +OPENCM3_TARGET=lib/stm32/f4 + +EXCLUDED_SCHEMES = \ + mupq/pqclean/crypto_sign/sphincs-haraka-256f% \ + mupq/pqclean/crypto_sign/sphincs-shake256-256f% \ + mupq/pqclean/crypto_sign/sphincs-sha256-256f% \ + mupq/pqclean/crypto_kem/mceliece% \ + mupq/crypto_sign/falcon-1024% \ + mupq/crypto_sign/falcon-512% \ + crypto_sign/falcon-1024% \ + crypto_sign/falcon-512% + +include mk/opencm3.mk diff --git a/mk/nucleo-l476rg.mk b/mk/nucleo-l476rg.mk index 93cab6f5..62349b53 100644 --- a/mk/nucleo-l476rg.mk +++ b/mk/nucleo-l476rg.mk @@ -1,4 +1,5 @@ DEVICE=stm32l476rg +OPENCM3_TARGET=lib/stm32/l4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ diff --git a/mk/nucleo-l4r5zi.mk b/mk/nucleo-l4r5zi.mk index 164d4e72..b3b673cd 100644 --- a/mk/nucleo-l4r5zi.mk +++ b/mk/nucleo-l4r5zi.mk @@ -1,4 +1,5 @@ DEVICE=stm32l4r5zi +OPENCM3_TARGET=lib/stm32/l4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ @@ -9,4 +10,7 @@ DEVICES_DATA := ldscripts/devices.data elf/boardtest.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_SRAM3 elf/boardtest.elf: LDSCRIPT=ldscripts/$(PLATFORM)-ramtest.ld +elf/boardtest-fast.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_SRAM3 +elf/boardtest-fast.elf: LDSCRIPT=ldscripts/$(PLATFORM)-ramtest.ld + include mk/opencm3.mk diff --git a/mk/opencm3.mk b/mk/opencm3.mk index b1c259bc..fbcd2428 100644 --- a/mk/opencm3.mk +++ b/mk/opencm3.mk @@ -61,7 +61,7 @@ LDFLAGS += -L$(OPENCM3_DIR)/lib CPPFLAGS += -I$(OPENCM3_DIR)/include $(OPENCM3_DIR)/lib/lib$(LIBNAME).a: - $(MAKE) -C $(OPENCM3_DIR) + $(MAKE) -C $(OPENCM3_DIR) $(OPENCM3_TARGET) obj/common/hal-opencm3.c.o: $(OPENCM3_DIR)/lib/lib$(LIBNAME).a @@ -89,6 +89,14 @@ CFLAGS += \ LDFLAGS += \ --specs=nosys.specs \ -Wl,--wrap=_sbrk \ + -Wl,--wrap=_close \ + -Wl,--wrap=_isatty \ + -Wl,--wrap=_kill \ + -Wl,--wrap=_lseek \ + -Wl,--wrap=_read \ + -Wl,--wrap=_write \ + -Wl,--wrap=_fstat \ + -Wl,--wrap=_getpid \ -nostartfiles \ -ffreestanding \ -T$(LDSCRIPT) \ diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index bf1f8a77..41862137 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -1,4 +1,5 @@ DEVICE=stm32f407vg +OPENCM3_TARGET=lib/stm32/f4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ @@ -7,6 +8,7 @@ EXCLUDED_SCHEMES = \ include mk/opencm3.mk elf/boardtest.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_CCM +elf/boardtest-fast.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_CCM elf/crypto_kem_frodokem640aes_m4_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/mupq_pqclean_crypto_kem_frodokem640shake_opt_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld diff --git a/mk/tests.mk b/mk/tests.mk index faf27a79..40923ab8 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -2,6 +2,11 @@ ifeq ($(AIO),1) elf/boardtest.elf: common/test.c $(LINKDEPS) $(CONFIG) $(compiletest) +elf/boardtest-fast.elf: common/testfast.c $(LINKDEPS) $(CONFIG) + $(compiletest) + +elf/boardtest-fast.elf: CPPFLAGS += -DCLOCK_TEST=CLOCK_FAST + elf/aestest.elf: common/aestest.c $(LINKDEPS) $(CONFIG) $(compiletest) @@ -10,10 +15,14 @@ elf/keccaktest.elf: common/keccaktest.c $(LINKDEPS) $(CONFIG) else elf/boardtest.elf: $(call objs,common/test.c) $(LINKDEPS) $(CONFIG) +elf/boardtest-fast.elf: $(call objs,common/testfast.c) $(LINKDEPS) $(CONFIG) + +$(call objs,common/testfast.c): CPPFLAGS += -DCLOCK_TEST=CLOCK_FAST + elf/aestest.elf: $(call objs,common/aestest.c) $(LINKDEPS) $(CONFIG) elf/keccaktest.elf: $(call objs,common/keccaktest.c) $(LINKDEPS) $(CONFIG) endif tests: elf/boardtest.elf elf/aestest.elf elf/keccaktest.elf -tests-bin: bin/boardtest.bin bin/aestest.bin bin/keccaktest.elf +tests-bin: bin/boardtest.bin bin/aestest.bin bin/keccaktest.bin From d5938b701c9c2827ec272e1193df07cfb5ddb1a1 Mon Sep 17 00:00:00 2001 From: Till Eifert Date: Thu, 26 Oct 2023 15:49:10 +0200 Subject: [PATCH 003/107] BIKE update schemes opt and m4f to spec v5.1 verified with KATs and testvectors --- crypto_kem/bikel1/m4f/api.h | 4 + crypto_kem/bikel1/m4f/defs.h | 9 +- crypto_kem/bikel1/m4f/error.h | 6 +- crypto_kem/bikel1/m4f/gf2x.h | 8 +- crypto_kem/bikel1/m4f/kem.c | 20 ++-- crypto_kem/bikel1/m4f/sampling.c | 149 +++++++----------------------- crypto_kem/bikel1/m4f/sampling.h | 13 +-- crypto_kem/bikel1/m4f/sha.h | 42 +-------- crypto_kem/bikel1/m4f/shake_prf.c | 65 +++++++++++++ crypto_kem/bikel1/m4f/shake_prf.h | 35 +++++++ crypto_kem/bikel3/m4f/api.h | 4 + crypto_kem/bikel3/m4f/defs.h | 9 +- crypto_kem/bikel3/m4f/error.h | 6 +- crypto_kem/bikel3/m4f/gf2x.h | 8 +- crypto_kem/bikel3/m4f/kem.c | 54 +++++------ crypto_kem/bikel3/m4f/sampling.c | 149 +++++++----------------------- crypto_kem/bikel3/m4f/sampling.h | 13 +-- crypto_kem/bikel3/m4f/sha.h | 42 +-------- crypto_kem/bikel3/m4f/shake_prf.c | 65 +++++++++++++ crypto_kem/bikel3/m4f/shake_prf.h | 35 +++++++ 20 files changed, 360 insertions(+), 376 deletions(-) create mode 100644 crypto_kem/bikel1/m4f/shake_prf.c create mode 100644 crypto_kem/bikel1/m4f/shake_prf.h create mode 100644 crypto_kem/bikel3/m4f/shake_prf.c create mode 100644 crypto_kem/bikel3/m4f/shake_prf.h diff --git a/crypto_kem/bikel1/m4f/api.h b/crypto_kem/bikel1/m4f/api.h index b2281850..304366f2 100644 --- a/crypto_kem/bikel1/m4f/api.h +++ b/crypto_kem/bikel1/m4f/api.h @@ -3,11 +3,15 @@ * * Written by Nir Drucker and Shay Gueron * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #pragma once #include "types.h" +#include "crypto_kem.h" #define CRYPTO_SECRETKEYBYTES sizeof(sk_t) #define CRYPTO_PUBLICKEYBYTES sizeof(pk_t) diff --git a/crypto_kem/bikel1/m4f/defs.h b/crypto_kem/bikel1/m4f/defs.h index 1a097fd6..2a49f679 100644 --- a/crypto_kem/bikel1/m4f/defs.h +++ b/crypto_kem/bikel1/m4f/defs.h @@ -3,6 +3,10 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert + * */ #pragma once @@ -26,7 +30,8 @@ // In asm the symbols '==' and '?' are not allowed. Therefore, if using // divide_and_ceil in asm files, we must ensure with static_assert its validity. -#if(__cplusplus >= 201103L) || defined(static_assert) +//#if(__cplusplus >= 201103L) || defined(static_assert) +#if defined(static_assert) # define bike_static_assert(COND, MSG) static_assert(COND, "MSG") #else # define bike_static_assert(COND, MSG) \ @@ -34,7 +39,7 @@ #endif // Divide by the divider and round up to next integer -#define DIVIDE_AND_CEIL(x, divider) (((x) + (divider)) / (divider)) +#define DIVIDE_AND_CEIL(x, divider) (((x) + (divider) - 1) / (divider)) // Bit manipulations // Linux Assemblies, except for Ubuntu, cannot understand what ULL mean. diff --git a/crypto_kem/bikel1/m4f/error.h b/crypto_kem/bikel1/m4f/error.h index f19a2366..580a9fe2 100644 --- a/crypto_kem/bikel1/m4f/error.h +++ b/crypto_kem/bikel1/m4f/error.h @@ -5,6 +5,7 @@ * AWS Cryptographic Algorithms Group. * * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert * */ @@ -22,12 +23,13 @@ enum _bike_err E_DECODING_FAILURE = 1, E_AES_CTR_PRF_INIT_FAIL = 2, E_AES_OVER_USED = 3, - EXTERNAL_LIB_ERROR_OPENSSL = 4 + EXTERNAL_LIB_ERROR_OPENSSL = 4, + E_SHAKE_PRF_INIT_FAIL = 5, + E_SHAKE_OVER_USED = 6 }; typedef enum _bike_err _bike_err_t; -//extern __thread _bike_err_t bike_errno; extern _bike_err_t bike_errno; #define BIKE_ERROR(x) \ do { \ diff --git a/crypto_kem/bikel1/m4f/gf2x.h b/crypto_kem/bikel1/m4f/gf2x.h index df6bc3b1..f4cdb53a 100644 --- a/crypto_kem/bikel1/m4f/gf2x.h +++ b/crypto_kem/bikel1/m4f/gf2x.h @@ -13,16 +13,12 @@ _INLINE_ void gf2x_mod_add(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b) { - REG_T va, vb; const uint64_t *a_qwords = (const uint64_t *)a; const uint64_t *b_qwords = (const uint64_t *)b; uint64_t * c_qwords = (uint64_t *)c; - for(size_t i = 0; i < R_PADDED_QWORDS; i += REG_QWORDS) { - va = LOAD(&a_qwords[i]); - vb = LOAD(&b_qwords[i]); - - STORE(&c_qwords[i], va ^ vb); + for(size_t i = 0; i < R_PADDED_QWORDS; i++) { + c_qwords[i] = a_qwords[i] ^ b_qwords[i]; } } diff --git a/crypto_kem/bikel1/m4f/kem.c b/crypto_kem/bikel1/m4f/kem.c index 4a0cf047..ca083e1e 100644 --- a/crypto_kem/bikel1/m4f/kem.c +++ b/crypto_kem/bikel1/m4f/kem.c @@ -5,10 +5,11 @@ * AWS Cryptographic Algorithms Group. * * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert * */ - #include "crypto_kem.h" +#include "crypto_kem.h" #include "decode.h" #include "gf2x.h" #include "sampling.h" @@ -95,7 +96,7 @@ _INLINE_ ret_t encrypt(OUT ct_t *ct, // ct = pk * e1 + e0 //gf2x_mod_mul(&p_ct, &e->val[1], &p_pk); //gf2x_mod_add(&p_ct, &p_ct, &e->val[0]); - ring_mul(&p_ct, &e->val[1], &p_pk); +ring_mul(&p_ct, &e->val[1], &p_pk); ring_add(&p_ct, &p_ct, &e->val[0]); @@ -150,11 +151,11 @@ int crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) // The randomness of the key generation DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup); - // An AES_PRF state for the secret key - DEFER_CLEANUP(aes_ctr_prf_state_t h_prf_state = {0}, aes_ctr_prf_state_cleanup); - get_seeds(&seeds); - GUARD(init_aes_ctr_prf_state(&h_prf_state, MAX_AES_INVOKATION, &seeds.seed[0])); + // A SHAKE_PRF state for the secret key + DEFER_CLEANUP(prf_state_t h_prf_state = {0}, clean_shake256_prf_state); + + GUARD(init_shake256_prf_state(&h_prf_state, MAX_PRF_INVOCATION, &seeds.seed[0])); // Generate the secret key (h0, h1) with weight w/2 GUARD(generate_sparse_rep(&h0, l_sk.wlist[0].val, &h_prf_state)); @@ -166,7 +167,7 @@ int crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) // Calculate the public key gf2x_mod_inv(&h0inv, &h0); //gf2x_mod_mul(&h, &h1, &h0inv); - ring_mul(&h, &h1, &h0inv); +ring_mul(&h, &h1, &h0inv); // Fill the secret key data structure with contents - cancel the padding l_sk.bin[0] = h0.val; @@ -256,8 +257,9 @@ int crypto_kem_dec(OUT unsigned char * ss, // (Note: possibly, a "fixed" zeroed error vector could suffice too, // and serve this generation) // get_seeds(&seeds); -// GUARD(generate_error_vector(&e_prime, &seeds.seed[0])); - memset(&e_prime,0,sizeof(e_prime)); + //GUARD(generate_error_vector(&e_prime, &seeds.seed[0])); +// generate_error_vector(&e_prime, &seeds.seed[0]); + memset( &e_prime, 0 , sizeof(e_prime) ); // Decode and on success check if |e|=T (all in constant-time) volatile uint32_t success_cond = (decode(&e, &l_ct, &l_sk) == SUCCESS); diff --git a/crypto_kem/bikel1/m4f/sampling.c b/crypto_kem/bikel1/m4f/sampling.c index 307eab0c..0b9dc34c 100644 --- a/crypto_kem/bikel1/m4f/sampling.c +++ b/crypto_kem/bikel1/m4f/sampling.c @@ -3,11 +3,15 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #include #include "sampling.h" +#include "cleanup.h" void get_seeds(OUT seeds_t *seeds) { @@ -25,126 +29,41 @@ void get_seeds(OUT seeds_t *seeds) } } -// BSR returns ceil(log2(val)) -_INLINE_ uint8_t bit_scan_reverse_vartime(IN uint64_t val) -{ - // index is always smaller than 64 - uint8_t index = 0; - - while(val != 0) { - val >>= 1; - index++; - } - - return index; -} - -_INLINE_ ret_t get_rand_mod_len(OUT uint32_t * rand_pos, - IN const uint32_t len, - IN OUT aes_ctr_prf_state_t *prf_state) -{ - const uint64_t mask = MASK(bit_scan_reverse_vartime(len)); - - do { - // Generate a 32 bits (pseudo) random value. - // This can be optimized to take only 16 bits. - GUARD(aes_ctr_prf((uint8_t *)rand_pos, prf_state, sizeof(*rand_pos))); - - // Mask relevant bits only - (*rand_pos) &= mask; - - // Break if a number that is smaller than len is found - if((*rand_pos) < len) { - break; - } - - } while(1 == 1); - - return SUCCESS; -} - -_INLINE_ void make_odd_weight(IN OUT r_t *r) -{ - if(((r_bits_vector_weight(r) % 2) == 1)) { - // Already odd - return; - } - - r->raw[0] ^= 1; -} - -// Returns an array of r pseudorandom bits. -// No restrictions exist for the top or bottom bits. -// If the generation requires an odd number, then set must_be_odd=1. -// The function uses the provided prf context. -ret_t sample_uniform_r_bits_with_fixed_prf_context( - OUT r_t *r, - IN OUT aes_ctr_prf_state_t *prf_state, - IN const must_be_odd_t must_be_odd) -{ - // Generate random data - GUARD(aes_ctr_prf(r->raw, prf_state, R_BYTES)); - - // Mask upper bits of the MSByte - r->raw[R_BYTES - 1] &= MASK(R_BITS + 8 - (R_BYTES * 8)); - - if(must_be_odd == MUST_BE_ODD) { - make_odd_weight(r); - } - - return SUCCESS; -} - -_INLINE_ int is_new(IN const idx_t *wlist, IN const size_t ctr) +ret_t sample_indices_fisher_yates(OUT idx_t *out, + IN size_t num_indices, + IN idx_t max_idx_val, + IN OUT prf_state_t *prf_state) { - for(size_t i = 0; i < ctr; i++) { - if(wlist[i] == wlist[ctr]) { - return 0; + for (size_t i = num_indices; i-- > 0;) { +#define CWW_RAND_BYTES 4 + uint64_t rand = 0ULL; + GUARD(get_shake256_prf_output((uint8_t *)&rand, prf_state, CWW_RAND_BYTES)); + rand *= (max_idx_val - i); + + // new index l is such that i <= l < max_idx_val + uint32_t l = i + (uint32_t)(rand >> (CWW_RAND_BYTES * 8)); + + // Loop over (the end of) the output array to determine if l is a duplicate + uint32_t is_dup = 0; + for (size_t j = i + 1; j < num_indices; ++j) { + is_dup |= secure_cmp32(l, out[j]); + } + + // if l is a duplicate out[i] gets i else out[i] gets l + // mask is all 1 if l is a duplicate, all 0 else + uint32_t mask = -is_dup; + out[i] = (mask & i) ^ (~mask & l); } - } - return 1; -} - -ret_t generate_indices_mod_z(OUT idx_t * out, - IN const size_t num_indices, - IN const size_t z, - IN OUT aes_ctr_prf_state_t *prf_state) -{ - size_t ctr = 0; - - // Generate num_indices unique (pseudo) random numbers modulo z - do { - GUARD(get_rand_mod_len(&out[ctr], z, prf_state)); - ctr += is_new(out, ctr); - } while(ctr < num_indices); - - return SUCCESS; -} - -// Returns an array of r pseudorandom bits. -// No restrictions exist for the top or bottom bits. -// If the generation requires an odd number, then set must_be_odd = MUST_BE_ODD -ret_t sample_uniform_r_bits(OUT r_t *r, - IN const seed_t * seed, - IN const must_be_odd_t must_be_odd) -{ - // For the seedexpander - DEFER_CLEANUP(aes_ctr_prf_state_t prf_state = {0}, aes_ctr_prf_state_cleanup); - - GUARD(init_aes_ctr_prf_state(&prf_state, MAX_AES_INVOKATION, seed)); - - GUARD(sample_uniform_r_bits_with_fixed_prf_context(r, &prf_state, must_be_odd)); - - return SUCCESS; + return SUCCESS; } ret_t generate_sparse_rep(OUT pad_r_t *r, OUT idx_t *wlist, - IN OUT aes_ctr_prf_state_t *prf_state) + IN OUT prf_state_t *prf_state) { - GUARD(generate_indices_mod_z(wlist, D, R_BITS, prf_state)); + GUARD(sample_indices_fisher_yates(wlist, D, R_BITS, prf_state)); secure_set_bits(r, 0, wlist, D); @@ -153,12 +72,12 @@ ret_t generate_sparse_rep(OUT pad_r_t *r, ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed) { - DEFER_CLEANUP(aes_ctr_prf_state_t prf_state = {0}, aes_ctr_prf_state_cleanup); + DEFER_CLEANUP(prf_state_t prf_state = {0}, clean_shake256_prf_state); - GUARD(init_aes_ctr_prf_state(&prf_state, MAX_AES_INVOKATION, seed)); + GUARD(init_shake256_prf_state(&prf_state, MAX_PRF_INVOCATION, seed)); idx_t wlist[T]; - GUARD(generate_indices_mod_z(wlist, T, N_BITS, &prf_state)); + GUARD(sample_indices_fisher_yates(wlist, T, N_BITS, &prf_state)); // (e0, e1) hold bits 0..R_BITS-1 and R_BITS..2*R_BITS-1 of the error, resp. secure_set_bits(&e->val[0], 0, wlist, T); @@ -170,5 +89,7 @@ ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed) bike_memset(&PE0_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); bike_memset(&PE1_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); + secure_clean((uint8_t *)wlist, sizeof(*wlist)); + return SUCCESS; } diff --git a/crypto_kem/bikel1/m4f/sampling.h b/crypto_kem/bikel1/m4f/sampling.h index 556ab282..5618c810 100644 --- a/crypto_kem/bikel1/m4f/sampling.h +++ b/crypto_kem/bikel1/m4f/sampling.h @@ -3,6 +3,9 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #pragma once @@ -14,7 +17,7 @@ # include #endif -#include "aes_ctr_prf.h" +#include "shake_prf.h" #include "utilities.h" typedef enum @@ -25,15 +28,9 @@ typedef enum void get_seeds(OUT seeds_t *seeds); -// Returns an array of r pseudorandom bits. If an odd -// weight of r is required, set must_be_odd to MUST_BE_ODD. -ret_t sample_uniform_r_bits(OUT r_t *r, - IN const seed_t *seed, - IN must_be_odd_t must_be_odd); - ret_t generate_sparse_rep(OUT pad_r_t *r, OUT idx_t *wlist, - IN OUT aes_ctr_prf_state_t *prf_state); + IN OUT prf_state_t *prf_state); ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed); diff --git a/crypto_kem/bikel1/m4f/sha.h b/crypto_kem/bikel1/m4f/sha.h index 027c087b..4a9ef2e5 100644 --- a/crypto_kem/bikel1/m4f/sha.h +++ b/crypto_kem/bikel1/m4f/sha.h @@ -4,7 +4,8 @@ * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. * - * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. + * Modification: 2023 Till Eifert + * */ #pragma once @@ -30,47 +31,12 @@ bike_static_assert(sizeof(sha384_dgst_t) == SHA384_DGST_BYTES, sha384_dgst_size) typedef sha384_dgst_t sha_dgst_t; CLEANUP_FUNC(sha_dgst, sha_dgst_t) -#if defined(PQM4) || defined(MUPQ) - -#include "sha2.h" +#include "fips202.h" _INLINE_ ret_t sha(OUT sha_dgst_t * dgst, IN const uint32_t byte_len, IN const uint8_t *msg) { - sha384(dgst->u.raw, msg, byte_len); + sha3_384(dgst->u.raw, msg, byte_len); return SUCCESS; } - - -#elif defined(USE_OPENSSL) - -# include "utilities.h" -# include - -_INLINE_ ret_t sha(OUT sha_dgst_t * dgst, - IN const uint32_t byte_len, - IN const uint8_t *msg) -{ - if(SHA384(msg, byte_len, dgst->u.raw) != NULL) { - return SUCCESS; - } - - return FAIL; -} - -#else // USE_OPENSSL - -# define HASH_BLOCK_BYTES 128ULL - -typedef struct sha512_dgst_s { - union { - uint8_t raw[SHA512_DGST_BYTES]; - uint64_t qw[SHA512_DGST_QWORDS]; - } u; -} sha512_dgst_t; -bike_static_assert(sizeof(sha512_dgst_t) == SHA512_DGST_BYTES, sha512_dgst_size); - -ret_t sha(OUT sha_dgst_t *dgst, IN uint32_t byte_len, IN const uint8_t *msg); - -#endif // USE_OPENSSL diff --git a/crypto_kem/bikel1/m4f/shake_prf.c b/crypto_kem/bikel1/m4f/shake_prf.c new file mode 100644 index 00000000..ffc184d4 --- /dev/null +++ b/crypto_kem/bikel1/m4f/shake_prf.c @@ -0,0 +1,65 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0" + * + * This code is maintained by Nir Drucker, Shay Gueron and Dusan Kostic, + * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * + */ + +#include "cleanup.h" +#include "shake_prf.h" +#include "utilities.h" + +ret_t init_shake256_prf_state(OUT shake256_prf_state_t *s, IN size_t max_num_invocations, + IN const seed_t *seed) +{ + if(0 == max_num_invocations) { + BIKE_ERROR(E_SHAKE_PRF_INIT_FAIL); + } + + // Initialize the SHAKE state with the given seed. + shake256_absorb(&s->s, seed->raw, sizeof(*seed)); + + // Initialize the PRF parameters. + s->curr_pos_in_buffer = SHAKE256_RATE; + s->rem_invocations = max_num_invocations; + + return SUCCESS; +} + +ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT shake256_prf_state_t *s, + IN size_t len) +{ + // Check if the maximum number of SHAKE invocations is reached. + if (s->rem_invocations == 0) + { + BIKE_ERROR(E_SHAKE_OVER_USED); + } + + // When |len| is smaller then use what's left in the buffer, + // there is no need for additional SHAKE256 invocations. + if((len + s->curr_pos_in_buffer) <= SHAKE256_RATE) { + bike_memcpy(out, &s->buffer[s->curr_pos_in_buffer], len); + s->curr_pos_in_buffer += len; + + return SUCCESS; + } + + // Generate one block (SHAKE256_RATE bytes) of random data with SHAKE256. + shake256_squeezeblocks(s->buffer, 1, &s->s); + + // Copy |len| bytes to the output, set the new buffer position indicator, + // and update the remaining allowable number of SHAKE invocations. + bike_memcpy(out, s->buffer, len); + s->curr_pos_in_buffer = len; + s->rem_invocations -= 1; + + return SUCCESS; +} + +void clean_shake256_prf_state(IN OUT shake256_prf_state_t *s) +{ + secure_clean((uint8_t*)s, sizeof(*s)); +} diff --git a/crypto_kem/bikel1/m4f/shake_prf.h b/crypto_kem/bikel1/m4f/shake_prf.h new file mode 100644 index 00000000..0d6926ec --- /dev/null +++ b/crypto_kem/bikel1/m4f/shake_prf.h @@ -0,0 +1,35 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0" + * + * Written by Nir Drucker, Shay Gueron and Dusan Kostic, + * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * + */ + +#pragma once + +#include "defs.h" +#include "error.h" +#include "types.h" +#include "fips202.h" + +typedef struct shake256_prf_state_s { + shake256ctx s; + uint8_t buffer[SHAKE256_RATE]; + size_t curr_pos_in_buffer; + size_t rem_invocations; +} shake256_prf_state_t; + +typedef shake256_prf_state_t prf_state_t; + +#define MAX_PRF_INVOCATION (MASK(32)) + +// Methods for interacting with the PRFs. +ret_t init_shake256_prf_state(OUT prf_state_t *s, IN size_t max_num_invocations, + IN const seed_t *seed); + +ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT prf_state_t *s, IN size_t len); + +void clean_shake256_prf_state(IN OUT prf_state_t *s); diff --git a/crypto_kem/bikel3/m4f/api.h b/crypto_kem/bikel3/m4f/api.h index b2281850..304366f2 100644 --- a/crypto_kem/bikel3/m4f/api.h +++ b/crypto_kem/bikel3/m4f/api.h @@ -3,11 +3,15 @@ * * Written by Nir Drucker and Shay Gueron * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #pragma once #include "types.h" +#include "crypto_kem.h" #define CRYPTO_SECRETKEYBYTES sizeof(sk_t) #define CRYPTO_PUBLICKEYBYTES sizeof(pk_t) diff --git a/crypto_kem/bikel3/m4f/defs.h b/crypto_kem/bikel3/m4f/defs.h index 59c29c38..8dda44e1 100644 --- a/crypto_kem/bikel3/m4f/defs.h +++ b/crypto_kem/bikel3/m4f/defs.h @@ -3,6 +3,10 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert + * */ #pragma once @@ -26,7 +30,8 @@ // In asm the symbols '==' and '?' are not allowed. Therefore, if using // divide_and_ceil in asm files, we must ensure with static_assert its validity. -#if(__cplusplus >= 201103L) || defined(static_assert) +//#if(__cplusplus >= 201103L) || defined(static_assert) +#if defined(static_assert) # define bike_static_assert(COND, MSG) static_assert(COND, "MSG") #else # define bike_static_assert(COND, MSG) \ @@ -34,7 +39,7 @@ #endif // Divide by the divider and round up to next integer -#define DIVIDE_AND_CEIL(x, divider) (((x) + (divider)) / (divider)) +#define DIVIDE_AND_CEIL(x, divider) (((x) + (divider) - 1) / (divider)) // Bit manipulations // Linux Assemblies, except for Ubuntu, cannot understand what ULL mean. diff --git a/crypto_kem/bikel3/m4f/error.h b/crypto_kem/bikel3/m4f/error.h index f19a2366..580a9fe2 100644 --- a/crypto_kem/bikel3/m4f/error.h +++ b/crypto_kem/bikel3/m4f/error.h @@ -5,6 +5,7 @@ * AWS Cryptographic Algorithms Group. * * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert * */ @@ -22,12 +23,13 @@ enum _bike_err E_DECODING_FAILURE = 1, E_AES_CTR_PRF_INIT_FAIL = 2, E_AES_OVER_USED = 3, - EXTERNAL_LIB_ERROR_OPENSSL = 4 + EXTERNAL_LIB_ERROR_OPENSSL = 4, + E_SHAKE_PRF_INIT_FAIL = 5, + E_SHAKE_OVER_USED = 6 }; typedef enum _bike_err _bike_err_t; -//extern __thread _bike_err_t bike_errno; extern _bike_err_t bike_errno; #define BIKE_ERROR(x) \ do { \ diff --git a/crypto_kem/bikel3/m4f/gf2x.h b/crypto_kem/bikel3/m4f/gf2x.h index df6bc3b1..f4cdb53a 100644 --- a/crypto_kem/bikel3/m4f/gf2x.h +++ b/crypto_kem/bikel3/m4f/gf2x.h @@ -13,16 +13,12 @@ _INLINE_ void gf2x_mod_add(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b) { - REG_T va, vb; const uint64_t *a_qwords = (const uint64_t *)a; const uint64_t *b_qwords = (const uint64_t *)b; uint64_t * c_qwords = (uint64_t *)c; - for(size_t i = 0; i < R_PADDED_QWORDS; i += REG_QWORDS) { - va = LOAD(&a_qwords[i]); - vb = LOAD(&b_qwords[i]); - - STORE(&c_qwords[i], va ^ vb); + for(size_t i = 0; i < R_PADDED_QWORDS; i++) { + c_qwords[i] = a_qwords[i] ^ b_qwords[i]; } } diff --git a/crypto_kem/bikel3/m4f/kem.c b/crypto_kem/bikel3/m4f/kem.c index 54c14189..bd95995f 100644 --- a/crypto_kem/bikel3/m4f/kem.c +++ b/crypto_kem/bikel3/m4f/kem.c @@ -5,10 +5,11 @@ * AWS Cryptographic Algorithms Group. * * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz + * Modification: 2023 Till Eifert * */ - #include "crypto_kem.h" +#include "crypto_kem.h" #include "decode.h" #include "gf2x.h" #include "sampling.h" @@ -95,7 +96,7 @@ _INLINE_ ret_t encrypt(OUT ct_t *ct, // ct = pk * e1 + e0 //gf2x_mod_mul(&p_ct, &e->val[1], &p_pk); //gf2x_mod_add(&p_ct, &p_ct, &e->val[0]); - ring_mul(&p_ct, &e->val[1], &p_pk); +ring_mul(&p_ct, &e->val[1], &p_pk); ring_add((r_t*)&p_ct, (r_t*)&p_ct, (const r_t*)&e->val[0]); @@ -150,11 +151,11 @@ int crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) // The randomness of the key generation DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup); - // An AES_PRF state for the secret key - DEFER_CLEANUP(aes_ctr_prf_state_t h_prf_state = {0}, aes_ctr_prf_state_cleanup); - get_seeds(&seeds); - GUARD(init_aes_ctr_prf_state(&h_prf_state, MAX_AES_INVOKATION, &seeds.seed[0])); + // A SHAKE_PRF state for the secret key + DEFER_CLEANUP(prf_state_t h_prf_state = {0}, clean_shake256_prf_state); + + GUARD(init_shake256_prf_state(&h_prf_state, MAX_PRF_INVOCATION, &seeds.seed[0])); // Generate the secret key (h0, h1) with weight w/2 GUARD(generate_sparse_rep(&h0, l_sk.wlist[0].val, &h_prf_state)); @@ -166,7 +167,7 @@ int crypto_kem_keypair(OUT unsigned char *pk, OUT unsigned char *sk) // Calculate the public key gf2x_mod_inv(&h0inv, &h0); //gf2x_mod_mul(&h, &h1, &h0inv); - ring_mul(&h, &h1, &h0inv); +ring_mul(&h, &h1, &h0inv); // Fill the secret key data structure with contents - cancel the padding l_sk.bin[0] = h0.val; @@ -236,35 +237,34 @@ int crypto_kem_dec(OUT unsigned char * ss, IN const unsigned char *sk) { // Public values, does not require a cleanup on exit - ct_t *l_ct = (ct_t*)ct; - - //DEFER_CLEANUP(aligned_sk_t l_sk, sk_cleanup); - aligned_sk_t *l_sk = (aligned_sk_t*)sk; - DEFER_CLEANUP(e_t e, e_cleanup); - - // Copy the data from the input buffers. This is required in order to avoid - // alignment issues on non x86_64 processors. - //bike_memcpy(&l_ct, ct, sizeof(l_ct)); - //bike_memcpy(&l_sk, sk, sizeof(l_sk)); - - // Decode and on success check if |e|=T (all in constant-time) - volatile uint32_t success_cond = (decode(&e, l_ct, l_sk) == SUCCESS); - //success_cond &= secure_cmp32(T, r_bits_vector_weight(&e.val[0]) + - // r_bits_vector_weight(&e.val[1])); + ct_t l_ct; DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup); DEFER_CLEANUP(ss_t l_ss, ss_cleanup); + DEFER_CLEANUP(aligned_sk_t l_sk, sk_cleanup); + DEFER_CLEANUP(e_t e, e_cleanup); DEFER_CLEANUP(m_t m_prime, m_cleanup); DEFER_CLEANUP(pad_e_t e_tmp, pad_e_cleanup); DEFER_CLEANUP(pad_e_t e_prime, pad_e_cleanup); + // Copy the data from the input buffers. This is required in order to avoid + // alignment issues on non x86_64 processors. + bike_memcpy(&l_ct, ct, sizeof(l_ct)); + bike_memcpy(&l_sk, sk, sizeof(l_sk)); + // Generate a random error vector to be used in case of decoding failure // (Note: possibly, a "fixed" zeroed error vector could suffice too, // and serve this generation) // get_seeds(&seeds); -// GUARD(generate_error_vector(&e_prime, &seeds.seed[0])); - memset(&e_prime,0,sizeof(e_prime)); + //GUARD(generate_error_vector(&e_prime, &seeds.seed[0])); +// generate_error_vector(&e_prime, &seeds.seed[0]); + memset( &e_prime, 0 , sizeof(e_prime) ); + + // Decode and on success check if |e|=T (all in constant-time) + volatile uint32_t success_cond = (decode(&e, &l_ct, &l_sk) == SUCCESS); +// success_cond &= secure_cmp32(T, r_bits_vector_weight(&e.val[0]) + +// r_bits_vector_weight(&e.val[1])); // Set appropriate error based on the success condition uint8_t mask; // = ~secure_l32_mask(0, success_cond); @@ -277,7 +277,7 @@ int crypto_kem_dec(OUT unsigned char * ss, PE1_RAW(&e_prime)[i] = E1_RAW(&e)[i]; } - GUARD(reencrypt(&m_prime, &e_prime, l_ct)); + GUARD(reencrypt(&m_prime, &e_prime, &l_ct)); // Check if H(m') is equal to (e0', e1') // (in constant-time) @@ -289,11 +289,11 @@ int crypto_kem_dec(OUT unsigned char * ss, mask = secure_l32_mask(0, success_cond); for(size_t i = 0; i < M_BYTES; i++) { m_prime.raw[i] &= u8_barrier(~mask); - m_prime.raw[i] |= (u8_barrier(mask) & l_sk->sigma.raw[i]); + m_prime.raw[i] |= (u8_barrier(mask) & l_sk.sigma.raw[i]); } // Generate the shared secret - GUARD(function_k(&l_ss, &m_prime, l_ct)); + GUARD(function_k(&l_ss, &m_prime, &l_ct)); // Copy the data into the output buffer bike_memcpy(ss, &l_ss, sizeof(l_ss)); diff --git a/crypto_kem/bikel3/m4f/sampling.c b/crypto_kem/bikel3/m4f/sampling.c index 307eab0c..0b9dc34c 100644 --- a/crypto_kem/bikel3/m4f/sampling.c +++ b/crypto_kem/bikel3/m4f/sampling.c @@ -3,11 +3,15 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #include #include "sampling.h" +#include "cleanup.h" void get_seeds(OUT seeds_t *seeds) { @@ -25,126 +29,41 @@ void get_seeds(OUT seeds_t *seeds) } } -// BSR returns ceil(log2(val)) -_INLINE_ uint8_t bit_scan_reverse_vartime(IN uint64_t val) -{ - // index is always smaller than 64 - uint8_t index = 0; - - while(val != 0) { - val >>= 1; - index++; - } - - return index; -} - -_INLINE_ ret_t get_rand_mod_len(OUT uint32_t * rand_pos, - IN const uint32_t len, - IN OUT aes_ctr_prf_state_t *prf_state) -{ - const uint64_t mask = MASK(bit_scan_reverse_vartime(len)); - - do { - // Generate a 32 bits (pseudo) random value. - // This can be optimized to take only 16 bits. - GUARD(aes_ctr_prf((uint8_t *)rand_pos, prf_state, sizeof(*rand_pos))); - - // Mask relevant bits only - (*rand_pos) &= mask; - - // Break if a number that is smaller than len is found - if((*rand_pos) < len) { - break; - } - - } while(1 == 1); - - return SUCCESS; -} - -_INLINE_ void make_odd_weight(IN OUT r_t *r) -{ - if(((r_bits_vector_weight(r) % 2) == 1)) { - // Already odd - return; - } - - r->raw[0] ^= 1; -} - -// Returns an array of r pseudorandom bits. -// No restrictions exist for the top or bottom bits. -// If the generation requires an odd number, then set must_be_odd=1. -// The function uses the provided prf context. -ret_t sample_uniform_r_bits_with_fixed_prf_context( - OUT r_t *r, - IN OUT aes_ctr_prf_state_t *prf_state, - IN const must_be_odd_t must_be_odd) -{ - // Generate random data - GUARD(aes_ctr_prf(r->raw, prf_state, R_BYTES)); - - // Mask upper bits of the MSByte - r->raw[R_BYTES - 1] &= MASK(R_BITS + 8 - (R_BYTES * 8)); - - if(must_be_odd == MUST_BE_ODD) { - make_odd_weight(r); - } - - return SUCCESS; -} - -_INLINE_ int is_new(IN const idx_t *wlist, IN const size_t ctr) +ret_t sample_indices_fisher_yates(OUT idx_t *out, + IN size_t num_indices, + IN idx_t max_idx_val, + IN OUT prf_state_t *prf_state) { - for(size_t i = 0; i < ctr; i++) { - if(wlist[i] == wlist[ctr]) { - return 0; + for (size_t i = num_indices; i-- > 0;) { +#define CWW_RAND_BYTES 4 + uint64_t rand = 0ULL; + GUARD(get_shake256_prf_output((uint8_t *)&rand, prf_state, CWW_RAND_BYTES)); + rand *= (max_idx_val - i); + + // new index l is such that i <= l < max_idx_val + uint32_t l = i + (uint32_t)(rand >> (CWW_RAND_BYTES * 8)); + + // Loop over (the end of) the output array to determine if l is a duplicate + uint32_t is_dup = 0; + for (size_t j = i + 1; j < num_indices; ++j) { + is_dup |= secure_cmp32(l, out[j]); + } + + // if l is a duplicate out[i] gets i else out[i] gets l + // mask is all 1 if l is a duplicate, all 0 else + uint32_t mask = -is_dup; + out[i] = (mask & i) ^ (~mask & l); } - } - return 1; -} - -ret_t generate_indices_mod_z(OUT idx_t * out, - IN const size_t num_indices, - IN const size_t z, - IN OUT aes_ctr_prf_state_t *prf_state) -{ - size_t ctr = 0; - - // Generate num_indices unique (pseudo) random numbers modulo z - do { - GUARD(get_rand_mod_len(&out[ctr], z, prf_state)); - ctr += is_new(out, ctr); - } while(ctr < num_indices); - - return SUCCESS; -} - -// Returns an array of r pseudorandom bits. -// No restrictions exist for the top or bottom bits. -// If the generation requires an odd number, then set must_be_odd = MUST_BE_ODD -ret_t sample_uniform_r_bits(OUT r_t *r, - IN const seed_t * seed, - IN const must_be_odd_t must_be_odd) -{ - // For the seedexpander - DEFER_CLEANUP(aes_ctr_prf_state_t prf_state = {0}, aes_ctr_prf_state_cleanup); - - GUARD(init_aes_ctr_prf_state(&prf_state, MAX_AES_INVOKATION, seed)); - - GUARD(sample_uniform_r_bits_with_fixed_prf_context(r, &prf_state, must_be_odd)); - - return SUCCESS; + return SUCCESS; } ret_t generate_sparse_rep(OUT pad_r_t *r, OUT idx_t *wlist, - IN OUT aes_ctr_prf_state_t *prf_state) + IN OUT prf_state_t *prf_state) { - GUARD(generate_indices_mod_z(wlist, D, R_BITS, prf_state)); + GUARD(sample_indices_fisher_yates(wlist, D, R_BITS, prf_state)); secure_set_bits(r, 0, wlist, D); @@ -153,12 +72,12 @@ ret_t generate_sparse_rep(OUT pad_r_t *r, ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed) { - DEFER_CLEANUP(aes_ctr_prf_state_t prf_state = {0}, aes_ctr_prf_state_cleanup); + DEFER_CLEANUP(prf_state_t prf_state = {0}, clean_shake256_prf_state); - GUARD(init_aes_ctr_prf_state(&prf_state, MAX_AES_INVOKATION, seed)); + GUARD(init_shake256_prf_state(&prf_state, MAX_PRF_INVOCATION, seed)); idx_t wlist[T]; - GUARD(generate_indices_mod_z(wlist, T, N_BITS, &prf_state)); + GUARD(sample_indices_fisher_yates(wlist, T, N_BITS, &prf_state)); // (e0, e1) hold bits 0..R_BITS-1 and R_BITS..2*R_BITS-1 of the error, resp. secure_set_bits(&e->val[0], 0, wlist, T); @@ -170,5 +89,7 @@ ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed) bike_memset(&PE0_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); bike_memset(&PE1_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); + secure_clean((uint8_t *)wlist, sizeof(*wlist)); + return SUCCESS; } diff --git a/crypto_kem/bikel3/m4f/sampling.h b/crypto_kem/bikel3/m4f/sampling.h index 556ab282..5618c810 100644 --- a/crypto_kem/bikel3/m4f/sampling.h +++ b/crypto_kem/bikel3/m4f/sampling.h @@ -3,6 +3,9 @@ * * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * */ #pragma once @@ -14,7 +17,7 @@ # include #endif -#include "aes_ctr_prf.h" +#include "shake_prf.h" #include "utilities.h" typedef enum @@ -25,15 +28,9 @@ typedef enum void get_seeds(OUT seeds_t *seeds); -// Returns an array of r pseudorandom bits. If an odd -// weight of r is required, set must_be_odd to MUST_BE_ODD. -ret_t sample_uniform_r_bits(OUT r_t *r, - IN const seed_t *seed, - IN must_be_odd_t must_be_odd); - ret_t generate_sparse_rep(OUT pad_r_t *r, OUT idx_t *wlist, - IN OUT aes_ctr_prf_state_t *prf_state); + IN OUT prf_state_t *prf_state); ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed); diff --git a/crypto_kem/bikel3/m4f/sha.h b/crypto_kem/bikel3/m4f/sha.h index 027c087b..4a9ef2e5 100644 --- a/crypto_kem/bikel3/m4f/sha.h +++ b/crypto_kem/bikel3/m4f/sha.h @@ -4,7 +4,8 @@ * Written by Nir Drucker, Shay Gueron and Dusan Kostic, * AWS Cryptographic Algorithms Group. * - * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. + * Modification: 2023 Till Eifert + * */ #pragma once @@ -30,47 +31,12 @@ bike_static_assert(sizeof(sha384_dgst_t) == SHA384_DGST_BYTES, sha384_dgst_size) typedef sha384_dgst_t sha_dgst_t; CLEANUP_FUNC(sha_dgst, sha_dgst_t) -#if defined(PQM4) || defined(MUPQ) - -#include "sha2.h" +#include "fips202.h" _INLINE_ ret_t sha(OUT sha_dgst_t * dgst, IN const uint32_t byte_len, IN const uint8_t *msg) { - sha384(dgst->u.raw, msg, byte_len); + sha3_384(dgst->u.raw, msg, byte_len); return SUCCESS; } - - -#elif defined(USE_OPENSSL) - -# include "utilities.h" -# include - -_INLINE_ ret_t sha(OUT sha_dgst_t * dgst, - IN const uint32_t byte_len, - IN const uint8_t *msg) -{ - if(SHA384(msg, byte_len, dgst->u.raw) != NULL) { - return SUCCESS; - } - - return FAIL; -} - -#else // USE_OPENSSL - -# define HASH_BLOCK_BYTES 128ULL - -typedef struct sha512_dgst_s { - union { - uint8_t raw[SHA512_DGST_BYTES]; - uint64_t qw[SHA512_DGST_QWORDS]; - } u; -} sha512_dgst_t; -bike_static_assert(sizeof(sha512_dgst_t) == SHA512_DGST_BYTES, sha512_dgst_size); - -ret_t sha(OUT sha_dgst_t *dgst, IN uint32_t byte_len, IN const uint8_t *msg); - -#endif // USE_OPENSSL diff --git a/crypto_kem/bikel3/m4f/shake_prf.c b/crypto_kem/bikel3/m4f/shake_prf.c new file mode 100644 index 00000000..ffc184d4 --- /dev/null +++ b/crypto_kem/bikel3/m4f/shake_prf.c @@ -0,0 +1,65 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0" + * + * This code is maintained by Nir Drucker, Shay Gueron and Dusan Kostic, + * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * + */ + +#include "cleanup.h" +#include "shake_prf.h" +#include "utilities.h" + +ret_t init_shake256_prf_state(OUT shake256_prf_state_t *s, IN size_t max_num_invocations, + IN const seed_t *seed) +{ + if(0 == max_num_invocations) { + BIKE_ERROR(E_SHAKE_PRF_INIT_FAIL); + } + + // Initialize the SHAKE state with the given seed. + shake256_absorb(&s->s, seed->raw, sizeof(*seed)); + + // Initialize the PRF parameters. + s->curr_pos_in_buffer = SHAKE256_RATE; + s->rem_invocations = max_num_invocations; + + return SUCCESS; +} + +ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT shake256_prf_state_t *s, + IN size_t len) +{ + // Check if the maximum number of SHAKE invocations is reached. + if (s->rem_invocations == 0) + { + BIKE_ERROR(E_SHAKE_OVER_USED); + } + + // When |len| is smaller then use what's left in the buffer, + // there is no need for additional SHAKE256 invocations. + if((len + s->curr_pos_in_buffer) <= SHAKE256_RATE) { + bike_memcpy(out, &s->buffer[s->curr_pos_in_buffer], len); + s->curr_pos_in_buffer += len; + + return SUCCESS; + } + + // Generate one block (SHAKE256_RATE bytes) of random data with SHAKE256. + shake256_squeezeblocks(s->buffer, 1, &s->s); + + // Copy |len| bytes to the output, set the new buffer position indicator, + // and update the remaining allowable number of SHAKE invocations. + bike_memcpy(out, s->buffer, len); + s->curr_pos_in_buffer = len; + s->rem_invocations -= 1; + + return SUCCESS; +} + +void clean_shake256_prf_state(IN OUT shake256_prf_state_t *s) +{ + secure_clean((uint8_t*)s, sizeof(*s)); +} diff --git a/crypto_kem/bikel3/m4f/shake_prf.h b/crypto_kem/bikel3/m4f/shake_prf.h new file mode 100644 index 00000000..0d6926ec --- /dev/null +++ b/crypto_kem/bikel3/m4f/shake_prf.h @@ -0,0 +1,35 @@ +/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0" + * + * Written by Nir Drucker, Shay Gueron and Dusan Kostic, + * AWS Cryptographic Algorithms Group. + * + * Modification: 2023 Till Eifert + * + */ + +#pragma once + +#include "defs.h" +#include "error.h" +#include "types.h" +#include "fips202.h" + +typedef struct shake256_prf_state_s { + shake256ctx s; + uint8_t buffer[SHAKE256_RATE]; + size_t curr_pos_in_buffer; + size_t rem_invocations; +} shake256_prf_state_t; + +typedef shake256_prf_state_t prf_state_t; + +#define MAX_PRF_INVOCATION (MASK(32)) + +// Methods for interacting with the PRFs. +ret_t init_shake256_prf_state(OUT prf_state_t *s, IN size_t max_num_invocations, + IN const seed_t *seed); + +ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT prf_state_t *s, IN size_t len); + +void clean_shake256_prf_state(IN OUT prf_state_t *s); From 5642fd91251272759870f84d5bc92402b2bee216 Mon Sep 17 00:00:00 2001 From: Till Eifert Date: Thu, 26 Oct 2023 16:20:34 +0200 Subject: [PATCH 004/107] BIKE: minor changes to reduce compiler warnings --- crypto_kem/bikel1/m4f/asm.h | 5 +++++ crypto_kem/bikel1/m4f/encode.c | 5 +++-- crypto_kem/bikel1/m4f/gf2x_inv.c | 5 ++++- crypto_kem/bikel1/m4f/rotr_cshift_12323.c | 3 +++ crypto_kem/bikel3/m4f/asm.h | 5 +++++ crypto_kem/bikel3/m4f/encode.c | 5 +++-- crypto_kem/bikel3/m4f/gf2x_inv.c | 5 ++++- crypto_kem/bikel3/m4f/rotr_cshift_24659.c | 3 +++ 8 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 crypto_kem/bikel1/m4f/asm.h create mode 100644 crypto_kem/bikel3/m4f/asm.h diff --git a/crypto_kem/bikel1/m4f/asm.h b/crypto_kem/bikel1/m4f/asm.h new file mode 100644 index 00000000..95a4363b --- /dev/null +++ b/crypto_kem/bikel1/m4f/asm.h @@ -0,0 +1,5 @@ +// Created by Till Eifert +// public domain + +void cshift_asm (uint32_t *array, int s); +void shiftright_small_umlal (uint32_t *array1, int s, int a); \ No newline at end of file diff --git a/crypto_kem/bikel1/m4f/encode.c b/crypto_kem/bikel1/m4f/encode.c index 4d0ca6fd..dd9d2292 100644 --- a/crypto_kem/bikel1/m4f/encode.c +++ b/crypto_kem/bikel1/m4f/encode.c @@ -1,4 +1,5 @@ // Implemented by Ming-Shing Chen, Tung Chou and Markus Krausz. +// Modified by Till Eifert // public domain #include "encode.h" @@ -8,8 +9,8 @@ void encode_to_gft( uint32_t * out , const uint32_t * in ) { const uint32_t * b = in; uint32_t g0,g1,g2,g3, g4,g5,g6,g7, g8,g9,g10,g11; -uint32_t f0,f1,f2,f3, f4,f5,f6,f7, f8,f9,f10,f11; -uint32_t f12,f13,f14,f15, f16,f17,f18,f19, f20,f21,f22,f23, f24,f25,f26,f27, f28,f29,f30,f31; +uint32_t f0,f1,f2, f4,f5,f6,f7, f8,f9,f10,f11; +uint32_t f12,f14,f15, f16,f17,f18,f19, f20,f22,f23, f24,f26,f27, f28,f29,f30,f31; // final state: [{0, 1, 2, 4, 8, 11}, {1, 4, 7, 9, 12, 14}, {3, 4, 5, 8, 9, 12, 13, 14}, {1, 2, 3, 7, 8, 9, 10, 12, 14}, {1, 2, 3, 4, 6, 7, 8, 9, 11}, {2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14}, {2, 5, 6, 8, 12, 13, 15}, {1, 2, 3, 9, 10, 11, 15}, {1, 12, 4, 5}, {1, 2, 3, 4, 5, 6, 7, 9, 11, 15}, {1, 4, 5, 8, 10, 11, 12}, {1, 3, 5, 6, 7, 8, 9, 10, 11, 14}, {2, 4, 5, 6, 7, 9, 10, 12, 13, 15}, {1, 3, 7, 8, 9, 11, 12, 14, 15}, {4, 5, 9, 10, 11, 12, 13, 15}, {2, 5, 6, 7, 9, 10, 12, 13, 14, 15}, {1, 3, 5, 9}, {13, 5, 15}, {9, 13, 5, 15}, {3, 9, 11, 13, 15}, {9, 3, 5, 7}, {3, 5, 7, 9, 11, 13, 15}, {9, 3, 13, 7}, {11, 3}, {13, 5}, {3, 5, 7}, {9, 13, 11, 5}, {9, 11, 15, 7}, {3, 5, 7, 11, 13}, {9, 13, 15}, {13, 11, 5}, {3, 7, 11, 13, 15}] // i = 0 diff --git a/crypto_kem/bikel1/m4f/gf2x_inv.c b/crypto_kem/bikel1/m4f/gf2x_inv.c index cb73c1cc..8325b331 100644 --- a/crypto_kem/bikel1/m4f/gf2x_inv.c +++ b/crypto_kem/bikel1/m4f/gf2x_inv.c @@ -5,6 +5,8 @@ * AWS Cryptographic Algorithms Group. * * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. + * Modification: 2023 Till Eifert + * * * The inversion algorithm in this file is based on: * [1] Nir Drucker, Shay Gueron, and Dusan Kostic. 2020. "Fast polynomial @@ -32,6 +34,7 @@ _INLINE_ void repeated_squaring(OUT pad_r_t *c, for(size_t i = 0; i < num_sqrs; i++) { #if defined(_MY_SQU_) ring_squ(c , c); + (void) sec_buf; #else gf2x_mod_sqr_in_place(c, sec_buf); #endif @@ -150,7 +153,7 @@ void gf2x_mod_inv(OUT pad_r_t *c, IN const pad_r_t *a) const size_t exp0_k[MAX_I] = {EXP0_K_VALS}; const size_t exp0_l[MAX_I] = {EXP0_L_VALS}; const size_t exp1_k[MAX_I] = {EXP1_K_VALS}; - const size_t exp1_l[MAX_I] = {EXP1_L_VALS}; + // const size_t exp1_l[MAX_I] = {EXP1_L_VALS}; #if defined(_ITOH_TSUJII_) DEFER_CLEANUP(mul_internal_t ta = {0}, mul_internal_cleanup); diff --git a/crypto_kem/bikel1/m4f/rotr_cshift_12323.c b/crypto_kem/bikel1/m4f/rotr_cshift_12323.c index a640e067..3675dae3 100644 --- a/crypto_kem/bikel1/m4f/rotr_cshift_12323.c +++ b/crypto_kem/bikel1/m4f/rotr_cshift_12323.c @@ -1,10 +1,13 @@ // Implemented by Ming-Shing Chen, Tung Chou and Markus Krausz. +// Modified by Till Eifert // public domain #include #define r 12323 #include "run_config.h" +#include "rotr_cshift.h" +#include "asm.h" static inline uint32_t bit_mask(uint32_t s,int i) { return -((s>>i)&1); } diff --git a/crypto_kem/bikel3/m4f/asm.h b/crypto_kem/bikel3/m4f/asm.h new file mode 100644 index 00000000..95a4363b --- /dev/null +++ b/crypto_kem/bikel3/m4f/asm.h @@ -0,0 +1,5 @@ +// Created by Till Eifert +// public domain + +void cshift_asm (uint32_t *array, int s); +void shiftright_small_umlal (uint32_t *array1, int s, int a); \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/encode.c b/crypto_kem/bikel3/m4f/encode.c index 4d0ca6fd..dd9d2292 100644 --- a/crypto_kem/bikel3/m4f/encode.c +++ b/crypto_kem/bikel3/m4f/encode.c @@ -1,4 +1,5 @@ // Implemented by Ming-Shing Chen, Tung Chou and Markus Krausz. +// Modified by Till Eifert // public domain #include "encode.h" @@ -8,8 +9,8 @@ void encode_to_gft( uint32_t * out , const uint32_t * in ) { const uint32_t * b = in; uint32_t g0,g1,g2,g3, g4,g5,g6,g7, g8,g9,g10,g11; -uint32_t f0,f1,f2,f3, f4,f5,f6,f7, f8,f9,f10,f11; -uint32_t f12,f13,f14,f15, f16,f17,f18,f19, f20,f21,f22,f23, f24,f25,f26,f27, f28,f29,f30,f31; +uint32_t f0,f1,f2, f4,f5,f6,f7, f8,f9,f10,f11; +uint32_t f12,f14,f15, f16,f17,f18,f19, f20,f22,f23, f24,f26,f27, f28,f29,f30,f31; // final state: [{0, 1, 2, 4, 8, 11}, {1, 4, 7, 9, 12, 14}, {3, 4, 5, 8, 9, 12, 13, 14}, {1, 2, 3, 7, 8, 9, 10, 12, 14}, {1, 2, 3, 4, 6, 7, 8, 9, 11}, {2, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14}, {2, 5, 6, 8, 12, 13, 15}, {1, 2, 3, 9, 10, 11, 15}, {1, 12, 4, 5}, {1, 2, 3, 4, 5, 6, 7, 9, 11, 15}, {1, 4, 5, 8, 10, 11, 12}, {1, 3, 5, 6, 7, 8, 9, 10, 11, 14}, {2, 4, 5, 6, 7, 9, 10, 12, 13, 15}, {1, 3, 7, 8, 9, 11, 12, 14, 15}, {4, 5, 9, 10, 11, 12, 13, 15}, {2, 5, 6, 7, 9, 10, 12, 13, 14, 15}, {1, 3, 5, 9}, {13, 5, 15}, {9, 13, 5, 15}, {3, 9, 11, 13, 15}, {9, 3, 5, 7}, {3, 5, 7, 9, 11, 13, 15}, {9, 3, 13, 7}, {11, 3}, {13, 5}, {3, 5, 7}, {9, 13, 11, 5}, {9, 11, 15, 7}, {3, 5, 7, 11, 13}, {9, 13, 15}, {13, 11, 5}, {3, 7, 11, 13, 15}] // i = 0 diff --git a/crypto_kem/bikel3/m4f/gf2x_inv.c b/crypto_kem/bikel3/m4f/gf2x_inv.c index cb73c1cc..8325b331 100644 --- a/crypto_kem/bikel3/m4f/gf2x_inv.c +++ b/crypto_kem/bikel3/m4f/gf2x_inv.c @@ -5,6 +5,8 @@ * AWS Cryptographic Algorithms Group. * * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. + * Modification: 2023 Till Eifert + * * * The inversion algorithm in this file is based on: * [1] Nir Drucker, Shay Gueron, and Dusan Kostic. 2020. "Fast polynomial @@ -32,6 +34,7 @@ _INLINE_ void repeated_squaring(OUT pad_r_t *c, for(size_t i = 0; i < num_sqrs; i++) { #if defined(_MY_SQU_) ring_squ(c , c); + (void) sec_buf; #else gf2x_mod_sqr_in_place(c, sec_buf); #endif @@ -150,7 +153,7 @@ void gf2x_mod_inv(OUT pad_r_t *c, IN const pad_r_t *a) const size_t exp0_k[MAX_I] = {EXP0_K_VALS}; const size_t exp0_l[MAX_I] = {EXP0_L_VALS}; const size_t exp1_k[MAX_I] = {EXP1_K_VALS}; - const size_t exp1_l[MAX_I] = {EXP1_L_VALS}; + // const size_t exp1_l[MAX_I] = {EXP1_L_VALS}; #if defined(_ITOH_TSUJII_) DEFER_CLEANUP(mul_internal_t ta = {0}, mul_internal_cleanup); diff --git a/crypto_kem/bikel3/m4f/rotr_cshift_24659.c b/crypto_kem/bikel3/m4f/rotr_cshift_24659.c index 7b5e9184..af43608f 100644 --- a/crypto_kem/bikel3/m4f/rotr_cshift_24659.c +++ b/crypto_kem/bikel3/m4f/rotr_cshift_24659.c @@ -1,10 +1,13 @@ // Implemented by Ming-Shing Chen, Tung Chou and Markus Krausz. +// Modified by Till Eifert // public domain #include #define r 24659 #include "run_config.h" +#include "rotr_cshift.h" +#include "asm.h" static inline uint32_t bit_mask(uint32_t s,int i) { return -((s>>i)&1); } From e21677ce496e4b5be3e9b2f56abac298d07d3a28 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 27 Oct 2023 15:21:41 +0800 Subject: [PATCH 005/107] output something if testvectors pass --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index cdf538c8..205a463b 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit cdf538c8adbb7dc2ab515bbf203f54ab2552dfc7 +Subproject commit 205a463b95f6e5b0187bf81586d77739ad906b8b From 6ea87b6e8b3a67e85270b878d85c998aad22b30f Mon Sep 17 00:00:00 2001 From: Till Eifert Date: Thu, 26 Oct 2023 17:22:43 +0200 Subject: [PATCH 006/107] BIKE remove outdated files (aes) and use symlinks for duplicate files between bike level 1 and bike level 3 --- crypto_kem/bikel1/m4f/aes_ctr_prf.c | 97 --------- crypto_kem/bikel1/m4f/aes_ctr_prf.h | 46 ----- crypto_kem/bikel1/m4f/bike_aes.h | 112 ---------- crypto_kem/bikel3/m4f/LICENSE | 176 +--------------- crypto_kem/bikel3/m4f/NOTICE | 2 +- crypto_kem/bikel3/m4f/aes_ctr_prf.c | 97 --------- crypto_kem/bikel3/m4f/aes_ctr_prf.h | 46 ----- crypto_kem/bikel3/m4f/api.h | 20 +- crypto_kem/bikel3/m4f/bike_aes.h | 111 ---------- crypto_kem/bikel3/m4f/bike_defs.h | 95 +-------- crypto_kem/bikel3/m4f/cleanup.h | 82 +------- crypto_kem/bikel3/m4f/crypto_kem.h | 31 +-- crypto_kem/bikel3/m4f/decode.h | 42 +--- crypto_kem/bikel3/m4f/error.c | 15 +- crypto_kem/bikel3/m4f/error.h | 39 +--- crypto_kem/bikel3/m4f/gf2x.h | 30 +-- crypto_kem/bikel3/m4f/gf2x_internal.h | 37 +--- crypto_kem/bikel3/m4f/gf2x_inv.c | 226 +-------------------- crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c | 49 +---- crypto_kem/bikel3/m4f/implementors | 10 +- crypto_kem/bikel3/m4f/sampling.c | 96 +-------- crypto_kem/bikel3/m4f/sampling.h | 43 +--- crypto_kem/bikel3/m4f/sampling_portable.c | 52 +---- crypto_kem/bikel3/m4f/sha.h | 43 +--- crypto_kem/bikel3/m4f/shake_prf.c | 66 +----- crypto_kem/bikel3/m4f/shake_prf.h | 36 +--- crypto_kem/bikel3/m4f/utilities.c | 147 +------------- crypto_kem/bikel3/m4f/utilities.h | 193 +----------------- 28 files changed, 22 insertions(+), 2017 deletions(-) delete mode 100644 crypto_kem/bikel1/m4f/aes_ctr_prf.c delete mode 100644 crypto_kem/bikel1/m4f/aes_ctr_prf.h delete mode 100644 crypto_kem/bikel1/m4f/bike_aes.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/LICENSE mode change 100644 => 120000 crypto_kem/bikel3/m4f/NOTICE delete mode 100644 crypto_kem/bikel3/m4f/aes_ctr_prf.c delete mode 100644 crypto_kem/bikel3/m4f/aes_ctr_prf.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/api.h delete mode 100644 crypto_kem/bikel3/m4f/bike_aes.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/bike_defs.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/cleanup.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/crypto_kem.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/decode.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/error.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/error.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/gf2x.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/gf2x_internal.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/gf2x_inv.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/implementors mode change 100644 => 120000 crypto_kem/bikel3/m4f/sampling.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/sampling.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/sampling_portable.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/sha.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/shake_prf.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/shake_prf.h mode change 100644 => 120000 crypto_kem/bikel3/m4f/utilities.c mode change 100644 => 120000 crypto_kem/bikel3/m4f/utilities.h diff --git a/crypto_kem/bikel1/m4f/aes_ctr_prf.c b/crypto_kem/bikel1/m4f/aes_ctr_prf.c deleted file mode 100644 index 20573c5f..00000000 --- a/crypto_kem/bikel1/m4f/aes_ctr_prf.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - */ - -#include "aes_ctr_prf.h" -#include "utilities.h" - -ret_t init_aes_ctr_prf_state(OUT aes_ctr_prf_state_t *s, - IN const uint32_t max_invokations, - IN const seed_t *seed) -{ - if(0 == max_invokations) { - BIKE_ERROR(E_AES_CTR_PRF_INIT_FAIL); - } - - // Set the key schedule (from seed). - // Make sure the size matches the AES256 key size. - DEFER_CLEANUP(aes256_key_t key, aes256_key_cleanup); - - bike_static_assert(sizeof(*seed) == sizeof(key.raw), seed_size_equals_ky_size); - bike_memcpy(key.raw, seed->raw, sizeof(key.raw)); - - GUARD(aes256_key_expansion(&s->ks, &key)); - - // Initialize buffer and counter - s->ctr.u.qw[0] = 0; - s->ctr.u.qw[1] = 0; - s->buffer.u.qw[0] = 0; - s->buffer.u.qw[1] = 0; - - s->pos = AES256_BLOCK_BYTES; - s->rem_invokations = max_invokations; - - DMSG(" Init aes_prf_ctr state:\n"); - DMSG(" s.pos = %d\n", s->pos); - DMSG(" s.rem_invokations = %u\n", s->rem_invokations); - - return SUCCESS; -} - -_INLINE_ ret_t perform_aes(OUT uint8_t *ct, IN OUT aes_ctr_prf_state_t *s) -{ - // Ensure that the CTR is large enough - bike_static_assert( - ((sizeof(s->ctr.u.qw[0]) == 8) && (BIT(33) >= MAX_AES_INVOKATION)), - ctr_size_is_too_small); - - if(0 == s->rem_invokations) { - BIKE_ERROR(E_AES_OVER_USED); - } - - GUARD(aes256_enc(ct, s->ctr.u.bytes, &s->ks)); - - s->ctr.u.qw[0]++; - s->rem_invokations--; - - return SUCCESS; -} - -ret_t aes_ctr_prf(OUT uint8_t *a, - IN OUT aes_ctr_prf_state_t *s, - IN const uint32_t len) -{ - // When Len is smaller than use what's left in the buffer, - // there is no need for additional AES invocations. - if((len + s->pos) <= AES256_BLOCK_BYTES) { - bike_memcpy(a, &s->buffer.u.bytes[s->pos], len); - s->pos += len; - - return SUCCESS; - } - - // If s.pos != AES256_BLOCK_BYTES then copy what's left in the buffer. - // Else copy zero bytes - uint32_t idx = AES256_BLOCK_BYTES - s->pos; - bike_memcpy(a, &s->buffer.u.bytes[s->pos], idx); - - // Init s.pos - s->pos = 0; - - // Copy full AES blocks - while((len - idx) >= AES256_BLOCK_BYTES) { - GUARD(perform_aes(&a[idx], s)); - idx += AES256_BLOCK_BYTES; - } - - GUARD(perform_aes(s->buffer.u.bytes, s)); - - // Copy the tail - s->pos = len - idx; - bike_memcpy(&a[idx], s->buffer.u.bytes, s->pos); - - return SUCCESS; -} diff --git a/crypto_kem/bikel1/m4f/aes_ctr_prf.h b/crypto_kem/bikel1/m4f/aes_ctr_prf.h deleted file mode 100644 index 1e724ee1..00000000 --- a/crypto_kem/bikel1/m4f/aes_ctr_prf.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -#include "bike_aes.h" - -////////////////////////////// -// Types -///////////////////////////// - -typedef struct aes_ctr_prf_state_s { - uint128_t ctr; - uint128_t buffer; - aes256_ks_t ks; - uint32_t rem_invokations; - uint8_t pos; -} aes_ctr_prf_state_t; - -////////////////////////////// -// Methods -///////////////////////////// - -ret_t init_aes_ctr_prf_state(OUT aes_ctr_prf_state_t *s, - IN uint32_t max_invokations, - IN const seed_t *seed); - -ret_t aes_ctr_prf(OUT uint8_t *a, IN OUT aes_ctr_prf_state_t *s, IN uint32_t len); - -_INLINE_ void finalize_aes_ctr_prf(IN OUT aes_ctr_prf_state_t *s) -{ - aes256_free_ks(&s->ks); - secure_clean((uint8_t *)s, sizeof(*s)); -} - -_INLINE_ void aes_ctr_prf_state_cleanup(IN OUT aes_ctr_prf_state_t *s) -{ - finalize_aes_ctr_prf(s); -} diff --git a/crypto_kem/bikel1/m4f/bike_aes.h b/crypto_kem/bikel1/m4f/bike_aes.h deleted file mode 100644 index d1b4a2e6..00000000 --- a/crypto_kem/bikel1/m4f/bike_aes.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. - * - */ - -#pragma once -#include "defs.h" - -#if defined(PQM4) || defined(MUPQ) - -#include "aes.h" - -#elif defined(USE_OPENSSL) -# include -#else -# include -#endif - -#include "cleanup.h" - -#define MAX_AES_INVOKATION (MASK(32)) - -#define AES256_KEY_BYTES (32U) -#define AES256_KEY_BITS (AES256_KEY_BYTES * 8) -#define AES256_BLOCK_BYTES (16U) -#define AES256_ROUNDS (14U) - -typedef ALIGN(16) struct aes256_key_s { - uint8_t raw[AES256_KEY_BYTES]; -} aes256_key_t; - -CLEANUP_FUNC(aes256_key, aes256_key_t) - -#if defined(PQM4) || defined(MUPQ) - -typedef aes256ctx aes256_ks_t; - - -_INLINE_ ret_t aes256_key_expansion(OUT aes256_ks_t *ks, IN const aes256_key_t *key) -{ - aes256_ecb_keyexp(ks, key->raw ); - return SUCCESS; -} - -_INLINE_ ret_t aes256_enc(OUT uint8_t *ct, IN const uint8_t *pt, IN const aes256_ks_t *ks) -{ - aes256_ecb( ct, pt, 1, ks ); - return SUCCESS; -} - -// Empty function -_INLINE_ void aes256_free_ks(OUT BIKE_UNUSED_ATT aes256_ks_t *ks) {} - - -#elif defined(USE_OPENSSL) - -// Using OpenSSL structures -typedef EVP_CIPHER_CTX *aes256_ks_t; - -_INLINE_ ret_t aes256_key_expansion(OUT aes256_ks_t *ks, - IN const aes256_key_t *key) -{ - *ks = EVP_CIPHER_CTX_new(); - if(*ks == NULL) { - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - if(0 == EVP_EncryptInit_ex(*ks, EVP_aes_256_ecb(), NULL, key->raw, NULL)) { - EVP_CIPHER_CTX_free(*ks); - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - - EVP_CIPHER_CTX_set_padding(*ks, 0); - - return SUCCESS; -} - -_INLINE_ ret_t aes256_enc(OUT uint8_t *ct, - IN const uint8_t *pt, - IN const aes256_ks_t *ks) -{ - int outlen = 0; - if(0 == EVP_EncryptUpdate(*ks, ct, &outlen, pt, AES256_BLOCK_BYTES)) { - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - return SUCCESS; -} - -_INLINE_ void aes256_free_ks(OUT aes256_ks_t *ks) -{ - EVP_CIPHER_CTX_free(*ks); - ks = NULL; -} - -#else - -typedef ALIGN(16) struct aes256_ks_s { - __m128i keys[AES256_ROUNDS + 1]; -} aes256_ks_t; - -ret_t aes256_key_expansion(OUT aes256_ks_t *ks, IN const aes256_key_t *key); - -ret_t aes256_enc(OUT uint8_t *ct, IN const uint8_t *pt, IN const aes256_ks_t *ks); - -// Empty function -_INLINE_ void aes256_free_ks(OUT BIKE_UNUSED_ATT aes256_ks_t *ks) {} - -#endif // USE_OPENSSL diff --git a/crypto_kem/bikel3/m4f/LICENSE b/crypto_kem/bikel3/m4f/LICENSE deleted file mode 100644 index 67db8588..00000000 --- a/crypto_kem/bikel3/m4f/LICENSE +++ /dev/null @@ -1,175 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. diff --git a/crypto_kem/bikel3/m4f/LICENSE b/crypto_kem/bikel3/m4f/LICENSE new file mode 120000 index 00000000..c7e2540b --- /dev/null +++ b/crypto_kem/bikel3/m4f/LICENSE @@ -0,0 +1 @@ +../../bikel1/m4f/LICENSE \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/NOTICE b/crypto_kem/bikel3/m4f/NOTICE deleted file mode 100644 index 616fc588..00000000 --- a/crypto_kem/bikel3/m4f/NOTICE +++ /dev/null @@ -1 +0,0 @@ -Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/crypto_kem/bikel3/m4f/NOTICE b/crypto_kem/bikel3/m4f/NOTICE new file mode 120000 index 00000000..4f5db311 --- /dev/null +++ b/crypto_kem/bikel3/m4f/NOTICE @@ -0,0 +1 @@ +../../bikel1/m4f/NOTICE \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/aes_ctr_prf.c b/crypto_kem/bikel3/m4f/aes_ctr_prf.c deleted file mode 100644 index 20573c5f..00000000 --- a/crypto_kem/bikel3/m4f/aes_ctr_prf.c +++ /dev/null @@ -1,97 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - */ - -#include "aes_ctr_prf.h" -#include "utilities.h" - -ret_t init_aes_ctr_prf_state(OUT aes_ctr_prf_state_t *s, - IN const uint32_t max_invokations, - IN const seed_t *seed) -{ - if(0 == max_invokations) { - BIKE_ERROR(E_AES_CTR_PRF_INIT_FAIL); - } - - // Set the key schedule (from seed). - // Make sure the size matches the AES256 key size. - DEFER_CLEANUP(aes256_key_t key, aes256_key_cleanup); - - bike_static_assert(sizeof(*seed) == sizeof(key.raw), seed_size_equals_ky_size); - bike_memcpy(key.raw, seed->raw, sizeof(key.raw)); - - GUARD(aes256_key_expansion(&s->ks, &key)); - - // Initialize buffer and counter - s->ctr.u.qw[0] = 0; - s->ctr.u.qw[1] = 0; - s->buffer.u.qw[0] = 0; - s->buffer.u.qw[1] = 0; - - s->pos = AES256_BLOCK_BYTES; - s->rem_invokations = max_invokations; - - DMSG(" Init aes_prf_ctr state:\n"); - DMSG(" s.pos = %d\n", s->pos); - DMSG(" s.rem_invokations = %u\n", s->rem_invokations); - - return SUCCESS; -} - -_INLINE_ ret_t perform_aes(OUT uint8_t *ct, IN OUT aes_ctr_prf_state_t *s) -{ - // Ensure that the CTR is large enough - bike_static_assert( - ((sizeof(s->ctr.u.qw[0]) == 8) && (BIT(33) >= MAX_AES_INVOKATION)), - ctr_size_is_too_small); - - if(0 == s->rem_invokations) { - BIKE_ERROR(E_AES_OVER_USED); - } - - GUARD(aes256_enc(ct, s->ctr.u.bytes, &s->ks)); - - s->ctr.u.qw[0]++; - s->rem_invokations--; - - return SUCCESS; -} - -ret_t aes_ctr_prf(OUT uint8_t *a, - IN OUT aes_ctr_prf_state_t *s, - IN const uint32_t len) -{ - // When Len is smaller than use what's left in the buffer, - // there is no need for additional AES invocations. - if((len + s->pos) <= AES256_BLOCK_BYTES) { - bike_memcpy(a, &s->buffer.u.bytes[s->pos], len); - s->pos += len; - - return SUCCESS; - } - - // If s.pos != AES256_BLOCK_BYTES then copy what's left in the buffer. - // Else copy zero bytes - uint32_t idx = AES256_BLOCK_BYTES - s->pos; - bike_memcpy(a, &s->buffer.u.bytes[s->pos], idx); - - // Init s.pos - s->pos = 0; - - // Copy full AES blocks - while((len - idx) >= AES256_BLOCK_BYTES) { - GUARD(perform_aes(&a[idx], s)); - idx += AES256_BLOCK_BYTES; - } - - GUARD(perform_aes(s->buffer.u.bytes, s)); - - // Copy the tail - s->pos = len - idx; - bike_memcpy(&a[idx], s->buffer.u.bytes, s->pos); - - return SUCCESS; -} diff --git a/crypto_kem/bikel3/m4f/aes_ctr_prf.h b/crypto_kem/bikel3/m4f/aes_ctr_prf.h deleted file mode 100644 index 1e724ee1..00000000 --- a/crypto_kem/bikel3/m4f/aes_ctr_prf.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -#include "bike_aes.h" - -////////////////////////////// -// Types -///////////////////////////// - -typedef struct aes_ctr_prf_state_s { - uint128_t ctr; - uint128_t buffer; - aes256_ks_t ks; - uint32_t rem_invokations; - uint8_t pos; -} aes_ctr_prf_state_t; - -////////////////////////////// -// Methods -///////////////////////////// - -ret_t init_aes_ctr_prf_state(OUT aes_ctr_prf_state_t *s, - IN uint32_t max_invokations, - IN const seed_t *seed); - -ret_t aes_ctr_prf(OUT uint8_t *a, IN OUT aes_ctr_prf_state_t *s, IN uint32_t len); - -_INLINE_ void finalize_aes_ctr_prf(IN OUT aes_ctr_prf_state_t *s) -{ - aes256_free_ks(&s->ks); - secure_clean((uint8_t *)s, sizeof(*s)); -} - -_INLINE_ void aes_ctr_prf_state_cleanup(IN OUT aes_ctr_prf_state_t *s) -{ - finalize_aes_ctr_prf(s); -} diff --git a/crypto_kem/bikel3/m4f/api.h b/crypto_kem/bikel3/m4f/api.h deleted file mode 100644 index 304366f2..00000000 --- a/crypto_kem/bikel3/m4f/api.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker and Shay Gueron - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#pragma once - -#include "types.h" -#include "crypto_kem.h" - -#define CRYPTO_SECRETKEYBYTES sizeof(sk_t) -#define CRYPTO_PUBLICKEYBYTES sizeof(pk_t) -#define CRYPTO_CIPHERTEXTBYTES sizeof(ct_t) -#define CRYPTO_BYTES sizeof(ss_t) diff --git a/crypto_kem/bikel3/m4f/api.h b/crypto_kem/bikel3/m4f/api.h new file mode 120000 index 00000000..05a11cce --- /dev/null +++ b/crypto_kem/bikel3/m4f/api.h @@ -0,0 +1 @@ +../../bikel1/m4f/api.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/bike_aes.h b/crypto_kem/bikel3/m4f/bike_aes.h deleted file mode 100644 index 7aefd010..00000000 --- a/crypto_kem/bikel3/m4f/bike_aes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. - */ - -#pragma once -#include "defs.h" - -#if defined(PQM4) || defined(MUPQ) - -#include "aes.h" - -#elif defined(USE_OPENSSL) -# include -#else -# include -#endif - -#include "cleanup.h" - -#define MAX_AES_INVOKATION (MASK(32)) - -#define AES256_KEY_BYTES (32U) -#define AES256_KEY_BITS (AES256_KEY_BYTES * 8) -#define AES256_BLOCK_BYTES (16U) -#define AES256_ROUNDS (14U) - -typedef ALIGN(16) struct aes256_key_s { - uint8_t raw[AES256_KEY_BYTES]; -} aes256_key_t; - -CLEANUP_FUNC(aes256_key, aes256_key_t) - -#if defined(PQM4) || defined(MUPQ) - -typedef aes256ctx aes256_ks_t; - - -_INLINE_ ret_t aes256_key_expansion(OUT aes256_ks_t *ks, IN const aes256_key_t *key) -{ - aes256_ecb_keyexp(ks, key->raw ); - return SUCCESS; -} - -_INLINE_ ret_t aes256_enc(OUT uint8_t *ct, IN const uint8_t *pt, IN const aes256_ks_t *ks) -{ - aes256_ecb( ct, pt, 1, ks ); - return SUCCESS; -} - -// Empty function -_INLINE_ void aes256_free_ks(OUT BIKE_UNUSED_ATT aes256_ks_t *ks) {} - - -#elif defined(USE_OPENSSL) - -// Using OpenSSL structures -typedef EVP_CIPHER_CTX *aes256_ks_t; - -_INLINE_ ret_t aes256_key_expansion(OUT aes256_ks_t *ks, - IN const aes256_key_t *key) -{ - *ks = EVP_CIPHER_CTX_new(); - if(*ks == NULL) { - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - if(0 == EVP_EncryptInit_ex(*ks, EVP_aes_256_ecb(), NULL, key->raw, NULL)) { - EVP_CIPHER_CTX_free(*ks); - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - - EVP_CIPHER_CTX_set_padding(*ks, 0); - - return SUCCESS; -} - -_INLINE_ ret_t aes256_enc(OUT uint8_t *ct, - IN const uint8_t *pt, - IN const aes256_ks_t *ks) -{ - int outlen = 0; - if(0 == EVP_EncryptUpdate(*ks, ct, &outlen, pt, AES256_BLOCK_BYTES)) { - BIKE_ERROR(EXTERNAL_LIB_ERROR_OPENSSL); - } - return SUCCESS; -} - -_INLINE_ void aes256_free_ks(OUT aes256_ks_t *ks) -{ - EVP_CIPHER_CTX_free(*ks); - ks = NULL; -} - -#else - -typedef ALIGN(16) struct aes256_ks_s { - __m128i keys[AES256_ROUNDS + 1]; -} aes256_ks_t; - -ret_t aes256_key_expansion(OUT aes256_ks_t *ks, IN const aes256_key_t *key); - -ret_t aes256_enc(OUT uint8_t *ct, IN const uint8_t *pt, IN const aes256_ks_t *ks); - -// Empty function -_INLINE_ void aes256_free_ks(OUT BIKE_UNUSED_ATT aes256_ks_t *ks) {} - -#endif // USE_OPENSSL diff --git a/crypto_kem/bikel3/m4f/bike_defs.h b/crypto_kem/bikel3/m4f/bike_defs.h deleted file mode 100644 index 9d7510b8..00000000 --- a/crypto_kem/bikel3/m4f/bike_defs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -#include "defs.h" - -//////////////////////////////////////////// -// BIKE Parameters -/////////////////////////////////////////// -#define N0 2 - -#if !defined(LEVEL) -# define LEVEL 1 -#endif - -#if(LEVEL == 3) -# define R_BITS 24659 -# define D 103 -# define T 199 - -# define THRESHOLD_COEFF0 15.2588 -# define THRESHOLD_COEFF1 0.005265 -# define THRESHOLD_MIN 52 - -// The gf2m code is optimized to a block in this case: -# define BLOCK_BITS 32768 -#elif(LEVEL == 1) -// 64-bits of post-quantum security parameters (BIKE paper): -# define R_BITS 12323 -# define D 71 -# define T 134 - -# define THRESHOLD_COEFF0 13.530 -# define THRESHOLD_COEFF1 0.0069722 -# define THRESHOLD_MIN 36 - -// The gf2x code is optimized to a block in this case: -# define BLOCK_BITS (16384) -#else -# error "Bad level, choose one of 1/3/5" -#endif - -#define NUM_OF_SEEDS 2 - -// Round the size to the nearest byte. -// SIZE suffix, is the number of bytes (uint8_t). -#define N_BITS (R_BITS * N0) -#define R_BYTES DIVIDE_AND_CEIL(R_BITS, 8) -#define R_QWORDS DIVIDE_AND_CEIL(R_BITS, 8 * BYTES_IN_QWORD) -#define R_XMM DIVIDE_AND_CEIL(R_BITS, 8 * BYTES_IN_XMM) -#define R_YMM DIVIDE_AND_CEIL(R_BITS, 8 * BYTES_IN_YMM) -#define R_ZMM DIVIDE_AND_CEIL(R_BITS, 8 * BYTES_IN_ZMM) - -#define R_BLOCKS DIVIDE_AND_CEIL(R_BITS, BLOCK_BITS) -#define R_PADDED (R_BLOCKS * BLOCK_BITS) -#define R_PADDED_BYTES (R_PADDED / 8) -#define R_PADDED_QWORDS (R_PADDED / 64) - -#define LAST_R_QWORD_LEAD (R_BITS & MASK(6)) -#define LAST_R_QWORD_TRAIL (64 - LAST_R_QWORD_LEAD) -#define LAST_R_QWORD_MASK MASK(LAST_R_QWORD_LEAD) - -#define LAST_R_BYTE_LEAD (R_BITS & MASK(3)) -#define LAST_R_BYTE_TRAIL (8 - LAST_R_BYTE_LEAD) -#define LAST_R_BYTE_MASK MASK(LAST_R_BYTE_LEAD) - -// Data alignement -#define ALIGN_BYTES (BYTES_IN_ZMM) - -#define M_BITS 256 -#define M_BYTES (M_BITS / 8) - -#define SS_BITS 256 -#define SS_BYTES (SS_BITS / 8) - -#define SEED_BYTES (256 / 8) - -////////////////////////////////// -// Parameters for the BGF decoder. -////////////////////////////////// -#define BGF_DECODER -#define DELTA 3 -#define SLICES (LOG2_MSB(D) + 1) - -// GF2X inversion can only handle R < 32768 -bike_static_assert((R_BITS < 32768), r_too_large_for_inversion); diff --git a/crypto_kem/bikel3/m4f/bike_defs.h b/crypto_kem/bikel3/m4f/bike_defs.h new file mode 120000 index 00000000..03b67c71 --- /dev/null +++ b/crypto_kem/bikel3/m4f/bike_defs.h @@ -0,0 +1 @@ +../../bikel1/m4f/bike_defs.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/cleanup.h b/crypto_kem/bikel3/m4f/cleanup.h deleted file mode 100644 index 4605e968..00000000 --- a/crypto_kem/bikel3/m4f/cleanup.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -#include "utilities.h" - -/* Runs _thecleanup function on _thealloc once _thealloc went out of scope */ -#define DEFER_CLEANUP(_thealloc, _thecleanup) \ - __attribute__((cleanup(_thecleanup))) _thealloc - -/* Create a cleanup function for pointers from function func, which accepts a - * pointer. This is useful for DEFER_CLEANUP, as it passes &_thealloc into - * _thecleanup function. This way, - * if _thealloc is a pointer _thecleanup would receive a pointer to a - * pointer.*/ -#define DEFINE_POINTER_CLEANUP_FUNC(type, func) \ - static inline void func##_pointer((type)*p) \ - { \ - if(p && *p) { \ - func(*p); \ - } \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ - -// len is bytes length of in -_INLINE_ void secure_clean(OUT uint8_t *p, IN const uint32_t len) -{ -#if defined(_WIN32) - SecureZeroMemory(p, len); -#else - typedef void *(*memset_t)(void *, int, size_t); - static volatile memset_t memset_func = bike_memset; - memset_func(p, 0, len); -#endif -} - -#define CLEANUP_FUNC(name, type) \ - _INLINE_ void name##_cleanup(IN OUT type *o) \ - { \ - secure_clean((uint8_t *)o, sizeof(*o)); \ - } - -CLEANUP_FUNC(r, r_t) -CLEANUP_FUNC(m, m_t) -CLEANUP_FUNC(e, e_t) -CLEANUP_FUNC(sk, sk_t) -CLEANUP_FUNC(ss, ss_t) -CLEANUP_FUNC(ct, ct_t) -CLEANUP_FUNC(pad_r, pad_r_t) -CLEANUP_FUNC(pad_e, pad_e_t) -CLEANUP_FUNC(seed, seed_t) -CLEANUP_FUNC(syndrome, syndrome_t) -CLEANUP_FUNC(upc, upc_t) -CLEANUP_FUNC(func_k, func_k_t) -CLEANUP_FUNC(dbl_pad_r, dbl_pad_r_t) -CLEANUP_FUNC(quad_pad_r, quad_pad_r_t) - -// The functions below require special handling because we deal -// with arrays and not structures. - -_INLINE_ void compressed_idx_d_ar_cleanup(IN OUT compressed_idx_d_ar_t *o) -{ - for(int i = 0; i < N0; i++) { - secure_clean((uint8_t *)&(*o)[i], sizeof((*o)[0])); - } -} - -_INLINE_ void seeds_cleanup(IN OUT seeds_t *o) -{ - for(int i = 0; i < NUM_OF_SEEDS; i++) { - seed_cleanup(&(o->seed[i])); - } -} diff --git a/crypto_kem/bikel3/m4f/cleanup.h b/crypto_kem/bikel3/m4f/cleanup.h new file mode 120000 index 00000000..1a7321c3 --- /dev/null +++ b/crypto_kem/bikel3/m4f/cleanup.h @@ -0,0 +1 @@ +../../bikel1/m4f/cleanup.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/crypto_kem.h b/crypto_kem/bikel3/m4f/crypto_kem.h deleted file mode 100644 index 4c3b4bdc..00000000 --- a/crypto_kem/bikel3/m4f/crypto_kem.h +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef _CRYPTO_KEM_H_ -#define _CRYPTO_KEM_H_ - - - - -//////////////////////////////////////////////////////////////// -//Below three APIs (keygen, encaps, decaps) are defined by NIST: -//////////////////////////////////////////////////////////////// -//Keygenerate - pk is the public key, -// sk is the private key, -int crypto_kem_keypair( unsigned char *pk, unsigned char *sk); - -//Encapsulate - pk is the public key, -// ct is a key encapsulation message (ciphertext), -// ss is the shared secret. -int crypto_kem_enc( unsigned char *ct, - unsigned char *ss, - const unsigned char *pk); - -//Decapsulate - ct is a key encapsulation message (ciphertext), -// sk is the private key, -// ss is the shared secret -int crypto_kem_dec( unsigned char *ss, - const unsigned char *ct, - const unsigned char *sk); - -#endif - diff --git a/crypto_kem/bikel3/m4f/crypto_kem.h b/crypto_kem/bikel3/m4f/crypto_kem.h new file mode 120000 index 00000000..59e3f1ab --- /dev/null +++ b/crypto_kem/bikel3/m4f/crypto_kem.h @@ -0,0 +1 @@ +../../bikel1/m4f/crypto_kem.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/decode.h b/crypto_kem/bikel3/m4f/decode.h deleted file mode 100644 index d00747f9..00000000 --- a/crypto_kem/bikel3/m4f/decode.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -#include "types.h" - -ret_t decode(OUT e_t *e, IN const ct_t *ct, IN const sk_t *sk); - -// Rotate right the first R_BITS of a syndrome. -// At input, the syndrome is stored as three R_BITS triplicate. -// (this makes rotation easier to implement) -// For the output: the output syndrome has only one R_BITS rotation, the remaining -// (2 * R_BITS) bits are undefined. -void rotate_right(OUT syndrome_t *out, - IN const syndrome_t *in, - IN uint32_t bitscount); - - -// Rotate right the first R_BITS of a syndrome. -// At input, the syndrome is stored as three R_BITS triplicate. -// (this makes rotation easier to implement) -// For the output: the output syndrome has only one R_BITS rotation, the remaining -// (2 * R_BITS) bits are undefined. -void rotate_right_u32(OUT syndrome_t *out, - IN const syndrome_t *in, - IN uint32_t bitscount); - - -void rotr_prepare_u32(OUT syndrome_t *out, IN const syndrome_t *in); - -void rotate_right_u32_2(OUT syndrome_t *out, - IN const syndrome_t *in, - IN uint32_t bitscount); diff --git a/crypto_kem/bikel3/m4f/decode.h b/crypto_kem/bikel3/m4f/decode.h new file mode 120000 index 00000000..fa6a684e --- /dev/null +++ b/crypto_kem/bikel3/m4f/decode.h @@ -0,0 +1 @@ +../../bikel1/m4f/decode.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/error.c b/crypto_kem/bikel3/m4f/error.c deleted file mode 100644 index 1b437660..00000000 --- a/crypto_kem/bikel3/m4f/error.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#include "error.h" - -//__thread _bike_err_t bike_errno; -_bike_err_t bike_errno; diff --git a/crypto_kem/bikel3/m4f/error.c b/crypto_kem/bikel3/m4f/error.c new file mode 120000 index 00000000..3fcea915 --- /dev/null +++ b/crypto_kem/bikel3/m4f/error.c @@ -0,0 +1 @@ +../../bikel1/m4f/error.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/error.h b/crypto_kem/bikel3/m4f/error.h deleted file mode 100644 index 580a9fe2..00000000 --- a/crypto_kem/bikel3/m4f/error.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * Modification: 2023 Till Eifert - * - */ - -#pragma once - -#define SUCCESS 0 -#define FAIL (-1) - -#define ret_t int __attribute__((warn_unused_result)) -#define GUARD(x) \ - if((x) != SUCCESS) return FAIL - -enum _bike_err -{ - E_DECODING_FAILURE = 1, - E_AES_CTR_PRF_INIT_FAIL = 2, - E_AES_OVER_USED = 3, - EXTERNAL_LIB_ERROR_OPENSSL = 4, - E_SHAKE_PRF_INIT_FAIL = 5, - E_SHAKE_OVER_USED = 6 -}; - -typedef enum _bike_err _bike_err_t; - -extern _bike_err_t bike_errno; -#define BIKE_ERROR(x) \ - do { \ - bike_errno = (x); \ - return FAIL; \ - } while(0) diff --git a/crypto_kem/bikel3/m4f/error.h b/crypto_kem/bikel3/m4f/error.h new file mode 120000 index 00000000..9f0ae953 --- /dev/null +++ b/crypto_kem/bikel3/m4f/error.h @@ -0,0 +1 @@ +../../bikel1/m4f/error.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/gf2x.h b/crypto_kem/bikel3/m4f/gf2x.h deleted file mode 100644 index f4cdb53a..00000000 --- a/crypto_kem/bikel3/m4f/gf2x.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - */ - -#pragma once - -#include "types.h" - -// c = a+b mod (x^r - 1) -_INLINE_ void -gf2x_mod_add(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b) -{ - const uint64_t *a_qwords = (const uint64_t *)a; - const uint64_t *b_qwords = (const uint64_t *)b; - uint64_t * c_qwords = (uint64_t *)c; - - for(size_t i = 0; i < R_PADDED_QWORDS; i++) { - c_qwords[i] = a_qwords[i] ^ b_qwords[i]; - } -} - -// c = a*b mod (x^r - 1) -void gf2x_mod_mul(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b); - -// c = a^-1 mod (x^r - 1) -void gf2x_mod_inv(OUT pad_r_t *c, IN const pad_r_t *a); diff --git a/crypto_kem/bikel3/m4f/gf2x.h b/crypto_kem/bikel3/m4f/gf2x.h new file mode 120000 index 00000000..15fe59cb --- /dev/null +++ b/crypto_kem/bikel3/m4f/gf2x.h @@ -0,0 +1 @@ +../../bikel1/m4f/gf2x.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/gf2x_internal.h b/crypto_kem/bikel3/m4f/gf2x_internal.h deleted file mode 100644 index 3dae1925..00000000 --- a/crypto_kem/bikel3/m4f/gf2x_internal.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - */ - -#pragma once - -// For size_t -#include - -#include "types.h" - -// The size in quadwords of the operands in the gf2x_mul_base function -// for different implementations. -#if defined(PCLMUL) -# define GF2X_BASE_QWORDS (8) -#elif defined(VPCLMUL) -# define GF2X_BASE_QWORDS (16) -#else -# define GF2X_BASE_QWORDS (1) -#endif - -// GF2X multiplication of a and b of size GF2X_BASE_QWORDS, c = a * b -void gf2x_mul_base(OUT uint64_t *c, IN const uint64_t *a, IN const uint64_t *b); - -// c = a^2 -void gf2x_sqr(OUT dbl_pad_r_t *c, IN const pad_r_t *a); - -// a = a^2 mod (x^r - 1) -void gf2x_mod_sqr_in_place(IN OUT pad_r_t *a, OUT dbl_pad_r_t *secure_buffer); - -// The k-squaring function computes c = a^(2^k) % (x^r - 1), -// It is required by inversion, where l_param is derived from k. -void k_squaring(OUT pad_r_t *c, IN const pad_r_t *a, IN size_t l_param); diff --git a/crypto_kem/bikel3/m4f/gf2x_internal.h b/crypto_kem/bikel3/m4f/gf2x_internal.h new file mode 120000 index 00000000..781778e0 --- /dev/null +++ b/crypto_kem/bikel3/m4f/gf2x_internal.h @@ -0,0 +1 @@ +../../bikel1/m4f/gf2x_internal.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/gf2x_inv.c b/crypto_kem/bikel3/m4f/gf2x_inv.c deleted file mode 100644 index 8325b331..00000000 --- a/crypto_kem/bikel3/m4f/gf2x_inv.c +++ /dev/null @@ -1,225 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modified by Ming-Shing Chen, Tung Chou and Markus Krausz. - * Modification: 2023 Till Eifert - * - * - * The inversion algorithm in this file is based on: - * [1] Nir Drucker, Shay Gueron, and Dusan Kostic. 2020. "Fast polynomial - * inversion for post quantum QC-MDPC cryptography". Cryptology ePrint Archive, - * 2020. https://eprint.iacr.org/2020/298.pdf - */ - -#include "cleanup.h" -#include "gf2x.h" -#include "gf2x_internal.h" - -#include "ring_ops.h" - -#define _MY_SQU_ - - -// c = a^2^2^num_sqrs -_INLINE_ void repeated_squaring(OUT pad_r_t *c, - IN pad_r_t * a, - IN const size_t num_sqrs, - OUT dbl_pad_r_t *sec_buf) -{ - c->val = a->val; - - for(size_t i = 0; i < num_sqrs; i++) { -#if defined(_MY_SQU_) - ring_squ(c , c); - (void) sec_buf; -#else - gf2x_mod_sqr_in_place(c, sec_buf); -#endif - } -} - -// The gf2x_mod_inv function implements inversion in F_2[x]/(x^R - 1) -// based on [1](Algorithm 2). - -// In every iteration, [1](Algorithm 2) performs two exponentiations: -// exponentiation 0 (exp0) and exponentiation 1 (exp1) of the form f^(2^k). -// These exponentiations are computed either by repeated squaring of f, k times, -// or by a single k-squaring of f. The method for a specific value of k -// is chosen based on the performance of squaring and k-squaring. -// -// Benchmarks on several platforms indicate that a good threshold -// for switching from repeated squaring to k-squaring is k = 64. -#define K_SQR_THR (7) - -// k-squaring is computed by a permutation of bits of the input polynomial, -// as defined in [1](Observation 1). The required parameter for the permutation -// is l = (2^k)^-1 % R. -// Therefore, there are two sets of parameters for every exponentiation: -// - exp0_k and exp1_k -// - exp0_l and exp1_l - -// Exponentiation 0 computes f^2^2^(i-1) for 0 < i < MAX_I. -// Exponentiation 1 computes f^2^((r-2) % 2^i) for 0 < i < MAX_I, -// only when the i-th bit of (r-2) is 1. Therefore, the value 0 in -// exp1_k[i] and exp1_l[i] means that exp1 is skipped in i-th iteration. - -// To quickly generate all the required parameters in Sage: -// r = DESIRED_R -// max_i = floor(log(r-2, 2)) + 1 -// exp0_k = [2^i for i in range(max_i)] -// exp0_l = [inverse_mod((2^k) % r, r) for k in exp0_k] -// exp1_k = [(r-2)%(2^i) if ((r-2) & (1<val; - - for(size_t i = 0; i < MAX_I; i++) { - if(exp0_k[i] <= K_SQR_THR) { - repeated_squaring(&g, &t, exp0_k[i], &sec_buf); - } else { - k_squaring(&g, &t, exp0_l[i]); - } - ring_mul(&t, &g, &t); - - if(exp1_k[i] != 0) { - repeated_squaring(&g, &t, exp1_k[i], &sec_buf); - ring_mul_2(&t, &g, &ta); - //ring_mul(&t, &g, a); /// XXX: use pre-computed input transform - } - } -#else - DEFER_CLEANUP(pad_r_t f = {0}, pad_r_cleanup); - DEFER_CLEANUP(pad_r_t g = {0}, pad_r_cleanup); - DEFER_CLEANUP(pad_r_t t = {0}, pad_r_cleanup); - DEFER_CLEANUP(dbl_pad_r_t sec_buf = {0}, dbl_pad_r_cleanup); - - // Steps 2 and 3 in [1](Algorithm 2) - f.val = a->val; - t.val = a->val; - - for(size_t i = 1; i < MAX_I; i++) { - // Step 5 in [1](Algorithm 2), exponentiation 0: g = f^2^2^(i-1) - if(exp0_k[i - 1] <= K_SQR_THR) { - repeated_squaring(&g, &f, exp0_k[i - 1], &sec_buf); - } else { - k_squaring(&g, &f, exp0_l[i - 1]); - } - - // Step 6, [1](Algorithm 2): f = f*g - //gf2x_mod_mul(&f, &g, &f); - ring_mul(&f, &g, &f); - - if(exp1_k[i] != 0) { - // Step 8, [1](Algorithm 2), exponentiation 1: g = f^2^((r-2) % 2^i) - if(exp1_k[i] <= K_SQR_THR) { - repeated_squaring(&g, &f, exp1_k[i], &sec_buf); - } else { - k_squaring(&g, &f, exp1_l[i]); - } - - // Step 9, [1](Algorithm 2): t = t*g; - gf2x_mod_mul(&t, &g, &t); - } - } -#endif - - // Step 10, [1](Algorithm 2): c = t^2 -#if defined(_MY_SQU_) - ring_squ(&t, &t); -#else - gf2x_mod_sqr_in_place(&t, &sec_buf); -#endif - c->val = t.val; -} diff --git a/crypto_kem/bikel3/m4f/gf2x_inv.c b/crypto_kem/bikel3/m4f/gf2x_inv.c new file mode 120000 index 00000000..b2237b9b --- /dev/null +++ b/crypto_kem/bikel3/m4f/gf2x_inv.c @@ -0,0 +1 @@ +../../bikel1/m4f/gf2x_inv.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c b/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c deleted file mode 100644 index 35dad201..00000000 --- a/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * The k-squaring algorithm in this file is based on: - * [1] Nir Drucker, Shay Gueron, and Dusan Kostic. 2020. "Fast polynomial - * inversion for post quantum QC-MDPC cryptography". Cryptology ePrint Archive, - * 2020. https://eprint.iacr.org/2020/298.pdf - */ - -#include "gf2x_internal.h" -#include "utilities.h" - -#define BITS_IN_BYTE (8) - -// The k-squaring function computes c = a^(2^k) % (x^r - 1), -// By [1](Observation 1), if -// a = sum_{j in supp(a)} x^j, -// then -// a^(2^k) % (x^r - 1) = sum_{j in supp(a)} x^((j * 2^k) % r). -// Therefore, k-squaring can be computed as permutation of the bits of "a": -// pi0 : j --> (j * 2^k) % r. -// For improved performance, we compute the result by inverted permutation pi1: -// pi1 : (j * 2^-k) % r --> j. -// Input argument l_param is defined as the value (2^-k) % r. -void k_squaring(OUT pad_r_t *c, IN const pad_r_t *a, IN const size_t l_param) -{ - bike_memset(c->val.raw, 0, sizeof(c->val)); - - // Compute the result byte by byte - size_t idx = 0; - for(size_t i = 0; i < R_BYTES; i++) { - for(size_t j = 0; j < BITS_IN_BYTE; j++, idx++) { - // Bit of "c" at position idx is set to the value of - // the bit of "a" at position pi1(idx) = (l_param * idx) % R_BITS. - size_t pos = (l_param * idx) % R_BITS; - - size_t pos_byte = pos >> 3; - size_t pos_bit = pos & 7; - uint8_t bit = (a->val.raw[pos_byte] >> pos_bit) & 1; - - c->val.raw[i] |= (bit << j); - } - } - c->val.raw[R_BYTES - 1] &= LAST_R_BYTE_MASK; -} diff --git a/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c b/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c new file mode 120000 index 00000000..d106d857 --- /dev/null +++ b/crypto_kem/bikel3/m4f/gf2x_ksqr_portable.c @@ -0,0 +1 @@ +../../bikel1/m4f/gf2x_ksqr_portable.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/implementors b/crypto_kem/bikel3/m4f/implementors deleted file mode 100644 index 481551a7..00000000 --- a/crypto_kem/bikel3/m4f/implementors +++ /dev/null @@ -1,9 +0,0 @@ -Original: -Nir Drucker (University of Haifa, Israel, and Amazon, USA), -Shay Gueron (University of Haifa, Israel, and Amazon, USA), -Dusan Kostic (EPFL, Switzerland) - -Modified: -Ming-Shing Chen (Ruhr University Bochum, Germany) -Tung Chou (Academia Sinica, Taiwan) -Markus Krausz (Ruhr University Bochum, Germany) diff --git a/crypto_kem/bikel3/m4f/implementors b/crypto_kem/bikel3/m4f/implementors new file mode 120000 index 00000000..699acf57 --- /dev/null +++ b/crypto_kem/bikel3/m4f/implementors @@ -0,0 +1 @@ +../../bikel1/m4f/implementors \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/sampling.c b/crypto_kem/bikel3/m4f/sampling.c deleted file mode 100644 index 0b9dc34c..00000000 --- a/crypto_kem/bikel3/m4f/sampling.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#include - -#include "sampling.h" -#include "cleanup.h" - -void get_seeds(OUT seeds_t *seeds) -{ -#if defined(USE_NIST_RAND) - randombytes((uint8_t *)seeds, NUM_OF_SEEDS * sizeof(seed_t)); -#else - for(uint32_t i = 0; i < NUM_OF_SEEDS; ++i) { - for(uint32_t j = 0; j < sizeof(seed_t); ++j) { - seeds->seed[i].raw[j] = rand(); - } - } -#endif - for(uint32_t i = 0; i < NUM_OF_SEEDS; ++i) { - print("s: ", (uint64_t *)&seeds->seed[i], SIZEOF_BITS(seed_t)); - } -} - -ret_t sample_indices_fisher_yates(OUT idx_t *out, - IN size_t num_indices, - IN idx_t max_idx_val, - IN OUT prf_state_t *prf_state) -{ - for (size_t i = num_indices; i-- > 0;) { -#define CWW_RAND_BYTES 4 - uint64_t rand = 0ULL; - GUARD(get_shake256_prf_output((uint8_t *)&rand, prf_state, CWW_RAND_BYTES)); - rand *= (max_idx_val - i); - - // new index l is such that i <= l < max_idx_val - uint32_t l = i + (uint32_t)(rand >> (CWW_RAND_BYTES * 8)); - - // Loop over (the end of) the output array to determine if l is a duplicate - uint32_t is_dup = 0; - for (size_t j = i + 1; j < num_indices; ++j) { - is_dup |= secure_cmp32(l, out[j]); - } - - // if l is a duplicate out[i] gets i else out[i] gets l - // mask is all 1 if l is a duplicate, all 0 else - uint32_t mask = -is_dup; - out[i] = (mask & i) ^ (~mask & l); - } - - return SUCCESS; -} - -ret_t generate_sparse_rep(OUT pad_r_t *r, - OUT idx_t *wlist, - IN OUT prf_state_t *prf_state) -{ - - GUARD(sample_indices_fisher_yates(wlist, D, R_BITS, prf_state)); - - secure_set_bits(r, 0, wlist, D); - - return SUCCESS; -} - -ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed) -{ - DEFER_CLEANUP(prf_state_t prf_state = {0}, clean_shake256_prf_state); - - GUARD(init_shake256_prf_state(&prf_state, MAX_PRF_INVOCATION, seed)); - - idx_t wlist[T]; - GUARD(sample_indices_fisher_yates(wlist, T, N_BITS, &prf_state)); - - // (e0, e1) hold bits 0..R_BITS-1 and R_BITS..2*R_BITS-1 of the error, resp. - secure_set_bits(&e->val[0], 0, wlist, T); - secure_set_bits(&e->val[1], R_BITS, wlist, T); - - // Clean the padding of the elements - PE0_RAW(e)[R_BYTES - 1] &= LAST_R_BYTE_MASK; - PE1_RAW(e)[R_BYTES - 1] &= LAST_R_BYTE_MASK; - bike_memset(&PE0_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); - bike_memset(&PE1_RAW(e)[R_BYTES], 0, R_PADDED_BYTES - R_BYTES); - - secure_clean((uint8_t *)wlist, sizeof(*wlist)); - - return SUCCESS; -} diff --git a/crypto_kem/bikel3/m4f/sampling.c b/crypto_kem/bikel3/m4f/sampling.c new file mode 120000 index 00000000..4bfc9258 --- /dev/null +++ b/crypto_kem/bikel3/m4f/sampling.c @@ -0,0 +1 @@ +../../bikel1/m4f/sampling.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/sampling.h b/crypto_kem/bikel3/m4f/sampling.h deleted file mode 100644 index 5618c810..00000000 --- a/crypto_kem/bikel3/m4f/sampling.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#pragma once -#include "defs.h" - -#if defined(USE_NIST_RAND) - #include "randombytes.h" -#else -# include -#endif - -#include "shake_prf.h" -#include "utilities.h" - -typedef enum -{ - NO_RESTRICTION = 0, - MUST_BE_ODD = 1 -} must_be_odd_t; - -void get_seeds(OUT seeds_t *seeds); - -ret_t generate_sparse_rep(OUT pad_r_t *r, - OUT idx_t *wlist, - IN OUT prf_state_t *prf_state); - -ret_t generate_error_vector(OUT pad_e_t *e, IN const seed_t *seed); - -// When "a" is considered as part of some larger array, then a_first_pos -// is the start position of "a" in the large array. -void secure_set_bits(OUT pad_r_t *r, - IN size_t first_pos, - IN const idx_t *wlist, - IN size_t w_size); diff --git a/crypto_kem/bikel3/m4f/sampling.h b/crypto_kem/bikel3/m4f/sampling.h new file mode 120000 index 00000000..64d49415 --- /dev/null +++ b/crypto_kem/bikel3/m4f/sampling.h @@ -0,0 +1 @@ +../../bikel1/m4f/sampling.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/sampling_portable.c b/crypto_kem/bikel3/m4f/sampling_portable.c deleted file mode 100644 index 9d16c84d..00000000 --- a/crypto_kem/bikel3/m4f/sampling_portable.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#include - -#include "sampling.h" - -#define MAX_WLIST_SIZE (T > D ? T : D) - -void secure_set_bits(OUT pad_r_t * r, - IN const size_t first_pos, - IN const idx_t *wlist, - IN const size_t w_size) -{ - assert(w_size <= MAX_WLIST_SIZE); - - // Ideally we would like to cast r.val but it is not guaranteed to be aligned - // as the entire pad_r_t structure. Thus, we assert that the position of val - // is at the beginning of r. - bike_static_assert(offsetof(pad_r_t, val) == 0, val_wrong_pos_in_pad_r_t); - uint64_t *a64 = (uint64_t *)r; - uint64_t val, mask; - - // The size of wlist can be either D or T. So, we set it to max(D, T) - uint32_t pos_qw[MAX_WLIST_SIZE]; - uint64_t pos_bit[MAX_WLIST_SIZE]; - - // Identify the QW position of every value, and the bit position inside this QW. - for(size_t i = 0; i < w_size; i++) { - int32_t w = wlist[i] - first_pos; - pos_qw[i] = w >> 6; - pos_bit[i] = BIT(w & MASK(6)); - } - - // Fill each QW in constant time - for(size_t i = 0; i < (sizeof(*r) / sizeof(uint64_t)); i++) { - val = 0; - for(size_t j = 0; j < w_size; j++) { - mask = (-1ULL) + (!secure_cmp32(pos_qw[j], i)); - val |= (pos_bit[j] & mask); - } - a64[i] = val; - } -} diff --git a/crypto_kem/bikel3/m4f/sampling_portable.c b/crypto_kem/bikel3/m4f/sampling_portable.c new file mode 120000 index 00000000..7b77fd5b --- /dev/null +++ b/crypto_kem/bikel3/m4f/sampling_portable.c @@ -0,0 +1 @@ +../../bikel1/m4f/sampling_portable.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/sha.h b/crypto_kem/bikel3/m4f/sha.h deleted file mode 100644 index 4a9ef2e5..00000000 --- a/crypto_kem/bikel3/m4f/sha.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#pragma once - -#include "cleanup.h" -#include "error.h" -#include "types.h" - -#define SHA384_DGST_BYTES 48ULL -#define SHA384_DGST_QWORDS (SHA384_DGST_BYTES / 8) - -#define SHA512_DGST_BYTES 64ULL -#define SHA512_DGST_QWORDS (SHA512_DGST_BYTES / 8) - -typedef struct sha384_dgst_s { - union { - uint8_t raw[SHA384_DGST_BYTES]; - uint64_t qw[SHA384_DGST_QWORDS]; - } u; -} sha384_dgst_t; -bike_static_assert(sizeof(sha384_dgst_t) == SHA384_DGST_BYTES, sha384_dgst_size); - -typedef sha384_dgst_t sha_dgst_t; -CLEANUP_FUNC(sha_dgst, sha_dgst_t) - -#include "fips202.h" - -_INLINE_ ret_t sha(OUT sha_dgst_t * dgst, - IN const uint32_t byte_len, - IN const uint8_t *msg) -{ - sha3_384(dgst->u.raw, msg, byte_len); - return SUCCESS; -} diff --git a/crypto_kem/bikel3/m4f/sha.h b/crypto_kem/bikel3/m4f/sha.h new file mode 120000 index 00000000..dde0f3c2 --- /dev/null +++ b/crypto_kem/bikel3/m4f/sha.h @@ -0,0 +1 @@ +../../bikel1/m4f/sha.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/shake_prf.c b/crypto_kem/bikel3/m4f/shake_prf.c deleted file mode 100644 index ffc184d4..00000000 --- a/crypto_kem/bikel3/m4f/shake_prf.c +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * This code is maintained by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#include "cleanup.h" -#include "shake_prf.h" -#include "utilities.h" - -ret_t init_shake256_prf_state(OUT shake256_prf_state_t *s, IN size_t max_num_invocations, - IN const seed_t *seed) -{ - if(0 == max_num_invocations) { - BIKE_ERROR(E_SHAKE_PRF_INIT_FAIL); - } - - // Initialize the SHAKE state with the given seed. - shake256_absorb(&s->s, seed->raw, sizeof(*seed)); - - // Initialize the PRF parameters. - s->curr_pos_in_buffer = SHAKE256_RATE; - s->rem_invocations = max_num_invocations; - - return SUCCESS; -} - -ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT shake256_prf_state_t *s, - IN size_t len) -{ - // Check if the maximum number of SHAKE invocations is reached. - if (s->rem_invocations == 0) - { - BIKE_ERROR(E_SHAKE_OVER_USED); - } - - // When |len| is smaller then use what's left in the buffer, - // there is no need for additional SHAKE256 invocations. - if((len + s->curr_pos_in_buffer) <= SHAKE256_RATE) { - bike_memcpy(out, &s->buffer[s->curr_pos_in_buffer], len); - s->curr_pos_in_buffer += len; - - return SUCCESS; - } - - // Generate one block (SHAKE256_RATE bytes) of random data with SHAKE256. - shake256_squeezeblocks(s->buffer, 1, &s->s); - - // Copy |len| bytes to the output, set the new buffer position indicator, - // and update the remaining allowable number of SHAKE invocations. - bike_memcpy(out, s->buffer, len); - s->curr_pos_in_buffer = len; - s->rem_invocations -= 1; - - return SUCCESS; -} - -void clean_shake256_prf_state(IN OUT shake256_prf_state_t *s) -{ - secure_clean((uint8_t*)s, sizeof(*s)); -} diff --git a/crypto_kem/bikel3/m4f/shake_prf.c b/crypto_kem/bikel3/m4f/shake_prf.c new file mode 120000 index 00000000..0dc5c9eb --- /dev/null +++ b/crypto_kem/bikel3/m4f/shake_prf.c @@ -0,0 +1 @@ +../../bikel1/m4f/shake_prf.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/shake_prf.h b/crypto_kem/bikel3/m4f/shake_prf.h deleted file mode 100644 index 0d6926ec..00000000 --- a/crypto_kem/bikel3/m4f/shake_prf.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2023 Till Eifert - * - */ - -#pragma once - -#include "defs.h" -#include "error.h" -#include "types.h" -#include "fips202.h" - -typedef struct shake256_prf_state_s { - shake256ctx s; - uint8_t buffer[SHAKE256_RATE]; - size_t curr_pos_in_buffer; - size_t rem_invocations; -} shake256_prf_state_t; - -typedef shake256_prf_state_t prf_state_t; - -#define MAX_PRF_INVOCATION (MASK(32)) - -// Methods for interacting with the PRFs. -ret_t init_shake256_prf_state(OUT prf_state_t *s, IN size_t max_num_invocations, - IN const seed_t *seed); - -ret_t get_shake256_prf_output(OUT uint8_t *out, IN OUT prf_state_t *s, IN size_t len); - -void clean_shake256_prf_state(IN OUT prf_state_t *s); diff --git a/crypto_kem/bikel3/m4f/shake_prf.h b/crypto_kem/bikel3/m4f/shake_prf.h new file mode 120000 index 00000000..11d96ab6 --- /dev/null +++ b/crypto_kem/bikel3/m4f/shake_prf.h @@ -0,0 +1 @@ +../../bikel1/m4f/shake_prf.h \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/utilities.c b/crypto_kem/bikel3/m4f/utilities.c deleted file mode 100644 index c3785116..00000000 --- a/crypto_kem/bikel3/m4f/utilities.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - */ - -#include - -#include "utilities.h" - -#define BITS_IN_QWORD 64ULL -#define BITS_IN_BYTE 8ULL - -uint64_t r_bits_vector_weight(IN const r_t *in) -{ - uint64_t acc = 0; - for(size_t i = 0; i < (R_BYTES - 1); i++) { - acc += __builtin_popcount(in->raw[i]); - } - - acc += __builtin_popcount(in->raw[R_BYTES - 1] & LAST_R_BYTE_MASK); - return acc; -} - -#if defined(VERBOSE) -// Print a new line only if we prints in qw blocks -_INLINE_ void print_newline(IN const uint64_t qw_pos) -{ -# if !defined(NO_NEWLINE) - if((qw_pos % 4) == 3) { - printf("\n "); - } -# endif -} - -// Prints a QW in LE/BE in win/linux format -_INLINE_ void print_uint64(IN const uint64_t val) -{ - // If printing in BE is required, swap the order of the bytes. -# if defined(PRINT_IN_BE) - uint64_t tmp = bswap_64(val); -# else - uint64_t tmp = val; -# endif - - printf("%.16" PRIx64, tmp); - -# if !defined(NO_SPACE) - printf(" "); -# endif -} - -// Last block requires special handling: we should zero-mask all the bits -// above the desired number. -// Endian - 0 - BE, 1 - LE -// Return 1 if the last block was printed; else return 0. -_INLINE_ uint8_t print_last_block(IN const uint8_t *last_bytes, - IN const uint32_t bits_num, - IN const uint32_t endien) -{ - // Floor of bits/64 the reminder is in the next QW - const uint32_t qw_num = bits_num / BITS_IN_QWORD; - - // How many bits to pad with zero - const uint32_t rem_bits = bits_num - (BITS_IN_QWORD * qw_num); - - // We read byte by byte and not the whole QW, in order to avoid reading a bad - // memory address - const uint32_t bytes_num = - ((rem_bits % 8) == 0) ? rem_bits / BITS_IN_BYTE : 1 + rem_bits / BITS_IN_BYTE; - - // Must be signed for the LE loop - int i; - - if(0 == rem_bits) { - return 0; - } - - // Mask unneeded bits - const uint8_t last_byte = (rem_bits % 8 == 0) - ? last_bytes[bytes_num - 1] - : last_bytes[bytes_num - 1] & MASK(rem_bits % 8); - // BE - if(0 == endien) { - for(i = 0; (uint32_t)i < (bytes_num - 1); i++) { - printf("%.2x", last_bytes[i]); - } - - printf("%.2x", last_byte); - - for(i++; (uint32_t)i < sizeof(uint64_t); i++) { - printf("__"); - } - } else { - for(i = sizeof(uint64_t) - 1; (uint32_t)i >= bytes_num; i--) { - printf("__"); - } - - printf("%.2x", last_byte); - - for(i--; i >= 0; i--) { - printf("%.2x", last_bytes[i]); - } - } - -# if !defined(NO_SPACE) - printf(" "); -# endif - - return 1; -} - -void print_LE(IN const uint64_t *in, IN const uint32_t bits_num) -{ - const uint32_t qw_num = bits_num / BITS_IN_QWORD; - - // Print the MSB QW - uint32_t qw_pos = print_last_block((const uint8_t *)&in[qw_num], bits_num, 1); - - // Print every 8 bytes separated by a space (if required) - for(int i = ((int)qw_num) - 1; i >= 0; i--, qw_pos++) { - print_uint64(in[i]); - print_newline(qw_pos); - } - - printf("\n"); -} - -void print_BE(IN const uint64_t *in, IN const uint32_t bits_num) -{ - const uint32_t qw_num = bits_num / BITS_IN_QWORD; - - // Print every 16 numbers separately - for(uint32_t i = 0; i < qw_num; ++i) { - print_uint64(in[i]); - print_newline(i); - } - - // Print the MSB QW - print_last_block((const uint8_t *)&in[qw_num], bits_num, 0); - - printf("\n"); -} - -#endif // VERBOSE diff --git a/crypto_kem/bikel3/m4f/utilities.c b/crypto_kem/bikel3/m4f/utilities.c new file mode 120000 index 00000000..846df04e --- /dev/null +++ b/crypto_kem/bikel3/m4f/utilities.c @@ -0,0 +1 @@ +../../bikel1/m4f/utilities.c \ No newline at end of file diff --git a/crypto_kem/bikel3/m4f/utilities.h b/crypto_kem/bikel3/m4f/utilities.h deleted file mode 100644 index 5bd3d1a4..00000000 --- a/crypto_kem/bikel3/m4f/utilities.h +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0" - * - * Written by Nir Drucker, Shay Gueron and Dusan Kostic, - * AWS Cryptographic Algorithms Group. - * - * Modification: 2021 Ming-Shing Chen, Tung Chou, and Markus Krausz - * - */ - -#pragma once - -// For memset -#include - -#include "types.h" - -#define ROTR64(x, s) (((x) >> (s)) | (x) << (64 - (s))) - -#if defined(__GNUC__) && __GNUC__ >= 2 -_INLINE_ uint64_t bswap_64(uint64_t x) { return __builtin_bswap64(x); } -#else -# define ROTR16(x, s) (((x) >> (s)) | (x) << (16 - (s))) - -_INLINE_ uint32_t bswap_32(uint32_t x) -{ - x = ROTR16(x, 16); - x = ((x & UINT32_C(0xff00ff00)) >> 8) | ((x & UINT32_C(0x00ff00ff)) << 8); - return x; -} - -_INLINE_ uint64_t bswap_64(uint64_t x) -{ - return bswap_32(x >> 32) | (((uint64_t)bswap_32(x)) << 32); -} -#endif - -uint64_t r_bits_vector_weight(IN const r_t *in); - -// "VALUE_BARRIER returns |a|, but prevents GCC and Clang from reasoning about -// the returned value. This is used to mitigate compilers undoing constant-time -// code, until we can express our requirements directly in the language. -// Note the compiler is aware that |VALUE_BARRIER| has no side effects and -// always has the same output for a given input. This allows it to eliminate -// dead code, move computations across loops, and vectorize." -// See: -// https://github.com/google/boringssl/commit/92b7c89e6e8ba82924b57153bea68241cc45f658 -#if(defined(__GNUC__) || defined(__clang__)) -# define VALUE_BARRIER(name, type) \ - _INLINE_ type name##_barrier(type a) \ - { \ - __asm__("" : "+r"(a) : /* no inputs */); \ - return a; \ - } -#else -# define VALUE_BARRIER(name, type) \ - _INLINE_ type name##_barrier(type a) { return a; } -#endif - -VALUE_BARRIER(u8, uint8_t) -VALUE_BARRIER(u32, uint32_t) -VALUE_BARRIER(u64, uint64_t) - -// Comparing value in a constant time manner -_INLINE_ uint32_t secure_cmp(IN const uint8_t *a, - IN const uint8_t *b, - IN const uint32_t size) -{ - volatile uint8_t res = 0; - - for(uint32_t i = 0; i < size; ++i) { - res |= (a[i] ^ b[i]); - } - - return (0 == res); -} - -// Return 1 if the arguments are equal to each other. Return 0 otherwise. -_INLINE_ uint32_t secure_cmp32(IN const uint32_t v1, IN const uint32_t v2) -{ -#if defined(__aarch64__) - uint32_t res; - __asm__ __volatile__("cmp %w[V1], %w[V2]; \n " - "cset %w[RES], EQ; \n" - : [RES] "=r"(res) - : [V1] "r"(v1), [V2] "r"(v2) - : "cc" /*The condition code flag*/); - return res; -#elif defined(__x86_64__) || defined(__i386__) - uint32_t res; - __asm__ __volatile__("xor %%edx, %%edx; \n" - "cmp %1, %2; \n " - "sete %%dl; \n" - "mov %%edx, %0; \n" - : "=r"(res) - : "r"(v1), "r"(v2) - : "rdx"); - return res; -#else - // Insecure comparison: The main purpose of secure_cmp32 is to avoid - // branches to prevent potential side channel leaks. To do that, - // we normally leverage some special CPU instructions such as "sete" - // (for __x86_64__) and "cset" (for __aarch64__). When dealing with general - // CPU architectures, the interpretation of the line below is left for the - // compiler. It could lead to an "insecure" branch. This case needs to be - // checked individually on such platforms - // (e.g., by checking the compiler-generated assembly). - return (v1 == v2 ? 1 : 0); - // the assembly code looks good on M4 - //uint32_t r = ~((v1-v2)|(v2-v1)); - //return (r>>31); -#endif -} - -// Return 0 if v1 < v2, (-1) otherwise -_INLINE_ uint32_t secure_l32_mask(IN const uint32_t v1, IN const uint32_t v2) -{ -#if defined(__aarch64__) - uint32_t res; - __asm__ __volatile__("cmp %w[V2], %w[V1]; \n " - "cset %w[RES], HI; \n" - : [RES] "=r"(res) - : [V1] "r"(v1), [V2] "r"(v2) - : "cc" /*The condition code flag*/); - return (res - 1); -#elif defined(__x86_64__) || defined(__i386__) - uint32_t res; - __asm__ __volatile__("xor %%edx, %%edx; \n" - "cmp %1, %2; \n " - "setl %%dl; \n" - "dec %%edx; \n" - "mov %%edx, %0; \n" - - : "=r"(res) - : "r"(v2), "r"(v1) - : "rdx"); - - return res; -#else - // If v1 >= v2 then the subtraction result is 0^32||(v1-v2). - // else it is 1^32||(v2-v1+1). Subsequently, negating the upper - // 32 bits gives 0 if v1 < v2 and otherwise (-1). - return ~((uint32_t)(((uint64_t)v1 - (uint64_t)v2) >> 32)); -#endif -} - -// bike_memcpy avoids the undefined behaviour of memcpy when byte_len=0 -_INLINE_ void *bike_memcpy(void *dst, const void *src, size_t byte_len) -{ - if(byte_len == 0) { - return dst; - } - - return memcpy(dst, src, byte_len); -} - -// bike_memset avoids the undefined behaviour of memset when byte_len=0 -_INLINE_ void *bike_memset(void *dst, const int ch, size_t byte_len) -{ - if(byte_len == 0) { - return dst; - } - - return memset(dst, ch, byte_len); -} - -#if defined(VERBOSE) -// Printing values in Little Endian -void print_LE(IN const uint64_t *in, IN uint32_t bits_num); - -// Printing values in Big Endian convention -void print_BE(IN const uint64_t *in, IN uint32_t bits_num); - -# if defined(PRINT_IN_BE) -// Print in Big Endian -# define print(name, in, bits_num) \ - do { \ - DMSG(name); \ - print_BE(in, bits_num); \ - } while(0) -# else -// Print in Little Endian -# define print(name, in, bits_num) \ - do { \ - DMSG(name); \ - print_LE(in, bits_num); \ - } while(0) -# endif -#else -// No prints at all -# define print(name, in, bits_num) -#endif diff --git a/crypto_kem/bikel3/m4f/utilities.h b/crypto_kem/bikel3/m4f/utilities.h new file mode 120000 index 00000000..71d5d666 --- /dev/null +++ b/crypto_kem/bikel3/m4f/utilities.h @@ -0,0 +1 @@ +../../bikel1/m4f/utilities.h \ No newline at end of file From 52ff7818e8fc088e6ed288697de5feca3ce792af Mon Sep 17 00:00:00 2001 From: Till Eifert <37eex9@riseup.net> Date: Thu, 2 Nov 2023 16:46:02 +0100 Subject: [PATCH 007/107] BIKE: remove compile flag _USE_CCM_IF_STM32F4_ and related unused code. Intention was to make use of CCM (core coupled memory) to allow (specific) platforms to run schemes with more memory consumption. --- crypto_kem/bikel1/m4f/decode.c | 8 --- crypto_kem/bikel1/m4f/run_config.h | 1 - crypto_kem/bikel3/m4f/decode.c | 12 ---- crypto_kem/bikel3/m4f/ring_ops.c | 89 +----------------------------- crypto_kem/bikel3/m4f/run_config.h | 15 +---- 5 files changed, 2 insertions(+), 123 deletions(-) mode change 100644 => 120000 crypto_kem/bikel3/m4f/run_config.h diff --git a/crypto_kem/bikel1/m4f/decode.c b/crypto_kem/bikel1/m4f/decode.c index 13eef190..3abafff9 100644 --- a/crypto_kem/bikel1/m4f/decode.c +++ b/crypto_kem/bikel1/m4f/decode.c @@ -252,12 +252,8 @@ void accumulate_unsat_syndrome(OUT upc_t *_upc, bit_sliced_adder(_upc, rotated_syndrome, LOG2_MSB(j + 1)); } #elif 71 == D -#if !defined( _UPC_SMALL_MEM_ ) && defined(_USE_CCM_IF_STM32F4_) -my_upc_t * upc = (my_upc_t*)0x10000000; -#else my_upc_t __upc; my_upc_t * upc = &__upc; -#endif //bike_memset(upc, 0, sizeof(my_upc_t)); //rotate_cmov_right(rotated_syndrome, syndrome, @@ -409,12 +405,8 @@ for(int i = 0; i < R_QWORDS; i++) { _upc->slice[7].u.qw[i] = 0; } bike_memset(upc, 0, sizeof(my_upc_t)); #elif 103 == D -#if defined(_USE_CCM_IF_STM32F4_) -my_upc_t * upc = (my_upc_t*)0x10000000; -#else my_upc_t __upc; my_upc_t * upc = &__upc; -#endif rotr_cshift((uint32_t*)rotated_syndrome, (uint32_t*)syndrome, wlist_val[0]); adder_size_k(upc, rotated_syndrome, 0, 0); diff --git a/crypto_kem/bikel1/m4f/run_config.h b/crypto_kem/bikel1/m4f/run_config.h index 475a4b7b..6f5a13bb 100644 --- a/crypto_kem/bikel1/m4f/run_config.h +++ b/crypto_kem/bikel1/m4f/run_config.h @@ -7,7 +7,6 @@ #if defined(PQM4) #define _M4_ASM_ -//#define _USE_CCM_IF_STM32F4_ // l1 can run with < 112KB SRAM. no need to use CCM #endif diff --git a/crypto_kem/bikel3/m4f/decode.c b/crypto_kem/bikel3/m4f/decode.c index 6dfa1bee..be2fcf2d 100644 --- a/crypto_kem/bikel3/m4f/decode.c +++ b/crypto_kem/bikel3/m4f/decode.c @@ -526,15 +526,9 @@ _INLINE_ void find_err1(OUT e_t *e, DEFER_CLEANUP(syndrome_t rotated_syndrome = {0}, syndrome_cleanup); //DEFER_CLEANUP(upc_t upc, upc_cleanup); -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - upc_t * upc = (upc_t*) ptr; - my_upc_t * myupc = (my_upc_t*) ptr; -#else my_upc_t __myupc; upc_t *upc = (upc_t*)&__myupc; my_upc_t * myupc = &__myupc; -#endif for(uint32_t i = 0; i < N0; i++) { // UPC must start from zero at every iteration @@ -588,15 +582,9 @@ _INLINE_ void find_err2(OUT e_t *e, { DEFER_CLEANUP(syndrome_t rotated_syndrome = {0}, syndrome_cleanup); //DEFER_CLEANUP(upc_t upc, upc_cleanup); -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - upc_t * upc = (upc_t*) ptr; - my_upc_t * myupc = (my_upc_t*) ptr; -#else my_upc_t __myupc; upc_t *upc = (upc_t*)&__myupc; my_upc_t * myupc = &__myupc; -#endif for(uint32_t i = 0; i < N0; i++) { diff --git a/crypto_kem/bikel3/m4f/ring_ops.c b/crypto_kem/bikel3/m4f/ring_ops.c index b602d359..a3722ffe 100644 --- a/crypto_kem/bikel3/m4f/ring_ops.c +++ b/crypto_kem/bikel3/m4f/ring_ops.c @@ -45,31 +45,6 @@ _INLINE_ void ring_red(OUT pad_r_t *c, IN const dbl_pad_r_t *a) #include "run_config.h" -#if defined(_USE_CCM_IF_STM32F4_) - - -#if 2048 == R_PADDED_BYTES -#define LOG_POLYLEN 11 - -#if defined(_USE_BMUL2_) -#define bitpolymul_input_transform(ao,ai,l,buf) bmul2_2048_to_4096_prepare_ebuff((uint32_t*)ao,ai,buf) -#define bitpolymul_mul(c,a,b,l,buf) bmul2_2048_to_4096_mul_ebuff(c,(const uint32_t*)a,(const uint32_t * )b,buf) -#endif - -#elif 4096 == R_PADDED_BYTES -#define LOG_POLYLEN 12 - -#if defined(_USE_BMUL2_) -#define bitpolymul_input_transform(ao,ai,l,buf) bmul2_4096_to_8192_prepare_ebuff((uint32_t*)ao,ai,buf) -#define bitpolymul_mul(c,a,b,l,buf) bmul2_4096_to_8192_mul_ebuff(c,(const uint32_t*)a,(const uint32_t * )b,buf) -#endif - -#else -error -#endif - -#else - #if 2048 == R_PADDED_BYTES #define LOG_POLYLEN 11 @@ -91,18 +66,10 @@ error error #endif -#endif - - void ring_mul_inputtransform(OUT mul_internal_t *c, IN const pad_r_t *a) { -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - bitpolymul_input_transform( (uint16_t*)c, (const uint8_t*)a , LOG_POLYLEN , ptr ); -#else bitpolymul_input_transform( (uint16_t*)c, (const uint8_t*)a , LOG_POLYLEN ); -#endif } @@ -111,21 +78,6 @@ void ring_mul_inputtransform(OUT mul_internal_t *c, IN const pad_r_t *a) void ring_mul(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b) { -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - dbl_pad_r_t * t = ptr; ptr += sizeof(dbl_pad_r_t); - - mul_internal_t *ta = ptr; ptr += sizeof(mul_internal_t); - memset(ta, 0, sizeof(mul_internal_t)); - mul_internal_t *tb = ptr; ptr += sizeof(mul_internal_t); - memset(tb, 0, sizeof(mul_internal_t)); - - bitpolymul_input_transform( (uint16_t*)ta, (const uint8_t*)a , LOG_POLYLEN , ptr ); - bitpolymul_input_transform( (uint16_t*)tb, (const uint8_t*)b , LOG_POLYLEN , ptr ); - bitpolymul_mul( (uint8_t*)t , (uint16_t *)ta, (const uint16_t *)tb , LOG_POLYLEN + 1 , ptr ); - - ring_red(c, t); -#else DEFER_CLEANUP(dbl_pad_r_t t = {0}, dbl_pad_r_cleanup); DEFER_CLEANUP(mul_internal_t ta = {0}, mul_internal_cleanup); DEFER_CLEANUP(mul_internal_t tb = {0}, mul_internal_cleanup); @@ -135,52 +87,14 @@ void ring_mul(OUT pad_r_t *c, IN const pad_r_t *a, IN const pad_r_t *b) bitpolymul_mul( (uint8_t*)&t , (uint16_t *)&ta, (const uint16_t *)&tb , LOG_POLYLEN + 1 ); ring_red(c, &t); -#endif } -#if 0 -void ring_mul_2(OUT pad_r_t *c, IN const pad_r_t *a, IN const mul_internal_t *tb) -{ -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - mul_internal_t * t = ptr; ptr += sizeof(mul_internal_t); - - mul_internal_t *ta = ptr; ptr += sizeof(mul_internal_t); - memset(ta, 0, sizeof(mul_internal_t)); - - bitpolymul_input_transform( (uint16_t*)ta, (const uint8_t*)a , LOG_POLYLEN ); - bitpolymul_mul( (uint8_t*)t , (uint16_t *)ta, (const uint16_t *)tb , LOG_POLYLEN + 1 ); - - ring_red(c, t); -#else - DEFER_CLEANUP(mul_internal_t t = {0}, mul_internal_cleanup); - DEFER_CLEANUP(mul_internal_t ta = {0}, mul_internal_cleanup); - - bitpolymul_input_transform( (uint16_t*)&ta, (const uint8_t*)a , LOG_POLYLEN ); - bitpolymul_mul( (uint8_t*)&t , (uint16_t *)&ta, (const uint16_t *)tb , LOG_POLYLEN + 1 ); - - ring_red(c, &t); -#endif -} -#else void ring_mul_2(OUT pad_r_t *c, IN const pad_r_t *a, IN const mul_internal_t *tb) { ring_mul_rep(c,a,tb); } -#endif + void ring_mul_rep(OUT pad_r_t *c, IN const pad_r_t *a, IN const mul_internal_t *tb) { -#if defined(_USE_CCM_IF_STM32F4_) - uint8_t * ptr = 0x10000000; - mul_internal_t * t = ptr; ptr += sizeof(mul_internal_t); - - mul_internal_t *ta = ptr; ptr += sizeof(mul_internal_t); - memset(ta, 0, sizeof(mul_internal_t)); - - bitpolymul_input_transform( (uint16_t*)ta, (const uint8_t*)a , LOG_POLYLEN , ptr ); - bitpolymul_mul( (uint8_t*)t , (uint16_t *)ta, (const uint16_t *)tb , LOG_POLYLEN + 1 , ptr ); - - ring_red(c, t); -#else DEFER_CLEANUP(mul_internal_t t = {0}, mul_internal_cleanup); DEFER_CLEANUP(mul_internal_t ta = {0}, mul_internal_cleanup); @@ -188,7 +102,6 @@ void ring_mul_rep(OUT pad_r_t *c, IN const pad_r_t *a, IN const mul_internal_t * bitpolymul_mul( (uint8_t*)&t , (uint16_t *)&ta, (const uint16_t *)tb , LOG_POLYLEN + 1 ); ring_red(c, &t); -#endif } diff --git a/crypto_kem/bikel3/m4f/run_config.h b/crypto_kem/bikel3/m4f/run_config.h deleted file mode 100644 index fdf0d50e..00000000 --- a/crypto_kem/bikel3/m4f/run_config.h +++ /dev/null @@ -1,14 +0,0 @@ -// Implemented by Ming-Shing Chen, Tung Chou and Markus Krausz. -// public domain - -#ifndef _RUN_CONFIG_H_ -#define _RUN_CONFIG_H_ - -#if defined(PQM4) - -#define _M4_ASM_ -//#define _USE_CCM_IF_STM32F4_ - -#endif - -#endif diff --git a/crypto_kem/bikel3/m4f/run_config.h b/crypto_kem/bikel3/m4f/run_config.h new file mode 120000 index 00000000..f4a525ea --- /dev/null +++ b/crypto_kem/bikel3/m4f/run_config.h @@ -0,0 +1 @@ +../../bikel1/m4f/run_config.h \ No newline at end of file From d2aa0e8849f24bf66870b447f6373f4eceba9304 Mon Sep 17 00:00:00 2001 From: Till Eifert <37eex9@riseup.net> Date: Mon, 6 Nov 2023 08:22:16 +0100 Subject: [PATCH 008/107] BIKE: use mupq/mupq with latest BIKE implementation --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 205a463b..bb78477e 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 205a463b95f6e5b0187bf81586d77739ad906b8b +Subproject commit bb78477ef7a70c4cafa9e6c559e3929a63266fea From 8582f47bba034524c87d8e1630553d799783a61d Mon Sep 17 00:00:00 2001 From: rpls Date: Tue, 7 Nov 2023 03:01:45 +0100 Subject: [PATCH 009/107] Implement new stack measurement HAL API (#304) * Implement new stack measurement HAL API * update mupq to current master --------- Co-authored-by: Matthias J. Kannwischer --- common/hal-mps2.c | 113 +++++++++++++++++++++++++++++++++++++++++++ common/hal-opencm3.c | 44 ++++++++++++++++- common/test.c | 17 +++++++ mupq | 2 +- 4 files changed, 174 insertions(+), 2 deletions(-) diff --git a/common/hal-mps2.c b/common/hal-mps2.c index 8ab37e32..eefa6440 100644 --- a/common/hal-mps2.c +++ b/common/hal-mps2.c @@ -163,3 +163,116 @@ size_t hal_get_stack_size(void) __asm__ volatile ("mov %0, sp" : "=r" (cur_stack)); return cur_stack - heap_end; } + +const uint32_t stackpattern = 0xDEADBEEFlu; + +static void* last_sp = NULL; + +void hal_spraystack(void) +{ + + char* _heap_end = heap_end; + asm volatile ("mov %0, sp\n" + ".L%=:\n\t" + "str %2, [%1], #4\n\t" + "cmp %1, %0\n\t" + "blt .L%=\n\t" + : "+r" (last_sp), "+r" (_heap_end) : "r" (stackpattern) : "cc", "memory"); +} + +size_t hal_checkstack(void) +{ + size_t result = 0; + asm volatile("sub %0, %1, %2\n" + ".L%=:\n\t" + "ldr ip, [%2], #4\n\t" + "cmp ip, %3\n\t" + "ite eq\n\t" + "subeq %0, #4\n\t" + "bne .LE%=\n\t" + "cmp %2, %1\n\t" + "blt .L%=\n\t" + ".LE%=:\n" + : "+r"(result) : "r" (last_sp), "r" (heap_end), "r" (stackpattern) : "ip", "cc"); + return result; +} + +/* Implement some system calls to shut up the linker warnings */ + +#include +#undef errno +extern int errno; + +int __wrap__open(char *file, int flags, int mode) +{ + (void) file; + (void) flags; + (void) mode; + errno = ENOSYS; + return -1; +} + +int __wrap__close(int fd) +{ + errno = ENOSYS; + (void) fd; + return -1; +} + +#include + +int __wrap__fstat(int fd, struct stat* buf) +{ + (void) fd; + (void) buf; + errno = ENOSYS; + return -1; +} + +int __wrap__getpid(void) +{ + errno = ENOSYS; + return -1; +} + +int __wrap__isatty(int file) +{ + (void) file; + errno = ENOSYS; + return 0; +} + +int __wrap__kill(int pid, int sig) +{ + (void) pid; + (void) sig; + errno = ENOSYS; + return -1; +} + +int __wrap__lseek(int fd, int ptr, int dir) +{ + (void) fd; + (void) ptr; + (void) dir; + errno = ENOSYS; + return -1; +} + +int __wrap__read(int fd, char* ptr, int len) +{ + (void) fd; + (void) ptr; + (void) len; + errno = ENOSYS; + return -1; +} + +int __wrap__write(int fd, const char* ptr, int len) +{ + (void) fd; + (void) ptr; + (void) len; + errno = ENOSYS; + return -1; +} diff --git a/common/hal-opencm3.c b/common/hal-opencm3.c index a27ceba7..8bc1e597 100644 --- a/common/hal-opencm3.c +++ b/common/hal-opencm3.c @@ -383,16 +383,58 @@ void* __wrap__sbrk (int incr) size_t hal_get_stack_size(void) { register char* cur_stack; - __asm__ volatile ("mov %0, sp" : "=r" (cur_stack)); + asm volatile ("mov %0, sp" : "=r" (cur_stack)); return cur_stack - heap_end; } +const uint32_t stackpattern = 0xDEADBEEFlu; + +static void* last_sp = NULL; + +void hal_spraystack(void) +{ + + char* _heap_end = heap_end; + asm volatile ("mov %0, sp\n" + ".L%=:\n\t" + "str %2, [%1], #4\n\t" + "cmp %1, %0\n\t" + "blt .L%=\n\t" + : "+r" (last_sp), "+r" (_heap_end) : "r" (stackpattern) : "cc", "memory"); +} + +size_t hal_checkstack(void) +{ + size_t result = 0; + asm volatile("sub %0, %1, %2\n" + ".L%=:\n\t" + "ldr ip, [%2], #4\n\t" + "cmp ip, %3\n\t" + "ite eq\n\t" + "subeq %0, #4\n\t" + "bne .LE%=\n\t" + "cmp %2, %1\n\t" + "blt .L%=\n\t" + ".LE%=:\n" + : "+r"(result) : "r" (last_sp), "r" (heap_end), "r" (stackpattern) : "ip", "cc"); + return result; +} + /* Implement some system calls to shut up the linker warnings */ #include #undef errno extern int errno; +int __wrap__open(char *file, int flags, int mode) +{ + (void) file; + (void) flags; + (void) mode; + errno = ENOSYS; + return -1; +} + int __wrap__close(int fd) { errno = ENOSYS; diff --git a/common/test.c b/common/test.c index d3878dda..987d12d2 100644 --- a/common/test.c +++ b/common/test.c @@ -128,6 +128,14 @@ static void memory_timing_test(void) #define CLOCK_TEST CLOCK_BENCHMARK #endif +void stacktest(size_t size) +{ + volatile uint32_t mem[size] __attribute__((unused)); + for (unsigned i = 0; i < size; ++i) { + mem[i] = 0; + } +} + int main(void) { hal_setup(CLOCK_TEST); @@ -136,6 +144,15 @@ int main(void) unsigned rnd; randombytes((unsigned char*) &rnd, sizeof(unsigned)); send_unsigned("Random number", rnd); + size_t stack; + hal_spraystack(); + stacktest(100); + stack = hal_checkstack(); + send_unsigned("stackusage1", stack); + hal_spraystack(); + stacktest(200); + stack = hal_checkstack(); + send_unsigned("stackusage2", stack); #if defined(SRAM_TIMING_TEST) memory_timing_test(); #endif diff --git a/mupq b/mupq index 205a463b..9998553b 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 205a463b95f6e5b0187bf81586d77739ad906b8b +Subproject commit 9998553b42bd224fc391f156d2f1bc00bbddd543 From d969ad404b5218d240680be1eb7a3b57ad2977e6 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 25 Oct 2023 20:35:41 +0800 Subject: [PATCH 010/107] add reference implementation of MAYO --- crypto_sign/mayo1/m4f/LICENSE | 201 +++++ crypto_sign/mayo1/m4f/aes_ctr.c | 1 + crypto_sign/mayo1/m4f/aes_ctr.h | 1 + crypto_sign/mayo1/m4f/api.c | 1 + crypto_sign/mayo1/m4f/api.h | 1 + crypto_sign/mayo1/m4f/asm_params.h | 5 + crypto_sign/mayo1/m4f/bitsliced_arithmetic.h | 1 + .../mayo1/m4f/bitsliced_arithmetic_128.h | 1 + .../mayo1/m4f/bitsliced_arithmetic_64.h | 1 + .../mayo1/m4f/bitsliced_arithmetic_96.h | 1 + .../mayo1/m4f/bitsliced_arithmetic_m4f.c | 434 +++++++++ crypto_sign/mayo1/m4f/debug_bench_tools.h | 1 + crypto_sign/mayo1/m4f/echelon_form.h | 1 + crypto_sign/mayo1/m4f/ef.S | 833 ++++++++++++++++++ crypto_sign/mayo1/m4f/gf16_bitslice.i | 54 ++ crypto_sign/mayo1/m4f/gf16_inverse.i | 24 + crypto_sign/mayo1/m4f/gf16_madd_bitsliced.i | 38 + crypto_sign/mayo1/m4f/m4f_asm.h | 31 + crypto_sign/mayo1/m4f/matmul.S | 48 + crypto_sign/mayo1/m4f/matmul.i | 530 +++++++++++ crypto_sign/mayo1/m4f/mayo.c | 1 + crypto_sign/mayo1/m4f/mayo.h | 1 + crypto_sign/mayo1/m4f/mem.c | 1 + crypto_sign/mayo1/m4f/mem.h | 1 + crypto_sign/mayo1/m4f/params.c | 1 + crypto_sign/mayo1/m4f/rng.h | 1 + crypto_sign/mayo1/m4f/simple_arithmetic.h | 1 + crypto_sign/mayo1/m4f/verification.S | 42 + crypto_sign/mayo1/m4f/verification.i | 301 +++++++ crypto_sign/mayo2/m4f/LICENSE | 201 +++++ crypto_sign/mayo2/m4f/aes_ctr.c | 1 + crypto_sign/mayo2/m4f/aes_ctr.h | 1 + crypto_sign/mayo2/m4f/api.c | 1 + crypto_sign/mayo2/m4f/api.h | 1 + crypto_sign/mayo2/m4f/asm_params.h | 5 + crypto_sign/mayo2/m4f/bitsliced_arithmetic.h | 1 + .../mayo2/m4f/bitsliced_arithmetic_128.h | 1 + .../mayo2/m4f/bitsliced_arithmetic_64.h | 1 + .../mayo2/m4f/bitsliced_arithmetic_96.h | 1 + .../mayo2/m4f/bitsliced_arithmetic_m4f.c | 1 + crypto_sign/mayo2/m4f/debug_bench_tools.h | 1 + crypto_sign/mayo2/m4f/echelon_form.h | 1 + crypto_sign/mayo2/m4f/ef.S | 1 + crypto_sign/mayo2/m4f/gf16_bitslice.i | 1 + crypto_sign/mayo2/m4f/gf16_inverse.i | 1 + crypto_sign/mayo2/m4f/gf16_madd_bitsliced.i | 1 + crypto_sign/mayo2/m4f/m4f_asm.h | 1 + crypto_sign/mayo2/m4f/matmul.S | 1 + crypto_sign/mayo2/m4f/matmul.i | 1 + crypto_sign/mayo2/m4f/mayo.c | 1 + crypto_sign/mayo2/m4f/mayo.h | 1 + crypto_sign/mayo2/m4f/mem.c | 1 + crypto_sign/mayo2/m4f/mem.h | 1 + crypto_sign/mayo2/m4f/params.c | 1 + crypto_sign/mayo2/m4f/rng.h | 1 + crypto_sign/mayo2/m4f/simple_arithmetic.h | 1 + crypto_sign/mayo2/m4f/verification.S | 1 + crypto_sign/mayo2/m4f/verification.i | 1 + crypto_sign/mayo3/m4f/LICENSE | 201 +++++ crypto_sign/mayo3/m4f/aes_ctr.c | 1 + crypto_sign/mayo3/m4f/aes_ctr.h | 1 + crypto_sign/mayo3/m4f/api.c | 1 + crypto_sign/mayo3/m4f/api.h | 1 + crypto_sign/mayo3/m4f/asm_params.h | 5 + crypto_sign/mayo3/m4f/bitsliced_arithmetic.h | 1 + .../mayo3/m4f/bitsliced_arithmetic_128.h | 1 + .../mayo3/m4f/bitsliced_arithmetic_64.h | 1 + .../mayo3/m4f/bitsliced_arithmetic_96.h | 1 + .../mayo3/m4f/bitsliced_arithmetic_m4f.c | 1 + crypto_sign/mayo3/m4f/debug_bench_tools.h | 1 + crypto_sign/mayo3/m4f/echelon_form.h | 1 + crypto_sign/mayo3/m4f/ef.S | 1 + crypto_sign/mayo3/m4f/gf16_bitslice.i | 1 + crypto_sign/mayo3/m4f/gf16_inverse.i | 1 + crypto_sign/mayo3/m4f/gf16_madd_bitsliced.i | 1 + crypto_sign/mayo3/m4f/m4f_asm.h | 1 + crypto_sign/mayo3/m4f/matmul.S | 1 + crypto_sign/mayo3/m4f/matmul.i | 1 + crypto_sign/mayo3/m4f/mayo.c | 1 + crypto_sign/mayo3/m4f/mayo.h | 1 + crypto_sign/mayo3/m4f/mem.c | 1 + crypto_sign/mayo3/m4f/mem.h | 1 + crypto_sign/mayo3/m4f/params.c | 1 + crypto_sign/mayo3/m4f/rng.h | 1 + crypto_sign/mayo3/m4f/simple_arithmetic.h | 1 + crypto_sign/mayo3/m4f/verification.S | 1 + crypto_sign/mayo3/m4f/verification.i | 1 + mupq | 2 +- skiplist.py | 8 +- 89 files changed, 3032 insertions(+), 2 deletions(-) create mode 100644 crypto_sign/mayo1/m4f/LICENSE create mode 120000 crypto_sign/mayo1/m4f/aes_ctr.c create mode 120000 crypto_sign/mayo1/m4f/aes_ctr.h create mode 120000 crypto_sign/mayo1/m4f/api.c create mode 120000 crypto_sign/mayo1/m4f/api.h create mode 100644 crypto_sign/mayo1/m4f/asm_params.h create mode 120000 crypto_sign/mayo1/m4f/bitsliced_arithmetic.h create mode 120000 crypto_sign/mayo1/m4f/bitsliced_arithmetic_128.h create mode 120000 crypto_sign/mayo1/m4f/bitsliced_arithmetic_64.h create mode 120000 crypto_sign/mayo1/m4f/bitsliced_arithmetic_96.h create mode 100644 crypto_sign/mayo1/m4f/bitsliced_arithmetic_m4f.c create mode 120000 crypto_sign/mayo1/m4f/debug_bench_tools.h create mode 120000 crypto_sign/mayo1/m4f/echelon_form.h create mode 100644 crypto_sign/mayo1/m4f/ef.S create mode 100644 crypto_sign/mayo1/m4f/gf16_bitslice.i create mode 100644 crypto_sign/mayo1/m4f/gf16_inverse.i create mode 100644 crypto_sign/mayo1/m4f/gf16_madd_bitsliced.i create mode 100644 crypto_sign/mayo1/m4f/m4f_asm.h create mode 100644 crypto_sign/mayo1/m4f/matmul.S create mode 100644 crypto_sign/mayo1/m4f/matmul.i create mode 120000 crypto_sign/mayo1/m4f/mayo.c create mode 120000 crypto_sign/mayo1/m4f/mayo.h create mode 120000 crypto_sign/mayo1/m4f/mem.c create mode 120000 crypto_sign/mayo1/m4f/mem.h create mode 120000 crypto_sign/mayo1/m4f/params.c create mode 120000 crypto_sign/mayo1/m4f/rng.h create mode 120000 crypto_sign/mayo1/m4f/simple_arithmetic.h create mode 100644 crypto_sign/mayo1/m4f/verification.S create mode 100644 crypto_sign/mayo1/m4f/verification.i create mode 100644 crypto_sign/mayo2/m4f/LICENSE create mode 120000 crypto_sign/mayo2/m4f/aes_ctr.c create mode 120000 crypto_sign/mayo2/m4f/aes_ctr.h create mode 120000 crypto_sign/mayo2/m4f/api.c create mode 120000 crypto_sign/mayo2/m4f/api.h create mode 100644 crypto_sign/mayo2/m4f/asm_params.h create mode 120000 crypto_sign/mayo2/m4f/bitsliced_arithmetic.h create mode 120000 crypto_sign/mayo2/m4f/bitsliced_arithmetic_128.h create mode 120000 crypto_sign/mayo2/m4f/bitsliced_arithmetic_64.h create mode 120000 crypto_sign/mayo2/m4f/bitsliced_arithmetic_96.h create mode 120000 crypto_sign/mayo2/m4f/bitsliced_arithmetic_m4f.c create mode 120000 crypto_sign/mayo2/m4f/debug_bench_tools.h create mode 120000 crypto_sign/mayo2/m4f/echelon_form.h create mode 120000 crypto_sign/mayo2/m4f/ef.S create mode 120000 crypto_sign/mayo2/m4f/gf16_bitslice.i create mode 120000 crypto_sign/mayo2/m4f/gf16_inverse.i create mode 120000 crypto_sign/mayo2/m4f/gf16_madd_bitsliced.i create mode 120000 crypto_sign/mayo2/m4f/m4f_asm.h create mode 120000 crypto_sign/mayo2/m4f/matmul.S create mode 120000 crypto_sign/mayo2/m4f/matmul.i create mode 120000 crypto_sign/mayo2/m4f/mayo.c create mode 120000 crypto_sign/mayo2/m4f/mayo.h create mode 120000 crypto_sign/mayo2/m4f/mem.c create mode 120000 crypto_sign/mayo2/m4f/mem.h create mode 120000 crypto_sign/mayo2/m4f/params.c create mode 120000 crypto_sign/mayo2/m4f/rng.h create mode 120000 crypto_sign/mayo2/m4f/simple_arithmetic.h create mode 120000 crypto_sign/mayo2/m4f/verification.S create mode 120000 crypto_sign/mayo2/m4f/verification.i create mode 100644 crypto_sign/mayo3/m4f/LICENSE create mode 120000 crypto_sign/mayo3/m4f/aes_ctr.c create mode 120000 crypto_sign/mayo3/m4f/aes_ctr.h create mode 120000 crypto_sign/mayo3/m4f/api.c create mode 120000 crypto_sign/mayo3/m4f/api.h create mode 100644 crypto_sign/mayo3/m4f/asm_params.h create mode 120000 crypto_sign/mayo3/m4f/bitsliced_arithmetic.h create mode 120000 crypto_sign/mayo3/m4f/bitsliced_arithmetic_128.h create mode 120000 crypto_sign/mayo3/m4f/bitsliced_arithmetic_64.h create mode 120000 crypto_sign/mayo3/m4f/bitsliced_arithmetic_96.h create mode 120000 crypto_sign/mayo3/m4f/bitsliced_arithmetic_m4f.c create mode 120000 crypto_sign/mayo3/m4f/debug_bench_tools.h create mode 120000 crypto_sign/mayo3/m4f/echelon_form.h create mode 120000 crypto_sign/mayo3/m4f/ef.S create mode 120000 crypto_sign/mayo3/m4f/gf16_bitslice.i create mode 120000 crypto_sign/mayo3/m4f/gf16_inverse.i create mode 120000 crypto_sign/mayo3/m4f/gf16_madd_bitsliced.i create mode 120000 crypto_sign/mayo3/m4f/m4f_asm.h create mode 120000 crypto_sign/mayo3/m4f/matmul.S create mode 120000 crypto_sign/mayo3/m4f/matmul.i create mode 120000 crypto_sign/mayo3/m4f/mayo.c create mode 120000 crypto_sign/mayo3/m4f/mayo.h create mode 120000 crypto_sign/mayo3/m4f/mem.c create mode 120000 crypto_sign/mayo3/m4f/mem.h create mode 120000 crypto_sign/mayo3/m4f/params.c create mode 120000 crypto_sign/mayo3/m4f/rng.h create mode 120000 crypto_sign/mayo3/m4f/simple_arithmetic.h create mode 120000 crypto_sign/mayo3/m4f/verification.S create mode 120000 crypto_sign/mayo3/m4f/verification.i diff --git a/crypto_sign/mayo1/m4f/LICENSE b/crypto_sign/mayo1/m4f/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/crypto_sign/mayo1/m4f/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crypto_sign/mayo1/m4f/aes_ctr.c b/crypto_sign/mayo1/m4f/aes_ctr.c new file mode 120000 index 00000000..318ca2f2 --- /dev/null +++ b/crypto_sign/mayo1/m4f/aes_ctr.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/aes_ctr.c \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/aes_ctr.h b/crypto_sign/mayo1/m4f/aes_ctr.h new file mode 120000 index 00000000..5cb7eba4 --- /dev/null +++ b/crypto_sign/mayo1/m4f/aes_ctr.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/aes_ctr.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/api.c b/crypto_sign/mayo1/m4f/api.c new file mode 120000 index 00000000..57555ed8 --- /dev/null +++ b/crypto_sign/mayo1/m4f/api.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/api.c \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/api.h b/crypto_sign/mayo1/m4f/api.h new file mode 120000 index 00000000..8b512805 --- /dev/null +++ b/crypto_sign/mayo1/m4f/api.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/api.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/asm_params.h b/crypto_sign/mayo1/m4f/asm_params.h new file mode 100644 index 00000000..cf81bfdb --- /dev/null +++ b/crypto_sign/mayo1/m4f/asm_params.h @@ -0,0 +1,5 @@ +#define M 64 +#define N 66 +#define K 9 +#define O 8 +#define V (N-O) diff --git a/crypto_sign/mayo1/m4f/bitsliced_arithmetic.h b/crypto_sign/mayo1/m4f/bitsliced_arithmetic.h new file mode 120000 index 00000000..28b9724b --- /dev/null +++ b/crypto_sign/mayo1/m4f/bitsliced_arithmetic.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/bitsliced_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/bitsliced_arithmetic_128.h b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_128.h new file mode 120000 index 00000000..eff0e2af --- /dev/null +++ b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_128.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/bitsliced_arithmetic_128.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/bitsliced_arithmetic_64.h b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_64.h new file mode 120000 index 00000000..af07dc85 --- /dev/null +++ b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_64.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/bitsliced_arithmetic_64.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/bitsliced_arithmetic_96.h b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_96.h new file mode 120000 index 00000000..74995681 --- /dev/null +++ b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_96.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/bitsliced_arithmetic_96.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/bitsliced_arithmetic_m4f.c b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_m4f.c new file mode 100644 index 00000000..990572ae --- /dev/null +++ b/crypto_sign/mayo1/m4f/bitsliced_arithmetic_m4f.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include "bitsliced_arithmetic.h" +#include +#include +#include +#include "m4f_asm.h" + +// This implements arithmetic for bitsliced vectors of m field elements in Z_2[x]/(x^4+x+1) +// A bitsliced vector is consists of m/32 * 4 consecutive uint32_t's +// the first m/32 uint32_t's are the degree-0 terms, the following m/3 uint32_t's are the degree-1 terms and so on. + +void bitsliced_m_vec_mul_add(int m_legs, const uint32_t *in, unsigned char a, uint32_t *acc) { + const uint32_t *in0 = in; + const uint32_t *in1 = in + m_legs; + const uint32_t *in2 = in + 2 * m_legs; + const uint32_t *in3 = in + 3 * m_legs; + + uint32_t *acc0 = acc; + uint32_t *acc1 = acc + m_legs; + uint32_t *acc2 = acc + 2 * m_legs; + uint32_t *acc3 = acc + 3 * m_legs; + + // terms of a + uint32_t aa = a; + uint32_t a0 = -(aa & 1); + uint32_t a1 = -((aa >> 1) & 1); + uint32_t a2 = -((aa >> 2) & 1); + uint32_t a3 = -((aa >> 3) & 1); + + uint32_t x, y, z; + for (int i = 0; i < m_legs; i++) { + // deg 0 term of a; + acc0[i] ^= a0 & in0[i]; + acc1[i] ^= a0 & in1[i]; + acc2[i] ^= a0 & in2[i]; + acc3[i] ^= a0 & in3[i]; + + // deg 1 term of a; + x = in0[i] ^ in3[i]; + acc0[i] ^= a1 & in3[i]; + acc1[i] ^= a1 & x; + acc2[i] ^= a1 & in1[i]; + acc3[i] ^= a1 & in2[i]; + + // deg 2 term of a + y = in3[i] ^ in2[i]; + acc0[i] ^= a2 & in2[i]; + acc1[i] ^= a2 & y; + acc2[i] ^= a2 & x; + acc3[i] ^= a2 & in1[i]; + + // deg 3 term of a + z = in2[i] ^ in1[i]; + acc0[i] ^= a3 & in1[i]; + acc1[i] ^= a3 & z; + acc2[i] ^= a3 & y; + acc3[i] ^= a3 & x; + } +} + + +void bitsliced_m_upper(int m_legs, const uint32_t *in, uint32_t *out, int size) { + int m_vecs_stored = 0; + for (int r = 0; r < size; r++) { + for (int c = r; c < size; c++) { + bitsliced_m_vec_copy(m_legs, in + m_legs * 4 * (r * size + c), out + m_legs * 4 * m_vecs_stored ); + if (r != c) { + bitsliced_m_vec_add(m_legs, in + m_legs * 4 * (c * size + r), out + m_legs * 4 * m_vecs_stored ); + } + m_vecs_stored ++; + } + } +} + +void bitslice_m_vec(int m_legs, const unsigned char *in, uint32_t *out) { + uint32_t *out0 = out; + uint32_t *out1 = out + m_legs; + uint32_t *out2 = out + 2 * m_legs; + uint32_t *out3 = out + 3 * m_legs; + + for (int leg = 0; leg < m_legs; leg++) { + uint32_t d0 = 0, d1 = 0, d2 = 0, d3 = 0; + for (int i = 31; i >= 0; i--) { + d0 = (d0 << 1) ^ (in[32 * leg + i] & 1); + d1 = (d1 << 1) ^ ((in[32 * leg + i] & 2) >> 1); + d2 = (d2 << 1) ^ ((in[32 * leg + i] & 4) >> 2); + d3 = (d3 << 1) ^ ((in[32 * leg + i] & 8) >> 3); + } + out0[leg] = d0; + out1[leg] = d1; + out2[leg] = d2; + out3[leg] = d3; + } +} + +void unbitslice_m_vec(int m_legs, const uint32_t *in, unsigned char *out) { + const uint32_t *in0 = in; + const uint32_t *in1 = in + m_legs; + const uint32_t *in2 = in + 2 * m_legs; + const uint32_t *in3 = in + 3 * m_legs; + + for (int leg = 0; leg < m_legs; leg ++) { + for (int i = 0; i < 32; i++) { + out[leg * 32 + i] = ((in0[leg] >> i) & 1) ^ + (((in1[leg] >> i) & 1) << 1) ^ + (((in2[leg] >> i) & 1) << 2) ^ + (((in3[leg] >> i) & 1) << 3) ; + } + } +} + +void P1_times_O(const mayo_params_t* p, const uint32_t* P1, const unsigned char* O, uint32_t* acc){ + (void) p; + mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm(acc, P1, O); +} + +void P1P1t_times_O(const mayo_params_t* p, const uint32_t* P1, const unsigned char* O, uint32_t* acc){ + (void) p; + const int param_m = M_MAX; + const int m_legs = param_m / 32; + const int param_o = O_MAX; + const int param_v = V_MAX; + int bs_mat_entries_used; + + for (int i = 0; i < m_legs; i++) + { + bs_mat_entries_used = 0; + for (int r = 0; r < param_v - 1; r++) + { + bs_mat_entries_used++; + int c = r + 1; + mayo_expand_sk_computeL_inner1_m4f(acc + m_legs * 4 * (r * param_o) + i, P1 + m_legs * 4 * bs_mat_entries_used + i, O + c * param_o, O + param_v * param_o); + bs_mat_entries_used += param_v - (r + 1); + } + } + + for (int i = 0; i < m_legs; i++) + { + bs_mat_entries_used = 0; + for (int c = 1; c < param_v; c++) + { + mayo_expand_sk_computeL_inner2_m4f(acc + m_legs * 4 * (c * param_o) + i, P1 + m_legs * 4 * (bs_mat_entries_used + 1) + i , O, c); + bs_mat_entries_used += 1; + } + } +} + +void P1_times_Vt(const mayo_params_t* p, const uint32_t* P1, const unsigned char* V, uint32_t* acc){ + (void) p; + mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm(acc, P1, V); +} + + +// multiplies the transpose of a single matrix with m bitsliced matrices and adds result to acc +void mul_add_mat_trans_x_bitsliced_m_mat(int m_legs, const unsigned char *mat, const uint32_t *bs_mat, uint32_t *acc, int mat_rows, int mat_cols, int bs_mat_cols) { + + for (int r = 0; r < mat_cols; r++) { + for (int c = 0; c < mat_rows; c++) { + for (int k = 0; k < bs_mat_cols; k += 1) { +#if defined(MAYO_VARIANT) && (M_MAX == 64) + (void) m_legs; + bitsliced_64_vec_mul_add((uint64_t *)bs_mat + 4 * (c * bs_mat_cols + k), mat[c * mat_cols + r], (uint64_t *) acc + 4 * (r * bs_mat_cols + k)); +#elif defined(MAYO_VARIANT) && (M_MAX == 96) + (void) m_legs; + bitsliced_96_vec_mul_add(bs_mat + 12 * (c * bs_mat_cols + k), mat[c * mat_cols + r], acc + 12 * (r * bs_mat_cols + k)); +#elif defined(MAYO_VARIANT) && (M_MAX == 128) + (void) m_legs; + bitsliced_128_vec_mul_add((uint64_t *)bs_mat + 8 * (c * bs_mat_cols + k), mat[c * mat_cols + r], (uint64_t *) acc + 8 * (r * bs_mat_cols + k)); +#else + bitsliced_m_vec_mul_add(m_legs, bs_mat + m_legs * 4 * (c * bs_mat_cols + k), mat[c * mat_cols + r], acc + m_legs * 4 * (r * bs_mat_cols + k)); +#endif + } + } + } +} + +// multiplies a single matrix with m bitsliced matrices and adds result to acc +void mul_add_mat_x_bitsliced_m_mat(int m_legs, const unsigned char *mat, const uint32_t *bs_mat, uint32_t *acc, int mat_rows, int mat_cols, int bs_mat_cols) { + (void) m_legs; + if(mat_rows == K_MAX && mat_cols == V_MAX && bs_mat_cols == O_MAX){ + mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm(acc, mat, bs_mat); + } else if(mat_rows == K_MAX && mat_cols == V_MAX && bs_mat_cols == K_MAX){ + mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm(acc, mat, bs_mat); + } +} + +// compute P * S^t = [ P1 P2 ] * [S1] = [P1*S1 + P2*S2] in bitsliced form +// [ 0 P3 ] [S2] [ P3*S2] +void bitsliced_m_calculate_PS_m4f(const uint32_t *P1, const uint32_t *P2, const uint32_t *P3, const unsigned char *S, uint32_t *PS) { + const int m = M_MAX; + const int v = V_MAX; + const int o = O_MAX; + const int k = K_MAX; + const int n = o + v; + const int m_legs = m / 32; + + #if N_MAX > 78 + uint32_t accumulator[16 * M_MAX * N_MAX / 8] = {0}; + int P1_used; + int P3_used; + for (int col = 0; col < k; col++) { + memset(accumulator, 0, sizeof accumulator); + P1_used = 0; + for (int row = 0; row < v; row++) { + bitsliced_m_calculate_PS_m4f_stack_asm(accumulator + ( row * 16 )*m_legs * 4 , P1 + P1_used * m_legs * 4, S + col*n + row, v-row); + P1_used += v-row; + bitsliced_m_calculate_PS_m4f_stack_asm(accumulator + ( row * 16 )*m_legs * 4 , P2 + (row * o)*m_legs * 4, S + (col * n) + v, o); + } + + P3_used = 0; + for (int row = v; row < n; row++) { + bitsliced_m_calculate_PS_m4f_stack_asm(accumulator + ( row * 16 )*m_legs * 4 , P3 + P3_used * m_legs * 4, S + col * n + row, n-row); + P3_used += (n-row); + + } + bitsliced_multiply_bins_stack_asm(accumulator, PS + col * m_legs * 4, n); + } + #else + uint32_t accumulator[16 * M_MAX * K_MAX * N_MAX / 8] = {0}; + int P1_used = 0; + + //bitsliced_m_calculate_PS_m4f_P1_asm(accumulator, P1, S); + for (int row = 0; row < v; row++) { + + bitsliced_m_calculate_PS_m4f_asm(accumulator + ( (row * k) * 16)*m_legs * 4, P1 + P1_used * m_legs * 4, S+row, v-row); + P1_used += (v-row); + bitsliced_m_calculate_PS_m4f_asm(accumulator + ( (row * k) * 16)*m_legs * 4, P2 + (row * o)*m_legs * 4, S+v, o); + } + + int P3_used = 0; + for (int row = v; row < n; row++) { + bitsliced_m_calculate_PS_m4f_asm(accumulator + ( (row * k) * 16)*m_legs * 4, P3 + P3_used * m_legs * 4, S+row, n-row); + P3_used += (n-row); + } + + // multiply stuff according to the bins of the accumulator and add to PS. + bitsliced_multiply_bins_asm(accumulator, PS, n*k); + #endif +} + + +void bitsliced_m_calculate_SPS_m4f(const uint32_t *PS, const unsigned char *S, uint32_t *SPS){ + const int k = K_MAX; + const int m = M_MAX; + uint32_t accumulator[16*M_MAX*K_MAX*K_MAX/8] = {0}; + const int m_legs = m/32; + + for (int col = 0; col < k; col += 1) { + bitsliced_m_calculate_SPS_m4f_asm(accumulator + ( (col) * 16 )*m_legs * 4, PS + (col) * m_legs * 4, S); + } + + bitsliced_multiply_bins_asm(accumulator, SPS, k*k); +} + +void bitsliced_m_calculate_PS_SPS(const uint32_t *bitsliced_P1, const uint32_t *bitsliced_P2, const uint32_t *bitsliced_P3, const unsigned char *S, + const int m, const int v, const int o, const int k, uint32_t *bitsliced_SPS){ + (void) m; + (void) v; + (void) o; + (void) k; + // compute P * S^t = {(P1, P2), (0, P3)} * S^t = {(P1*S1 + P2*S2), (P3 * S2)} + alignas (32) uint32_t bitsliced_PS[N_MAX * K_MAX * M_MAX / 8]; + + bitsliced_m_calculate_PS_m4f(bitsliced_P1, bitsliced_P2, bitsliced_P3, S, bitsliced_PS); + bitsliced_m_calculate_SPS_m4f(bitsliced_PS, S, bitsliced_SPS); +} + + + +#define PARAM_m(p) PARAM_NAME(m) +#define PARAM_o(p) PARAM_NAME(o) +#define PARAM_A_cols(p) PARAM_NAME(A_cols) +#define PARAM_k(p) PARAM_NAME(k) +#define MAYO_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAYO_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +// assembly +void ef_bitslice_asm(uint32_t *a_bs, unsigned char *a); +void ef_unbitslice_asm(unsigned char *a, uint32_t *a_bs); +uint8_t ef_inner1_asm(uint32_t *pivot_row, uint32_t *a_bs_row, int pivot_col, int pivot_row_lower_bound, int pivot_row_ctr, uint8_t *pivot_is_zero, int row_upper_bound); +void ef_inner2_asm(uint32_t *pivot_row2, uint32_t *pivot_row, uint8_t pivot); +void ef_inner3_asm(uint32_t *a_bs_row, uint32_t *pivot_row, int pivot_row_ctr, int pivot_row_lower_bound, int pivot_row_upper_bound, int pivot_is_zero); +int ef_inner4_asm(uint32_t *a_bs, uint32_t *pivot_row, int pivot_row_lower_bound, int pivot_row_ctr, int pivot_col, int pivot_is_nonzero); +void backsub_inner_asm(uint8_t *a1, uint8_t *a2, uint8_t *a3, int correct_column, int r); + + +// put matrix in row echelon form with ones on first nonzero entries *in +// constant time* +static void EF(unsigned char *A, int nrows, int ncols) { + + uint32_t _pivot_row[(K_MAX * O_MAX + 1 + 31) / 32 * 4]; + uint32_t _pivot_row2[(K_MAX * O_MAX + 1 + 31) / 32 * 4]; + uint32_t bitsliced_A[((K_MAX * O_MAX + 1 + 31) / 32) * 4 * M_MAX]; + + int legs = (ncols + 31) / 32; + + + ef_bitslice_asm(bitsliced_A, A); + + // pivot row is secret, pivot col is not + + //unsigned char inverse; + int pivot_row = 0; + for (int pivot_col = 0; pivot_col < ncols; pivot_col++) { + + int pivot_row_lower_bound = MAYO_MAX(0, pivot_col + nrows - ncols); + int pivot_row_upper_bound = MAYO_MIN(nrows - 1, pivot_col); + // the pivot row is guaranteed to be between these lower and upper bounds if + // A has full rank + + // zero out pivot row + for (int i = 0; i < legs * 4; i++) { + _pivot_row[i] = 0; + } + + // try to get a pivot row in constant time + unsigned char pivot = 0; + unsigned char pivot_is_zero = 1; + + + // make sure pivot is non-zero + pivot = ef_inner1_asm(_pivot_row, bitsliced_A + pivot_row_lower_bound*legs*4, pivot_col, pivot_row_lower_bound, pivot_row, &pivot_is_zero, MAYO_MIN(nrows - 1, pivot_row_upper_bound + 16)); + + ef_inner2_asm(_pivot_row2, _pivot_row, pivot); + + // conditionally write pivot row to the correct row, if there is a nonzero + // pivot + ef_inner3_asm(bitsliced_A + pivot_row_lower_bound * legs * 4, _pivot_row2, pivot_row, pivot_row_lower_bound, pivot_row_upper_bound, pivot_is_zero ? 1 : 0); + + // eliminate entries below pivot + pivot_row = ef_inner4_asm(bitsliced_A, _pivot_row2, pivot_row_lower_bound, pivot_row, pivot_col, pivot_is_zero ? 0 : 1); + } + + // unbitslice the matrix A + for (int i = 0; i < nrows; i++) { + ef_unbitslice_asm(A + i*ncols, bitsliced_A + i * legs * 4); + } +} + + +// sample a solution x to Ax = y, with r used as randomness +// require: +// - A is a matrix with m rows and k*o+1 collumns (values in the last collum are +// not important, they will be overwritten by y) in row major order +// - y is a vector with m elements +// - r and x are k*o bytes long +// return: 1 on success, 0 on failure +int sample_solution(const mayo_params_t *p, unsigned char *A, + const unsigned char *y, const unsigned char *r, + unsigned char *x, int _k, int _o, int _m, int _A_cols) { + int finished; + int col_upper_bound; + int correct_column; + (void) _k; + (void) _o; + (void) _m; + (void) _A_cols; + const int k = PARAM_k(p); + const int o = PARAM_o(p); + const int m = PARAM_m(p); + const int A_cols = PARAM_A_cols(p); + + (void) p; + + // x <- r + for (int i = 0; i < k * o; i++) { + x[i] = r[i]; + } + + // compute Ar; + unsigned char Ar[M_MAX]; + for (int i = 0; i < m; i++) { + A[k * o + i * (k * o + 1)] = 0; // clear last col of A + } + mat_mul(A, r, Ar, k * o + 1, m, 1); + + // move y - Ar to last column of matrix A + for (int i = 0; i < m; i++) { + A[k * o + i * (k * o + 1)] = sub_f(y[i], Ar[i]); + } + + EF(A, m, k * o + 1); + + // check if last row of A (excluding the last entry of y) is zero + unsigned char full_rank = 0; + for (int i = 0; i < A_cols - 1; i++) { + full_rank |= A[(m - 1) * A_cols + i]; + } + + + if (full_rank == 0) { + return 0; + } + + // back substitution in constant time + // the index of the first nonzero entry in each row is secret, which makes + // things less efficient + for (int u = m - 1; u >= 0; u--) { + finished = 0; + col_upper_bound = MAYO_MIN(u + (32/(m-u)), k*o); + // the first nonzero entry in row r is between r and col_upper_bound with probability at least ~1-q^{-32} + + for (int col = u; col <= col_upper_bound; col++) { + correct_column = (A[u * A_cols + col] != 0) && !finished; + + x[col] ^= correct_column * A[u * A_cols + A_cols - 1]; + + + #if 1 + if(u>0) { + backsub_inner_asm(A + u * A_cols + A_cols - 1, A + col, A + A_cols - 1, correct_column, u); + } + #else + for (int i = 0; i < u; i++) { + A[i * A_cols + A_cols - 1] ^= + correct_column * + mul_f(A[u * A_cols + A_cols - 1], A[i * A_cols + col]); + } + #endif + + // for (int i = 0; i < r; i++) { + // A[i * A_cols + A_cols - 1] ^= + // correct_column * + // mul_f(A[r * A_cols + A_cols - 1], A[i * A_cols + col]); + + // } + + + finished = finished || correct_column; + } + } + return 1; +} diff --git a/crypto_sign/mayo1/m4f/debug_bench_tools.h b/crypto_sign/mayo1/m4f/debug_bench_tools.h new file mode 120000 index 00000000..b534fcbe --- /dev/null +++ b/crypto_sign/mayo1/m4f/debug_bench_tools.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/debug_bench_tools.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/echelon_form.h b/crypto_sign/mayo1/m4f/echelon_form.h new file mode 120000 index 00000000..122cc01a --- /dev/null +++ b/crypto_sign/mayo1/m4f/echelon_form.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/echelon_form.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/ef.S b/crypto_sign/mayo1/m4f/ef.S new file mode 100644 index 00000000..3a2ba476 --- /dev/null +++ b/crypto_sign/mayo1/m4f/ef.S @@ -0,0 +1,833 @@ + +.syntax unified +.cpu cortex-m4 +.thumb + + +#include "gf16_madd_bitsliced.i" +#include "gf16_inverse.i" +#include "gf16_bitslice.i" +#include "asm_params.h" + +.macro bitsliced_32_vec_mul_add legs, acc0, acc1, acc2, acc3, mat0, mat1, mat2, mat3, mat, bbb, tmp0, tmp1, tmp2, incr + ldr.w \mat1, [\mat, #4*1*\legs] + ldr.w \mat2, [\mat, #4*2*\legs] + ldr.w \mat3, [\mat, #4*3*\legs] + .if \incr < 256 + ldr.w \mat0, [\mat], \incr + .else + ldr.w \mat0, [\mat] + add.w \mat, \mat, \incr + .endif + + gf16_madd_bitsliced \acc0, \acc1, \acc2, \acc3, \mat0, \mat1, \mat2, \mat3, \bbb, \tmp0, \tmp1, \tmp2 +.endm + + +.macro extract_bitsliced legs, el, AAA, tmp0, tmp1, tmp2, tmp3, tmp4, index + // in += 4*(index / 32) + ubfx.w \tmp0, \index, #5, #27 + add.w \tmp2, \AAA, \tmp0, lsl#2 + + // (idx & 0x4) + 8*(idx & 0x3) + ((idx & 0x18)>>3); + and.w \tmp0, \index, #4 + bfi.w \tmp0, \index, #3, #2 + ubfx.w \tmp4, \index, #3, #2 + add.w \tmp4, \tmp0 + + ldr.w \el, [\tmp2] + ldr.w \tmp0, [\tmp2, #4*1*\legs] + ldr.w \tmp1, [\tmp2, #4*2*\legs] + ldr.w \tmp2, [\tmp2, #4*3*\legs] + + lsr.w \el, \el, \tmp4 + lsr.w \tmp0, \tmp0, \tmp4 + lsr.w \tmp1, \tmp1, \tmp4 + lsr.w \tmp2, \tmp2, \tmp4 + + bfi.w \el, \tmp0, #1, #1 + bfi.w \el, \tmp1, #2, #1 + bfi.w \el, \tmp2, #3, #1 + + and.w \el, #0xF +.endm + + +.macro bitsliced_vec_mul_add legs, accu0, accu1, accu2, accu3, acc, mat0, mat1, mat2, mat3, mat, bbb, tmp0, tmp1, tmp2 + .set i, 0 + .rept \legs + ldr.w \accu0, [\acc, #4*0*\legs] + ldr.w \accu1, [\acc, #4*1*\legs] + ldr.w \accu2, [\acc, #4*2*\legs] + ldr.w \accu3, [\acc, #4*3*\legs] + + + .if i != \legs-1 + .set incrAcc, 4 + .set incrMat, 4 + .else + .set incrAcc, 4+4*3*\legs + .set incrMat, 4-4*\legs + .endif + + bitsliced_32_vec_mul_add \legs, \accu0, \accu1, \accu2, \accu3, \mat0, \mat1, \mat2, \mat3, \mat, \bbb, \tmp0, \tmp1, \tmp2, incrMat + + str.w \accu1, [\acc, #4*1*\legs] + str.w \accu2, [\acc, #4*2*\legs] + str.w \accu3, [\acc, #4*3*\legs] + str.w \accu0, [\acc], incrAcc + + .set i, i+1 + .endr +.endm + + +.global ef_inner1_asm +.type ef_inner1_asm, %function +.align 2 +ef_inner1_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + pivot_row_idxf .req s0 + pivot_is_zero .req r12 + row_upper_bound .req s1 + + vldr.w pivot_row_idxf, [sp] + ldr.w r12, [sp, #4] + ldrb.w pivot_is_zero, [r12] + vldr.w row_upper_bound, [sp, #8] + + push.w {r4-r11, r14} + + pivot_row .req r0 + AAA .req r1 + pivot_col .req r2 + row .req r3 + + tmp0 .req r4 + tmp1 .req r5 + tmp2 .req r6 + tmp3 .req r7 + tmp4 .req r8 + tmp5 .req r9 + tmp6 .req r10 + tmp7 .req r11 + + pivot .req r14 + 1: + + // ((row == pivot_row) || ((row > pivot_row) && pivot_is_zero)) + vmov.w tmp0, pivot_row_idxf + mov.w tmp1, pivot_is_zero + cmp.n row, tmp0 + it lt + movlt tmp1, #0 + it eq + moveq tmp1, #1 + nop + cmp.w tmp1, #0 + + .set i, 0 + .rept legs + ldr.w tmp0, [pivot_row, #0*4] + ldr.w tmp1, [pivot_row, #1*4] + ldr.w tmp2, [pivot_row, #2*4] + ldr.w tmp3, [pivot_row, #3*4] + + ldr.w tmp5, [AAA, #1*4] + ldr.w tmp6, [AAA, #2*4] + ldr.w tmp7, [AAA, #3*4] + ldr.w tmp4, [AAA], #16 + + nop + itttt ne + eorne.w tmp0, tmp4 + eorne.w tmp1, tmp5 + eorne.w tmp2, tmp6 + eorne.w tmp3, tmp7 + + str.w tmp1, [pivot_row, #1*4] + str.w tmp2, [pivot_row, #2*4] + str.w tmp3, [pivot_row, #3*4] + .if i < legs-1 + str.w tmp0, [pivot_row], #16 + .else + str.w tmp0, [pivot_row], -16*(legs-1) + .endif + .set i,i+1 + .endr + + // extract pivot + mov.w r8, pivot_row + extract_bitsliced legs, pivot, r8, r4, r5, r6, r7, r9, pivot_col + + // update pivot_is_zero + clz pivot_is_zero, pivot + lsr pivot_is_zero, #5 + + add.w row, row, #1 + vmov.w tmp0, row_upper_bound + cmp.w row, tmp0 + ble.w 1b + + // store pivot_is_zero + ldr.w r8, [sp, #4+9*4] + strb.w pivot_is_zero, [r8] + mov.w r0, pivot + + pop.w {r4-r11, pc} + + + .unreq pivot_row_idxf + .unreq pivot_is_zero + .unreq row_upper_bound + .unreq pivot_row + .unreq AAA + .unreq pivot_col + .unreq row + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq tmp7 + .unreq pivot + + + + +.global ef_inner2_asm +.type ef_inner2_asm, %function +.align 2 +ef_inner2_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + push.w {r4-r11, r14} + pivot_row_out .req r0 + pivot_row_in .req r1 + pivot .req r2 + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + tmp0 .req r11 + tmp1 .req r12 + tmp2 .req r14 + + gf16_inverse tmp0, pivot, tmp1, tmp2 + mov.w pivot, tmp0 + + .rept legs + mov.w accu0, #0 + mov.w accu1, #0 + mov.w accu2, #0 + mov.w accu3, #0 + + bitsliced_32_vec_mul_add legs, accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, pivot_row_in, pivot, tmp0, tmp1, tmp2, 4 + + str.w accu1, [pivot_row_out, #4*1*legs] + str.w accu2, [pivot_row_out, #4*2*legs] + str.w accu3, [pivot_row_out, #4*3*legs] + str.w accu0, [pivot_row_out], #4 + .endr + + pop.w {r4-r11, pc} + + .unreq pivot_row_out + .unreq pivot_row_in + .unreq pivot + .unreq accu0 + .unreq accu1 + .unreq accu2 + .unreq accu3 + + .unreq mat0 + .unreq mat1 + .unreq mat2 + .unreq mat3 + + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + + +.global ef_inner3_asm +.type ef_inner3_asm, %function +.align 2 +ef_inner3_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + pivot_row_upper_boundf .req s0 + pivot_is_nonzero .req r12 + + vldr.w pivot_row_upper_boundf, [sp] + ldr.w pivot_is_nonzero, [sp, #4] + + push.w {r4-r11, r14} + + AAA .req r0 + pivot_row .req r1 + pivot_row_ctr .req r2 + row .req r3 + + tmp0 .req r4 + tmp1 .req r5 + tmp2 .req r6 + tmp3 .req r7 + tmp4 .req r8 + tmp5 .req r9 + tmp6 .req r10 + tmp7 .req r11 + + + 1: + eor.w tmp0, pivot_row_ctr, row + orrs.w tmp0, tmp0, pivot_is_nonzero + + .set i, 0 + .rept legs + ldr.w tmp0, [AAA, #0*4] + ldr.w tmp1, [AAA, #1*4] + ldr.w tmp2, [AAA, #2*4] + ldr.w tmp3, [AAA, #3*4] + + ldr.w tmp5, [pivot_row, #1*4] + ldr.w tmp6, [pivot_row, #2*4] + ldr.w tmp7, [pivot_row, #3*4] + + .if i < (legs-1) + ldr.w tmp4, [pivot_row], #16 + .else + ldr.w tmp4, [pivot_row], -16*(legs-1) + .endif + + nop + itttt eq + moveq.w tmp0, tmp4 + moveq.w tmp1, tmp5 + moveq.w tmp2, tmp6 + moveq.w tmp3, tmp7 + + str.w tmp1, [AAA, #1*4] + str.w tmp2, [AAA, #2*4] + str.w tmp3, [AAA, #3*4] + str.w tmp0, [AAA], #16 + .set i, i+1 + .endr + + add.w row, row, #1 + vmov.w tmp0, pivot_row_upper_boundf + cmp.w row, tmp0 + ble.w 1b + + + pop.w {r4-r11, pc} + + + .unreq AAA + .unreq pivot_row + .unreq pivot_row_ctr + .unreq row + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq tmp7 + .unreq pivot_is_nonzero + + +.global ef_inner4_asm +.type ef_inner4_asm, %function +.align 2 +ef_inner4_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + AAA .req r0 + pivot_row .req r1 + row_ctr .req r2 + pivot_row_ctr .req r3 + below_pivot .req r4 + bbb .req r2 + + + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + tmp0 .req r11 + tmp1 .req r12 + tmp2 .req r14 + tmp3 .req mat0 + + pivot_col_f .req s0 + pivot_is_nonzero .req s1 + pivot_row_ctrf .req s2 + row_ctrf .req s3 + + vldr.w pivot_col_f, [sp, #0] + vldr.w pivot_is_nonzero, [sp, #4] + push.w {r4-r11, r14} + + + vmov.w pivot_row_ctrf, pivot_row_ctr + vmov.w row_ctrf, row_ctr + + mov.w tmp0, #4*4*legs + mul.w tmp0, tmp0, row_ctr + add.w AAA, tmp0 + + + 1: + vmov.w below_pivot, pivot_is_nonzero + vmov.w pivot_row_ctr, pivot_row_ctrf + cmp.n row_ctr, pivot_row_ctr + it le + movle.w below_pivot, 0 + + vmov.w r10, pivot_col_f + extract_bitsliced legs, bbb, AAA, tmp0, tmp1, tmp2, tmp3, r10, r10 + + mul.w bbb, below_pivot + bitsliced_vec_mul_add legs, accu0, accu1, accu2, accu3, AAA, mat0, mat1, mat2, mat3, pivot_row, bbb, tmp0, tmp1, tmp2 + + vmov.w row_ctr, row_ctrf + add.w row_ctr, #1 + vmov.w row_ctrf, row_ctr + cmp.w row_ctr, M + bne.w 1b + + + + vmov.w tmp0, pivot_is_nonzero + vmov.w tmp1, pivot_row_ctrf + add.w tmp1, tmp0 + vmov.w pivot_row_ctrf, tmp1 + + vmov.w r0, pivot_row_ctrf + + pop.w {r4-r11, pc} + + + .unreq AAA + .unreq pivot_row + .unreq row_ctr + .unreq pivot_row_ctr + .unreq below_pivot + .unreq bbb + + .unreq accu0 + .unreq accu1 + .unreq accu2 + .unreq accu3 + + .unreq mat0 + .unreq mat1 + .unreq mat2 + .unreq mat3 + + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq tmp3 + + .unreq pivot_col_f + .unreq pivot_is_nonzero + .unreq pivot_row_ctrf + .unreq row_ctrf + + + + +.global ef_bitslice_asm +.type ef_bitslice_asm, %function +.align 2 +ef_bitslice_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + push.w {r4-r11, r14} + out .req r0 + in .req r1 + + tmp0 .req r2 + tmp1 .req r3 + tmp2 .req r4 + tmp3 .req r5 + tmp4 .req r6 + tmp5 .req r7 + tmp6 .req r8 + tmp7 .req r9 + + ctr .req r10 + + mov.w ctr, M + + 1: + .rept legs + ldr.w tmp1, [in, #4*1] + ldr.w tmp2, [in, #4*2] + ldr.w tmp3, [in, #4*3] + ldr.w tmp4, [in, #4*4] + ldr.w tmp5, [in, #4*5] + ldr.w tmp6, [in, #4*6] + ldr.w tmp7, [in, #4*7] + ldr.w tmp0, [in], #32 + + eor.w tmp0, tmp0, tmp1, lsl#4 + eor.w tmp2, tmp2, tmp3, lsl#4 + eor.w tmp4, tmp4, tmp5, lsl#4 + eor.w tmp6, tmp6, tmp7, lsl#4 + + gf16_bitslice tmp1, tmp3, tmp5, tmp7, tmp0, tmp2, tmp4, tmp6 + + + str.w tmp3, [out, #4*1*legs] + str.w tmp5, [out, #4*2*legs] + str.w tmp7, [out, #4*3*legs] + str.w tmp1, [out], #4 + .endr + + add.w out, legs*16 - 4*legs + sub.w in, legs*32 - ncols + + subs.w ctr, #1 + bne 1b + + pop.w {r4-r11, pc} + + .unreq out + .unreq in + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq tmp7 + .unreq ctr + + + +.global ef_unbitslice_asm +.type ef_unbitslice_asm, %function +.align 2 +ef_unbitslice_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + push.w {r4-r11, r14} + out .req r0 + in .req r1 + + tmp0 .req r2 + tmp1 .req r3 + tmp2 .req r4 + tmp3 .req r5 + tmp4 .req r6 + tmp5 .req r7 + tmp6 .req r8 + tmp7 .req r9 + + + # store elements except for last word + .rept legs-1 + ldr.w tmp3, [in, #4*1*legs] + ldr.w tmp5, [in, #4*2*legs] + ldr.w tmp7, [in, #4*3*legs] + ldr.w tmp1, [in], #4 + + gf16_bitslice tmp0, tmp2, tmp4, tmp6, tmp1, tmp3, tmp5, tmp7 + + lsr.w tmp1, tmp0, #4 + lsr.w tmp3, tmp2, #4 + lsr.w tmp5, tmp4, #4 + lsr.w tmp7, tmp6, #4 + + and.w tmp0, #0x0F0F0F0F + and.w tmp1, #0x0F0F0F0F + and.w tmp2, #0x0F0F0F0F + and.w tmp3, #0x0F0F0F0F + and.w tmp4, #0x0F0F0F0F + and.w tmp5, #0x0F0F0F0F + and.w tmp6, #0x0F0F0F0F + and.w tmp7, #0x0F0F0F0F + + str.w tmp1, [out, #4*1] + str.w tmp2, [out, #4*2] + str.w tmp3, [out, #4*3] + str.w tmp4, [out, #4*4] + str.w tmp5, [out, #4*5] + str.w tmp6, [out, #4*6] + str.w tmp7, [out, #4*7] + str.w tmp0, [out], #32 + .endr + + # store last word + ldr.w tmp3, [in, #4*1*legs] + ldr.w tmp5, [in, #4*2*legs] + ldr.w tmp7, [in, #4*3*legs] + ldr.w tmp1, [in], #4 + + gf16_bitslice tmp0, tmp2, tmp4, tmp6, tmp1, tmp3, tmp5, tmp7 + + + .if ncols % 32 == 9 + lsr.w tmp1, tmp0, #4 + + and.w tmp0, #0x0F0F0F0F + and.w tmp1, #0x0F0F0F0F + and.w tmp2, #0x0F0F0F0F + + str.w tmp0, [out] + str.w tmp1, [out, #4*1] + strb.w tmp2, [out, #4*2] + .endif + + .if ncols % 32 == 15 + lsr.w tmp1, tmp0, #4 + lsr.w tmp3, tmp2, #4 + + and.w tmp0, #0x0F0F0F0F + and.w tmp1, #0x0F0F0F0F + and.w tmp2, #0x0F0F0F0F + and.w tmp3, #0x0F0F0F0F + + str.w tmp0, [out] + str.w tmp1, [out, #4*1] + str.w tmp2, [out, #4*2] + + // DODO can we just do a str directly? + strb.w tmp3, [out, #4*3] + lsr.w tmp3, 8 + strb.w tmp3, [out, #4*3+1] + lsr.w tmp3, 8 + strb.w tmp3, [out, #4*3+2] + + .endif + + + + pop.w {r4-r11, pc} + + .unreq out + .unreq in + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq tmp7 + +.macro backsub_add ptr, el, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, ncols + ubfx \tmp0, \el, #28, #4 + ubfx \tmp1, \el, #24, #4 + ubfx \tmp2, \el, #20, #4 + ubfx \tmp3, \el, #16, #4 + + ldrb.w \tmp4, [\ptr, #0*\ncols] + ldrb.w \tmp5, [\ptr, #1*\ncols] + ldrb.w \tmp6, [\ptr, #2*\ncols] + ldrb.w \tmp7, [\ptr, #3*\ncols] + + eor.w \tmp4, \tmp0 + eor.w \tmp5, \tmp1 + eor.w \tmp6, \tmp2 + eor.w \tmp7, \tmp3 + + + strb.w \tmp4, [\ptr], \ncols + strb.w \tmp5, [\ptr], \ncols + strb.w \tmp6, [\ptr], \ncols + strb.w \tmp7, [\ptr], \ncols + + ubfx \tmp0, \el, #12, #4 + ubfx \tmp1, \el, #8, #4 + ubfx \tmp2, \el, #4, #4 + ubfx \tmp3, \el, #0, #4 + + ldrb.w \tmp4, [\ptr, #0*\ncols] + ldrb.w \tmp5, [\ptr, #1*\ncols] + ldrb.w \tmp6, [\ptr, #2*\ncols] + ldrb.w \tmp7, [\ptr, #3*\ncols] + + eor.w \tmp4, \tmp0 + eor.w \tmp5, \tmp1 + eor.w \tmp6, \tmp2 + eor.w \tmp7, \tmp3 + + + strb.w \tmp4, [\ptr], \ncols + strb.w \tmp5, [\ptr], \ncols + strb.w \tmp6, [\ptr], \ncols + strb.w \tmp7, [\ptr], \ncols +.endm + + + +.global backsub_inner_asm +.type backsub_inner_asm, %function +.align 2 +backsub_inner_asm: + .set ncols, (K*O+1) + .set legs, ((ncols+31)/32) + + ctr .req s0 + + vldr.w ctr, [sp] + push.w {r4-r11, r14} + vmov.w s2, r1 + + ldrb.w r0, [r0] + cmp.n r3, #0 + + // TODO: check if mul works too + it eq + moveq.w r0, #0 + + vmov.w r12, ctr + 1: + + cmp.w r12, #32 + blt.w 4f + + // ctr >= 32 + // 0-7 + ldrb.w r9, [r1], ncols + and.w r9, 0xF + .rept 7 + ldrb.w r8, [r1], ncols + eor.w r9, r8, r9, lsl#4 + .endr + + // 8-15 + ldrb.w r10, [r1], ncols + and.w r10, 0xF + .rept 7 + ldrb.w r8, [r1], ncols + eor.w r10, r8, r10, lsl#4 + .endr + + // 16-23 + ldrb.w r11, [r1], ncols + and.w r11, 0xF + .rept 7 + ldrb.w r8, [r1], ncols + eor.w r11, r8, r11, lsl#4 + .endr + + // 24-31 + ldrb.w r12, [r1], ncols + and.w r12, 0xF + .rept 7 + ldrb.w r8, [r1], ncols + eor.w r12, r8, r12, lsl#4 + .endr + + + gf16_bitslice r4, r5, r6, r7, r9, r10, r11, r12 + + mov.w r8, #0 + mov.w r9, #0 + mov.w r10, #0 + mov.w r11, #0 + + gf16_madd_bitsliced r8, r9, r10, r11, r4, r5, r6, r7, r0, r12, r14, r3 + + gf16_bitslice r4, r5, r6, r7, r8, r9, r10, r11 + + vmov.w s7, r5 + vmov.w s8, r6 + vmov.w s9, r7 + + backsub_add r2, r4, r12, r5, r6, r7, r8, r9, r10, r11, ncols + vmov.w r4, s7 + backsub_add r2, r4, r12, r5, r6, r7, r8, r9, r10, r11, ncols + vmov.w r4, s8 + backsub_add r2, r4, r12, r5, r6, r7, r8, r9, r10, r11, ncols + vmov.w r4, s9 + backsub_add r2, r4, r12, r5, r6, r7, r8, r9, r10, r11, ncols + + vmov.w r12, ctr + subs.w r12, r12, #32 + vmov.w ctr, r12 + bne.w 1b + b.w 3f + + + 4: + + cmp.w r12, #8 + blt.w 2f + + // ctr >= 8 + ldrb.w r9, [r1], ncols + .rept 7 + ldrb.w r8, [r1], ncols + eor.w r9, r8, r9, lsl#4 + .endr + + gf16_bitslice_single r4, r5, r6, r7, r9 + + mov.w r8, #0 + mov.w r9, #0 + mov.w r10, #0 + mov.w r11, #0 + + gf16_madd_bitsliced r8, r9, r10, r11, r4, r5, r6, r7, r0, r12, r14, r3 + + gf16_unbitslice_single r12, r8, r9, r10, r11 + + backsub_add r2, r12, r4, r5, r6, r7, r8, r9, r10, r11, ncols + + vmov.w r12, ctr + subs.w r12, r12, #8 + vmov.w ctr, r12 + bne.w 1b + b.w 3f + + // ctr < 8 + 2: + ldrb.w r8, [r1], ncols + + gf16_bitslice_single r4, r5, r6, r7, r8 + + mov.w r8, #0 + mov.w r9, #0 + mov.w r10, #0 + mov.w r11, #0 + + gf16_madd_bitsliced r8, r9, r10, r11, r4, r5, r6, r7, r0, r12, r14, r3 + gf16_unbitslice_single r12, r8, r9, r10, r11 + + + ldrb.w r14, [r2] + eor.w r14, r14, r12 + strb.w r14, [r2], ncols + + vmov.w r12, ctr + subs.w r12, r12, #1 + vmov.w ctr, r12 + bne.w 1b + + // end + 3: + + pop.w {r4-r11, pc} diff --git a/crypto_sign/mayo1/m4f/gf16_bitslice.i b/crypto_sign/mayo1/m4f/gf16_bitslice.i new file mode 100644 index 00000000..fe88e8ff --- /dev/null +++ b/crypto_sign/mayo1/m4f/gf16_bitslice.i @@ -0,0 +1,54 @@ +.macro gf16_bitslice out0, out1, out2, out3, in0, in1, in2, in3 + // use out3 as tmp + and.w \out0, \in0, #0x11111111 + and.w \out3, \in1, #0x11111111 + orr.w \out0, \out0, \out3, lsl#1 + and.w \out3, \in2, #0x11111111 + orr.w \out0, \out0, \out3, lsl#2 + and.w \out3, \in3, #0x11111111 + orr.w \out0, \out0, \out3, lsl#3 + + and.w \out1, \in1, #0x22222222 + and.w \out3, \in0, #0x22222222 + orr.w \out1, \out1, \out3, lsr#1 + and.w \out3, \in2, #0x22222222 + orr.w \out1, \out1, \out3, lsl#1 + and.w \out3, \in3, #0x22222222 + orr.w \out1, \out1, \out3, lsl#2 + + and.w \out2, \in2, #0x44444444 + and.w \out3, \in0, #0x44444444 + orr.w \out2, \out2, \out3, lsr#2 + and.w \out3, \in1, #0x44444444 + orr.w \out2, \out2, \out3, lsr#1 + and.w \out3, \in3, #0x44444444 + orr.w \out2, \out2, \out3, lsl#1 + + and.w \out3, \in3, #0x88888888 + // in3 no longer needed; use as tmp + and.w \in3, \in0, #0x88888888 + orr.w \out3, \out3, \in3, lsr#3 + and.w \in3, \in1, #0x88888888 + orr.w \out3, \out3, \in3, lsr#2 + and.w \in3, \in2, #0x88888888 + orr.w \out3, \out3, \in3, lsr#1 +.endm + + +.macro gf16_bitslice_single out0, out1, out2, out3, in0 + and.w \out0, \in0, #0x11111111 + and.w \out1, \in0, #0x22222222 + lsr.w \out1, \out1, #1 + and.w \out2, \in0, #0x44444444 + lsr.w \out2, \out2, #2 + and.w \out3, \in0, #0x88888888 + lsr.w \out3, \out3, #3 +.endm + + +.macro gf16_unbitslice_single out0, in0, in1, in2, in3 + and.w \out0, \in0, #0x11111111 + orr.w \out0, \out0, \in1, lsl#1 + orr.w \out0, \out0, \in2, lsl#2 + orr.w \out0, \out0, \in3, lsl#3 +.endm \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/gf16_inverse.i b/crypto_sign/mayo1/m4f/gf16_inverse.i new file mode 100644 index 00000000..2a938f2a --- /dev/null +++ b/crypto_sign/mayo1/m4f/gf16_inverse.i @@ -0,0 +1,24 @@ + +@ static const uint8_t gf16_inv_lut[] = { +@ 0, 1, 9, 14, 13, 11, 7, 6, 15, 2, 12, 5, 10, 4, 3, 8 +@ }; +// gf16 := gf2[x]/x^4+x+1 + + +.macro gf16_inverse out, in, tmp, tmp2 + movw \tmp, #0x4976 + lsr.w \out, \tmp, \in + and.w \out, #1 + movw \tmp, #0x53E8 + lsr.w \tmp2, \tmp, \in + and.w \tmp2, #1 + orr.w \out, \out, \tmp2, lsl #1 + movw \tmp, #0x2DD8 + lsr.w \tmp2, \tmp, \in + and.w \tmp2, #1 + orr.w \out, \out, \tmp2, lsl #2 + movw \tmp, #0x953C + lsr.w \tmp2, \tmp, \in + and.w \tmp2, #1 + orr.w \out, \out, \tmp2, lsl #3 +.endm \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/gf16_madd_bitsliced.i b/crypto_sign/mayo1/m4f/gf16_madd_bitsliced.i new file mode 100644 index 00000000..3f552983 --- /dev/null +++ b/crypto_sign/mayo1/m4f/gf16_madd_bitsliced.i @@ -0,0 +1,38 @@ + +.macro gf16_madd_bitsliced accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, b_32, tmp0, tmp1, tmp2, tmp3 + eor.w \tmp0, \mat0, \mat3 // tmp0 = a[0] ^ a[1] + eor.w \tmp1, \mat2, \mat3 // tmp1 = a[2] ^ a[3] + eor.w \tmp2, \mat1, \mat2 // tmp2 = a[1] ^ a[2] + + tst.w \b_32, #1 + nop.n + itttt ne + eorne.w \accu0, \accu0, \mat0 // out[0] ^= (b[0] & a[0]) + eorne.w \accu1, \accu1, \mat1 // out[1] ^= (b[0] & a[1]) + eorne.w \accu2, \accu2, \mat2 // out[2] ^= (b[0] & a[2]) + eorne.w \accu3, \accu3, \mat3 // out[3] ^= (b[0] & a[3]) + + tst.w \b_32, #2 + nop.n + itttt ne + eorne.w \accu0, \accu0, \mat3 // out[0] ^= (b[1] & a[3]) + eorne.w \accu1, \accu1, \tmp0 // out[1] ^= (b[1] & (a[0] ^ a[3])) + eorne.w \accu2, \accu2, \mat1 // out[2] ^= (b[1] & a[1]) + eorne.w \accu3, \accu3, \mat2 // out[3] ^= (b[1] & a[2]) + + tst.w \b_32, #4 + nop.n + itttt ne + eorne.w \accu0, \accu0, \mat2 // out[0] ^= (b[2] & a[2]) + eorne.w \accu1, \accu1, \tmp1 // out[1] ^= (b[2] & (a[2] ^ a[3])) + eorne.w \accu2, \accu2, \tmp0 // out[2] ^= (b[2] & (a[0] ^ a[3])) + eorne.w \accu3, \accu3, \mat1 // out[3] ^= (b[2] & a[1]) + + tst.w \b_32, #8 + nop.n + itttt ne + eorne.w \accu0, \accu0, \mat1 // out[0] ^= (b[3] & a[1]) + eorne.w \accu1, \accu1, \tmp2 // out[1] ^= (b[2] & (a[1] ^ a[2])) + eorne.w \accu2, \accu2, \tmp1 // out[2] ^= (b[2] & (a[2] ^ a[3])) + eorne.w \accu3, \accu3, \tmp0 // out[3] ^= (b[2] & (a[0] ^ a[1])) +.endm diff --git a/crypto_sign/mayo1/m4f/m4f_asm.h b/crypto_sign/mayo1/m4f/m4f_asm.h new file mode 100644 index 00000000..de526e7f --- /dev/null +++ b/crypto_sign/mayo1/m4f/m4f_asm.h @@ -0,0 +1,31 @@ +#ifndef M4F_ASM_H +#define M4F_ASM_H + +#include + + + +void mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm(uint32_t *acc, const unsigned char *mat, const uint32_t *bs_mat); +void mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm(uint32_t *acc, const unsigned char *mat, const uint32_t *bs_mat); +void mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm(uint32_t *acc, const uint32_t *bs_mat, const unsigned char *mat); +void mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm(uint32_t *acc, const uint32_t *bs_mat, const unsigned char *mat); + +void bitsliced_m_calculate_SPS_m4f_asm(uint32_t *, const uint32_t *, const unsigned char *); +void bitsliced_multiply_bins_asm(uint32_t *, uint32_t *, const int); + +#if N_MAX <= 78 +void bitsliced_m_calculate_PS_m4f_asm(uint32_t *, const uint32_t *, const unsigned char *, const int); +#else +void bitsliced_m_calculate_PS_m4f_stack_asm(uint32_t *, const uint32_t *, const unsigned char *, const int); +void bitsliced_multiply_bins_stack_asm(uint32_t *, uint32_t *, const int); +#endif + + +int sample_solution_m4f(const mayo_params_t *p, unsigned char *A, + const unsigned char *y, const unsigned char *r, + unsigned char *x); + +void mayo_expand_sk_computeL_inner1_m4f(uint32_t *p2, const uint32_t *p1, const uint8_t *O, const uint8_t *O_max); +void mayo_expand_sk_computeL_inner2_m4f(uint32_t *p2, const uint32_t *p1, const uint8_t *O, size_t c); + +#endif \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/matmul.S b/crypto_sign/mayo1/m4f/matmul.S new file mode 100644 index 00000000..b3878dc9 --- /dev/null +++ b/crypto_sign/mayo1/m4f/matmul.S @@ -0,0 +1,48 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "matmul.i" +#include "asm_params.h" + + +//void mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm(uint32_t *c, uint32_t *a, uint8_t *b); +.global mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm +.type mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm, %function +.align 2 +mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f_V_V_O_triangular_asm: + mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f V, 0, 1, O, M + +//void mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm(uint32_t *c, uint32_t *a, uint8_t *b); +.global mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm +.type mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm, %function +.align 2 +mul_add_bitsliced_m_upper_triangular_mat_x_mat_trans_m4f_V_V_K_triangular_asm: + mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f V, 1, 1, K, M + + +//void mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm(uint32_t *c, uint8_t *a, uint32_t *b); +.global mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm +.type mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm, %function +.align 2 +mul_add_mat_x_bitsliced_m_mat_m4f_K_V_O_triangular_asm: + mul_add_mat_x_bitsliced_m_mat_m4f K, V, O, M + +//void mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm(uint32_t *c, uint8_t *a, uint32_t *b); +.global mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm +.type mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm, %function +.align 2 +mul_add_mat_x_bitsliced_m_mat_m4f_K_V_K_triangular_asm: + mul_add_mat_x_bitsliced_m_mat_m4f K, V, K, M + +.global mayo_expand_sk_computeL_inner1_m4f +.type mayo_expand_sk_computeL_inner1_m4f, %function +.align 2 +mayo_expand_sk_computeL_inner1_m4f: + mayo_expand_sk_computeL_inner1_m4f M, O + +.global mayo_expand_sk_computeL_inner2_m4f +.type mayo_expand_sk_computeL_inner2_m4f, %function +.align 2 +mayo_expand_sk_computeL_inner2_m4f: + mayo_expand_sk_computeL_inner2_m4f M, O, V diff --git a/crypto_sign/mayo1/m4f/matmul.i b/crypto_sign/mayo1/m4f/matmul.i new file mode 100644 index 00000000..9b87d001 --- /dev/null +++ b/crypto_sign/mayo1/m4f/matmul.i @@ -0,0 +1,530 @@ + +#include "gf16_madd_bitsliced.i" + + +.macro bitsliced_32_vec_mul_add m_legs, acc0, acc1, acc2, acc3, mat0, mat1, mat2, mat3, mat, bbb, tmp0, tmp1, tmp2, incr + ldr.w \mat1, [\mat, #4*1*\m_legs] + ldr.w \mat2, [\mat, #4*2*\m_legs] + ldr.w \mat3, [\mat, #4*3*\m_legs] + .if \incr < 256 + ldr.w \mat0, [\mat], \incr + .else + ldr.w \mat0, [\mat] + add.w \mat, \mat, \incr + .endif + + gf16_madd_bitsliced \acc0, \acc1, \acc2, \acc3, \mat0, \mat1, \mat2, \mat3, \bbb, \tmp0, \tmp1, \tmp2 +.endm + + + +/* +void mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f(int m_legs, const uint32_t *bs_mat, const unsigned char *mat, uint32_t *acc, int bs_mat_rows, int bs_mat_cols, int mat_cols, int triangular) { + int bs_mat_entries_used; + for(int i = 0; i < m_legs; i++){ + bs_mat_entries_used = 0; + for (int r = 0; r < bs_mat_rows; r++) { + for (int k = 0; k < mat_cols; k += 1) { + for (int c = triangular * r; c < bs_mat_cols; c++) { + + #ifdef transpose + bitsliced_32_vec_mul_add(m_legs, bs_mat + m_legs * 4 * bs_mat_entries_used + i, mat[k * bs_mat_cols + c], acc + m_legs * 4 * (r * mat_cols + k) + i); + #else + bitsliced_32_vec_mul_add(m_legs, bs_mat + m_legs * 4 * bs_mat_entries_used + i, mat[c * mat_cols + k], acc + m_legs * 4 * (r * mat_cols + k) + i); + #endif + bs_mat_entries_used += 1; + } + bs_mat_entries_used -= bs_mat_cols - triangular * r; + } + bs_mat_entries_used += bs_mat_cols - triangular * r; + } + } +} +*/ + +.macro mul_add_bitsliced_m_upper_triangular_mat_x_mat_m4f dim1, transpose, triangular, dim3, m + .set m_legs, (\m/32) + push {r4-r11, r14} + acc .req r0 + ctr .req r0 + mat .req r1 + bbb .req r2 + + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + tmp0 .req r11 + tmp1 .req r12 + tmp2 .req r14 + + + + ctr4f .req s0 + ctr3f .req s1 + ctr2f .req s2 + + acc_orig .req s3 + mat_orig .req s4 + bbb_orig .req s5 + + accf .req s6 + matf .req s7 + bbbf .req s8 + + bbb_cur .req s9 + + vmov mat_orig, mat + vmov acc_orig, acc + vmov.w bbb_orig, bbb + + mov.w tmp0, m_legs + 4: + vmov.w ctr4f, tmp0 + vmov.w accf, acc + + mov.w tmp0, \dim1 + 3: + vmov.w ctr3f, tmp0 + vmov.w matf, mat + vmov.w bbb_cur, bbb_orig + + mov.w tmp0, \dim3 + 2: + vmov.w ctr2f, tmp0 + vmov.w mat, matf + + ldr.w accu0, [acc, 0*m_legs*4] + ldr.w accu1, [acc, 1*m_legs*4] + ldr.w accu2, [acc, 2*m_legs*4] + ldr.w accu3, [acc, 3*m_legs*4] + + vmov.w tmp0, bbb_cur + vmov.w bbbf, tmp0 + .if \transpose == 0 + add.w tmp0, #1 + .else + add.w tmp0, \dim1 + .endif + vmov.w bbb_cur, tmp0 + + .if \triangular == 0 + mov ctr, \dim1 + .else + vmov.w tmp1, bbbf + vmov.w ctr, ctr3f + rsb.w tmp0, ctr, \dim1 + .if \transpose == 0 + mov.w tmp2, \dim3 + mla.w tmp1, tmp0, tmp2, tmp1 + .else + add.w tmp1, tmp0 + .endif + vmov bbbf, tmp1 + .endif + 1: + vmov.w tmp0, bbbf + .if \transpose == 0 + ldrb bbb, [tmp0], \dim3 + .else + ldrb bbb, [tmp0], #1 + .endif + vmov.w bbbf, tmp0 + + bitsliced_32_vec_mul_add m_legs, accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, mat, bbb, tmp0, tmp1, tmp2, 4*m_legs*4 + subs.w ctr, ctr, #1 + bne.w 1b + + vmov.w acc, accf + str.w accu1, [acc, 1*m_legs*4] + str.w accu2, [acc, 2*m_legs*4] + str.w accu3, [acc, 3*m_legs*4] + str.w accu0, [acc], 4*m_legs*4 + + vmov.w accf, acc + + vmov.w tmp0, ctr2f + subs.w tmp0, tmp0, #1 + bne.w 2b + vmov.w tmp0, ctr3f + subs.w tmp0, tmp0, #1 + bne.w 3b + + vmov.w mat, mat_orig + add.w mat, mat, #4 + vmov.w mat_orig, mat + + vmov.w acc, acc_orig + add.w acc, acc, #4 + vmov.w acc_orig, acc + + vmov.w tmp0, ctr4f + subs.w tmp0, tmp0, #1 + bne.w 4b + pop.w {r4-r11, pc} + + + .unreq acc + .unreq ctr + .unreq mat + .unreq bbb + .unreq accu0 + .unreq accu1 + .unreq accu2 + .unreq accu3 + .unreq mat0 + .unreq mat1 + .unreq mat2 + .unreq mat3 + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq ctr4f + .unreq ctr3f + .unreq ctr2f + .unreq acc_orig + .unreq mat_orig + .unreq bbb_orig + .unreq accf + .unreq matf + .unreq bbbf + .unreq bbb_cur +.endm + +.macro mul_add_mat_x_bitsliced_m_mat_m4f mat_rows, mat_cols, bs_mat_cols, m + .set m_legs, (\m/32) + push {r4-r11, r14} + acc .req r0 + ctr .req r0 + bbb .req r1 + mat .req r2 + + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + tmp0 .req r11 + tmp1 .req r12 + tmp2 .req r14 + + ctr4f .req s0 + ctr3f .req s1 + ctr2f .req s2 + + acc_orig .req s3 + mat_orig .req s4 + bbb_orig .req s5 + + accf .req s6 + matf .req s7 + bbbf .req s8 + + bbb_cur .req s9 + mat_cur .req s10 + + vmov.w mat_orig, mat + vmov.w mat_cur, mat + vmov acc_orig, acc + vmov.w bbb_orig, bbb + + mov.w tmp0, m_legs + 4: + vmov.w ctr4f, tmp0 + vmov.w accf, acc + vmov.w bbb_cur, bbb_orig + + mov.w tmp0, \mat_rows + 3: + vmov.w ctr3f, tmp0 + + mov.w tmp0, \bs_mat_cols + 2: + vmov.w ctr2f, tmp0 + + ldr.w accu0, [acc, 0*m_legs*4] + ldr.w accu1, [acc, 1*m_legs*4] + ldr.w accu2, [acc, 2*m_legs*4] + ldr.w accu3, [acc, 3*m_legs*4] + + vmov.w bbbf, bbb_cur + + mov ctr, \mat_cols + 1: + vmov.w tmp0, bbbf + ldrb bbb, [tmp0], #1 + vmov.w bbbf, tmp0 + + bitsliced_32_vec_mul_add m_legs, accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, mat, bbb, tmp0, tmp1, tmp2, 4*m_legs*4*\bs_mat_cols + + subs.w ctr, ctr, #1 + bne.w 1b + + vmov.w acc, accf + str.w accu1, [acc, 1*m_legs*4] + str.w accu2, [acc, 2*m_legs*4] + str.w accu3, [acc, 3*m_legs*4] + str.w accu0, [acc], 4*m_legs*4 + vmov.w accf, acc + + vmov.w mat, mat_cur + add.w mat, mat, 4*m_legs*4 + vmov.w mat_cur, mat + + vmov.w tmp0, ctr2f + subs.w tmp0, tmp0, #1 + bne 2b + + vmov.w mat_cur, mat_orig + vmov.w mat, mat_cur + + vmov.w tmp0, bbb_cur + add.w tmp0, \mat_cols + vmov.w bbb_cur, tmp0 + + vmov.w tmp0, ctr3f + subs.w tmp0, tmp0, #1 + bne 3b + + vmov.w acc, acc_orig + add.w acc, acc, #4 + vmov.w acc_orig, acc + + vmov.w mat, mat_orig + add.w mat, mat, #4 + vmov.w mat_orig, mat + vmov.w mat_cur, mat + + vmov.w tmp0, ctr4f + subs.w tmp0, tmp0, #1 + bne 4b + pop.w {r4-r11, pc} + + .unreq acc + .unreq ctr + .unreq bbb + .unreq mat + .unreq accu0 + .unreq accu1 + .unreq accu2 + .unreq accu3 + .unreq mat0 + .unreq mat1 + .unreq mat2 + .unreq mat3 + .unreq tmp0 + .unreq tmp1 + .unreq tmp2 + .unreq ctr4f + .unreq ctr3f + .unreq ctr2f + .unreq acc_orig + .unreq mat_orig + .unreq bbb_orig + .unreq accf + .unreq matf + .unreq bbbf + .unreq bbb_cur + .unreq mat_cur +.endm + + +.macro mayo_expand_sk_computeL_inner1_m4f m, o + .set m_legs, (\m/32) + push.w {r4-r11, r14} + mat .req r1 + bbb_ptr .req r2 + + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + bbb_ptr_max .req s0 + acc_ptr .req s1 + acc_ptr_max .req s2 + + mat_orig .req s3 + bbb_ptr_orig .req s4 + + bbb .req r0 + + add.w r12, r0, \o*16*m_legs + vmov.w acc_ptr_max, r12 + vmov.w mat_orig, r1 + vmov.w bbb_ptr_max, r3 + vmov.w acc_ptr, r0 + vmov.w bbb_ptr_orig, bbb_ptr + + 2: + ldr.w accu0, [r0, 0*4*m_legs] + ldr.w accu1, [r0, 1*4*m_legs] + ldr.w accu2, [r0, 2*4*m_legs] + ldr.w accu3, [r0, 3*4*m_legs] + + + + 1: + ldr.w mat1, [mat, 1*4*m_legs] + ldr.w mat2, [mat, 2*4*m_legs] + ldr.w mat3, [mat, 3*4*m_legs] + ldr.w mat0, [mat], 4*4*m_legs + + ldrb.w bbb, [bbb_ptr], \o + gf16_madd_bitsliced accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, bbb, r11, r12, r14 + + + vmov.w r12, bbb_ptr_max + cmp.w r12, bbb_ptr + bne.w 1b + + vmov.w r0, acc_ptr + str.w accu1, [r0, 1*4*m_legs] + str.w accu2, [r0, 2*4*m_legs] + str.w accu3, [r0, 3*4*m_legs] + str.w accu0, [r0], 16*m_legs + vmov.w acc_ptr, r0 + + vmov.w mat, mat_orig + vmov.w r11, bbb_ptr_max + add.w r11, r11, #1 + vmov.w bbb_ptr_max, r11 + vmov.w bbb_ptr, bbb_ptr_orig + add.w bbb_ptr, #1 + vmov.w bbb_ptr_orig, bbb_ptr + + + vmov.w r12, acc_ptr_max + cmp.w r12, r0 + bne 2b + + pop.w {r4-r11, pc} + + .unreq mat + .unreq bbb_ptr + .unreq accu0 + .unreq accu1 + .unreq accu2 + .unreq accu3 + .unreq mat0 + .unreq mat1 + .unreq mat2 + .unreq mat3 + .unreq bbb_ptr_max + .unreq acc_ptr + .unreq acc_ptr_max + .unreq mat_orig + .unreq bbb_ptr_orig + .unreq bbb +.endm + + +.macro mayo_expand_sk_computeL_inner2_m4f m, o, v + .set m_legs, (\m/32) + push.w {r4-r11, r14} + + mat .req r1 + bbb_ptr .req r2 + + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + acc_ptr .req s1 + acc_ptr_max .req s2 + + mat_orig .req s3 + bbb_ptr_orig .req s4 + + bbb .req r0 + offset .req s0 + min_offset .req s7 + + + // offset = 16*m_legs*(param_v-1) + // min_offset = 16*m_legs*(param_v - c - 1) + mov.w r12, 16*m_legs + rsb.w r11, r3, (\v-1) + mul.w r12, r11, r12 + vmov.w min_offset, r12 + + add.w r12, r0, \o*16*m_legs + vmov.w acc_ptr_max, r12 + vmov.w acc_ptr, r0 + + vmov.w mat_orig, r1 + vmov.w bbb_ptr_orig, bbb_ptr + + 2: + mov.w r12, 16*m_legs*(\v-1) + vmov.w offset, r12 + + + ldr.w accu0, [r0, 0*4*m_legs] + ldr.w accu1, [r0, 1*4*m_legs] + ldr.w accu2, [r0, 2*4*m_legs] + ldr.w accu3, [r0, 3*4*m_legs] + 1: + ldr.w mat0, [mat, 0*4*m_legs] + ldr.w mat1, [mat, 1*4*m_legs] + ldr.w mat2, [mat, 2*4*m_legs] + ldr.w mat3, [mat, 3*4*m_legs] + + + ldrb.w bbb, [bbb_ptr], \o + gf16_madd_bitsliced accu0, accu1, accu2, accu3, mat0, mat1, mat2, mat3, bbb, r11, r12, r14 + + + vmov.w r12, offset + add.w mat, r12 + sub.w r12, r12, 16*m_legs + vmov.w offset, r12 + + + vmov.w r11, min_offset + cmp.w r12, r11 + bne.w 1b + + vmov.w r0, acc_ptr + str.w accu1, [r0, 1*4*m_legs] + str.w accu2, [r0, 2*4*m_legs] + str.w accu3, [r0, 3*4*m_legs] + str.w accu0, [r0], 16*m_legs + vmov.w acc_ptr, r0 + + + vmov.w mat, mat_orig + vmov.w bbb_ptr, bbb_ptr_orig + add.w bbb_ptr, #1 + vmov.w bbb_ptr_orig, bbb_ptr + + + vmov.w r12, acc_ptr_max + cmp.w r12, r0 + bne 2b + + + pop.w {r4-r11, pc} +.endm \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/mayo.c b/crypto_sign/mayo1/m4f/mayo.c new file mode 120000 index 00000000..fb423ee6 --- /dev/null +++ b/crypto_sign/mayo1/m4f/mayo.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/mayo.c \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/mayo.h b/crypto_sign/mayo1/m4f/mayo.h new file mode 120000 index 00000000..cdbe41db --- /dev/null +++ b/crypto_sign/mayo1/m4f/mayo.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/mayo.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/mem.c b/crypto_sign/mayo1/m4f/mem.c new file mode 120000 index 00000000..69461fae --- /dev/null +++ b/crypto_sign/mayo1/m4f/mem.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/mem.c \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/mem.h b/crypto_sign/mayo1/m4f/mem.h new file mode 120000 index 00000000..2f9e0061 --- /dev/null +++ b/crypto_sign/mayo1/m4f/mem.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/mem.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/params.c b/crypto_sign/mayo1/m4f/params.c new file mode 120000 index 00000000..605286ac --- /dev/null +++ b/crypto_sign/mayo1/m4f/params.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/params.c \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/rng.h b/crypto_sign/mayo1/m4f/rng.h new file mode 120000 index 00000000..49185e18 --- /dev/null +++ b/crypto_sign/mayo1/m4f/rng.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/rng.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/simple_arithmetic.h b/crypto_sign/mayo1/m4f/simple_arithmetic.h new file mode 120000 index 00000000..811bcb8d --- /dev/null +++ b/crypto_sign/mayo1/m4f/simple_arithmetic.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo1/ref/simple_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo1/m4f/verification.S b/crypto_sign/mayo1/m4f/verification.S new file mode 100644 index 00000000..8eeca9b5 --- /dev/null +++ b/crypto_sign/mayo1/m4f/verification.S @@ -0,0 +1,42 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "verification.i" +#include "asm_params.h" + + +// For MAYO3 and MAYO5 we need to compute PS incrementally +#if N <= 78 +.global bitsliced_m_calculate_PS_m4f_asm +.type bitsliced_m_calculate_PS_m4f_asm, %function +.align 2 +bitsliced_m_calculate_PS_m4f_asm: + macro_bitsliced_m_calculate_PS_m4f_asm (M/32), N, K +#else +.global bitsliced_m_calculate_PS_m4f_stack_asm +.type bitsliced_m_calculate_PS_m4f_stack_asm, %function +.align 2 +bitsliced_m_calculate_PS_m4f_stack_asm: + macro_bitsliced_m_calculate_PS_m4f_stack_asm (M/32), N, K + +.global bitsliced_multiply_bins_stack_asm +.type bitsliced_multiply_bins_stack_asm, %function +.align 2 +bitsliced_multiply_bins_stack_asm: + macro_bitsliced_multiply_bins_stack_asm (M/32), N, K +#endif + +.global bitsliced_m_calculate_SPS_m4f_asm +.type bitsliced_m_calculate_SPS_m4f_asm, %function +.align 2 +bitsliced_m_calculate_SPS_m4f_asm: + macro_bitsliced_m_calculate_SPS_m4f_asm (M/32), N, K + +.global bitsliced_multiply_bins_asm +.type bitsliced_multiply_bins_asm, %function +.align 2 +bitsliced_multiply_bins_asm: + macro_bitsliced_multiply_bins_asm (M/32), N, K + + diff --git a/crypto_sign/mayo1/m4f/verification.i b/crypto_sign/mayo1/m4f/verification.i new file mode 100644 index 00000000..d65ff83d --- /dev/null +++ b/crypto_sign/mayo1/m4f/verification.i @@ -0,0 +1,301 @@ + .macro macro_bitsliced_m_calculate_PS_m4f_asm m_legs, n, k + push.w {r4-r11, r14} + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + add.w r11, r2, r3 + mov.w r14, 16*\m_legs + + 1: + .set i, 0 + .rept \m_legs + ldr.w mat1, [r1, #1*4*\m_legs] + ldr.w mat2, [r1, #2*4*\m_legs] + ldr.w mat3, [r1, #3*4*\m_legs] + ldr.w mat0, [r1], #4 + + + .rept \k + ldrb.w r12, [r2], \n + mla.w r12, r14, r12, r0 + + ldr.w accu0, [r12, #0*4*\m_legs] + ldr.w accu1, [r12, #1*4*\m_legs] + ldr.w accu2, [r12, #2*4*\m_legs] + ldr.w accu3, [r12, #3*4*\m_legs] + + eor.w accu0, mat0 + eor.w accu1, mat1 + eor.w accu2, mat2 + eor.w accu3, mat3 + + str.w accu0, [r12, #0*4*\m_legs] + str.w accu1, [r12, #1*4*\m_legs] + str.w accu2, [r12, #2*4*\m_legs] + str.w accu3, [r12, #3*4*\m_legs] + + add.w r0, r0, 16*16*\m_legs + .endr + + .if i < \m_legs-1 + sub.w r2, \n*\k + mov.w r12, 16*16*\k*\m_legs-4 + sub.w r0, r0, r12 + .else + sub.w r2, \n*\k-1 + mov.w r12, 16*16*\k*\m_legs+(\m_legs-1)*4 + sub.w r0, r0, r12 + .endif + + .set i,i+1 + .endr + add.w r1, r1, #3*4*\m_legs + cmp.w r2, r11 + bne.w 1b + + pop.w {r4-r11, pc} +.endm + + .macro macro_bitsliced_m_calculate_PS_m4f_stack_asm m_legs, n, k + push.w {r4-r11, r14} + accu0 .req r3 + accu1 .req r4 + accu2 .req r5 + accu3 .req r6 + + mat0 .req r7 + mat1 .req r8 + mat2 .req r9 + mat3 .req r10 + + add.w r11, r2, r3 + mov.w r14, 16*\m_legs + + + 1: + ldrb.w r12, [r2], #1 + mla.w r12, r14, r12, r0 + + .set i, 0 + .rept \m_legs + ldr.w mat1, [r1, #1*4*\m_legs] + ldr.w mat2, [r1, #2*4*\m_legs] + ldr.w mat3, [r1, #3*4*\m_legs] + ldr.w mat0, [r1], #4 + + ldr.w accu0, [r12, #0*4*\m_legs] + ldr.w accu1, [r12, #1*4*\m_legs] + ldr.w accu2, [r12, #2*4*\m_legs] + ldr.w accu3, [r12, #3*4*\m_legs] + + eor.w accu0, mat0 + eor.w accu1, mat1 + eor.w accu2, mat2 + eor.w accu3, mat3 + + str.w accu1, [r12, #1*4*\m_legs] + str.w accu2, [r12, #2*4*\m_legs] + str.w accu3, [r12, #3*4*\m_legs] + str.w accu0, [r12], #4 + .endr + + add.w r1, r1, 16*\m_legs - \m_legs*4 + + cmp.w r2, r11 + bne.w 1b + + pop.w {r4-r11, pc} +.endm + +.macro macro_bitsliced_m_calculate_SPS_m4f_asm m_legs, n, k + push.w {r4-r11, r14} + mov.w r14, 16*\m_legs + + mov.w r11, \n + 1: + .set i,0 + .rept \k + ldrb.w r12, [r2], \n + mla.w r12, r14, r12, r0 + + .rept \m_legs + ldr.w mat1, [r1, #1*4*\m_legs] + ldr.w mat2, [r1, #2*4*\m_legs] + ldr.w mat3, [r1, #3*4*\m_legs] + ldr.w mat0, [r1], #4 + + ldr.w accu0, [r12, #0*4*\m_legs] + ldr.w accu1, [r12, #1*4*\m_legs] + ldr.w accu2, [r12, #2*4*\m_legs] + ldr.w accu3, [r12, #3*4*\m_legs] + + eor.w accu0, mat0 + eor.w accu1, mat1 + eor.w accu2, mat2 + eor.w accu3, mat3 + + str.w accu1, [r12, #1*4*\m_legs] + str.w accu2, [r12, #2*4*\m_legs] + str.w accu3, [r12, #3*4*\m_legs] + str.w accu0, [r12], #4 + .endr + + .if i < \k-1 + add.w r0, \k*16*16*\m_legs + sub.w r1, \m_legs*4 + .else + sub.w r0, (\k-1)*\k*16*16*\m_legs + add.w r1, \k*\m_legs*16 - \m_legs*4 + .endif + + .set i, i+1 + .endr + + sub.w r2, \n*\k-1 + + subs.w r11, #1 + bne.w 1b + + pop.w {r4-r11, pc} +.endm + + +.macro addx m_legs, outidx, inidx + ldr.w r3, [r0, #0*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r4, [r0, #1*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r5, [r0, #2*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r6, [r0, #3*4*\m_legs+(\inidx-1)*16*\m_legs] + + ldr.w r7, [r0, #0*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r8, [r0, #1*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r9, [r0, #2*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r10, [r0, #3*4*\m_legs+(\outidx-1)*16*\m_legs] + + eor.w r7, r6 + eor.w r8, r3 + eor.w r8, r6 + eor.w r9, r4 + eor.w r10, r5 + + str.w r7, [r0, #0*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r8, [r0, #1*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r9, [r0, #2*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r10, [r0, #3*4*\m_legs+(\outidx-1)*16*\m_legs] +.endm + +.macro addx_final m_legs, outidx, inidx + ldr.w r3, [r0, #0*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r4, [r0, #1*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r5, [r0, #2*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r6, [r0, #3*4*\m_legs+(\inidx-1)*16*\m_legs] + + ldr.w r8, [r0, #1*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r9, [r0, #2*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r10, [r0, #3*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r7, [r0], #4 + + eor.w r7, r6 + eor.w r8, r3 + eor.w r8, r6 + eor.w r9, r4 + eor.w r10, r5 + + str.w r8, [r1, #1*4*\m_legs] + str.w r9, [r1, #2*4*\m_legs] + str.w r10, [r1, #3*4*\m_legs] + str.w r7, [r1], #4 +.endm + +.macro addx_inv m_legs, outidx, inidx + ldr.w r3, [r0, #0*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r4, [r0, #1*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r5, [r0, #2*4*\m_legs+(\inidx-1)*16*\m_legs] + ldr.w r6, [r0, #3*4*\m_legs+(\inidx-1)*16*\m_legs] + + ldr.w r7, [r0, #0*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r8, [r0, #1*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r9, [r0, #2*4*\m_legs+(\outidx-1)*16*\m_legs] + ldr.w r10, [r0, #3*4*\m_legs+(\outidx-1)*16*\m_legs] + + eor.w r7, r3 + eor.w r7, r4 + eor.w r8, r5 + eor.w r9, r6 + eor.w r10, r3 + + str.w r7, [r0, #0*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r8, [r0, #1*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r9, [r0, #2*4*\m_legs+(\outidx-1)*16*\m_legs] + str.w r10, [r0, #3*4*\m_legs+(\outidx-1)*16*\m_legs] +.endm + + + + +.macro macro_bitsliced_multiply_bins_asm m_legs, n, k + push.w {r4-r11, r14} + add.w r0, \m_legs*16 + mov.w r11, r2 + 1: + .rept \m_legs + addx_inv \m_legs, 10, 5 + addx \m_legs, 12, 11 + addx_inv \m_legs, 7, 10 + addx \m_legs, 6, 12 + addx_inv \m_legs, 14, 7 + addx \m_legs, 3, 6 + addx_inv \m_legs, 15, 14 + addx \m_legs, 8, 3 + addx_inv \m_legs, 13, 15 + addx \m_legs, 4, 8 + addx_inv \m_legs, 9, 13 + addx \m_legs, 2, 4 + addx_inv \m_legs, 1, 9 + addx_final \m_legs, 1, 2 + .endr + + add.w r0, 4*16*4*\m_legs - \m_legs*4 + add.w r1, 8*2*\m_legs - \m_legs*4 + + subs.w r11, #1 + bne 1b + pop.w {r4-r11, pc} +.endm + + +.macro macro_bitsliced_multiply_bins_stack_asm m_legs, n, k + push.w {r4-r11, r14} + add.w r0, \m_legs*16 + mov.w r11, r2 + 1: + .rept \m_legs + addx_inv \m_legs, 10, 5 + addx \m_legs, 12, 11 + addx_inv \m_legs, 7, 10 + addx \m_legs, 6, 12 + addx_inv \m_legs, 14, 7 + addx \m_legs, 3, 6 + addx_inv \m_legs, 15, 14 + addx \m_legs, 8, 3 + addx_inv \m_legs, 13, 15 + addx \m_legs, 4, 8 + addx_inv \m_legs, 9, 13 + addx \m_legs, 2, 4 + addx_inv \m_legs, 1, 9 + addx_final \m_legs, 1, 2 + .endr + + add.w r0, 4*16*4*\m_legs - \m_legs*4 + add.w r1, 8*2*\k*\m_legs - \m_legs*4 + + subs.w r11, #1 + bne 1b + pop.w {r4-r11, pc} +.endm \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/LICENSE b/crypto_sign/mayo2/m4f/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/crypto_sign/mayo2/m4f/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crypto_sign/mayo2/m4f/aes_ctr.c b/crypto_sign/mayo2/m4f/aes_ctr.c new file mode 120000 index 00000000..a1d10982 --- /dev/null +++ b/crypto_sign/mayo2/m4f/aes_ctr.c @@ -0,0 +1 @@ +../../mayo1/m4f/aes_ctr.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/aes_ctr.h b/crypto_sign/mayo2/m4f/aes_ctr.h new file mode 120000 index 00000000..f7f848c5 --- /dev/null +++ b/crypto_sign/mayo2/m4f/aes_ctr.h @@ -0,0 +1 @@ +../../mayo1/m4f/aes_ctr.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/api.c b/crypto_sign/mayo2/m4f/api.c new file mode 120000 index 00000000..67710abb --- /dev/null +++ b/crypto_sign/mayo2/m4f/api.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo2/ref/api.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/api.h b/crypto_sign/mayo2/m4f/api.h new file mode 120000 index 00000000..f25e7318 --- /dev/null +++ b/crypto_sign/mayo2/m4f/api.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo2/ref/api.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/asm_params.h b/crypto_sign/mayo2/m4f/asm_params.h new file mode 100644 index 00000000..2e35c63e --- /dev/null +++ b/crypto_sign/mayo2/m4f/asm_params.h @@ -0,0 +1,5 @@ +#define M 64 +#define N 78 +#define K 4 +#define O 18 +#define V (N-O) diff --git a/crypto_sign/mayo2/m4f/bitsliced_arithmetic.h b/crypto_sign/mayo2/m4f/bitsliced_arithmetic.h new file mode 120000 index 00000000..e4727a11 --- /dev/null +++ b/crypto_sign/mayo2/m4f/bitsliced_arithmetic.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/bitsliced_arithmetic_128.h b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_128.h new file mode 120000 index 00000000..c39b297a --- /dev/null +++ b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_128.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_128.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/bitsliced_arithmetic_64.h b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_64.h new file mode 120000 index 00000000..0ef52f8c --- /dev/null +++ b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_64.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_64.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/bitsliced_arithmetic_96.h b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_96.h new file mode 120000 index 00000000..4d6a2446 --- /dev/null +++ b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_96.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_96.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/bitsliced_arithmetic_m4f.c b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_m4f.c new file mode 120000 index 00000000..acf6a1f2 --- /dev/null +++ b/crypto_sign/mayo2/m4f/bitsliced_arithmetic_m4f.c @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_m4f.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/debug_bench_tools.h b/crypto_sign/mayo2/m4f/debug_bench_tools.h new file mode 120000 index 00000000..aa49cad1 --- /dev/null +++ b/crypto_sign/mayo2/m4f/debug_bench_tools.h @@ -0,0 +1 @@ +../../mayo1/m4f/debug_bench_tools.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/echelon_form.h b/crypto_sign/mayo2/m4f/echelon_form.h new file mode 120000 index 00000000..1fd7a0a8 --- /dev/null +++ b/crypto_sign/mayo2/m4f/echelon_form.h @@ -0,0 +1 @@ +../../mayo1/m4f/echelon_form.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/ef.S b/crypto_sign/mayo2/m4f/ef.S new file mode 120000 index 00000000..94999f45 --- /dev/null +++ b/crypto_sign/mayo2/m4f/ef.S @@ -0,0 +1 @@ +../../mayo1/m4f/ef.S \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/gf16_bitslice.i b/crypto_sign/mayo2/m4f/gf16_bitslice.i new file mode 120000 index 00000000..cbb67b40 --- /dev/null +++ b/crypto_sign/mayo2/m4f/gf16_bitslice.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_bitslice.i \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/gf16_inverse.i b/crypto_sign/mayo2/m4f/gf16_inverse.i new file mode 120000 index 00000000..2057de90 --- /dev/null +++ b/crypto_sign/mayo2/m4f/gf16_inverse.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_inverse.i \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/gf16_madd_bitsliced.i b/crypto_sign/mayo2/m4f/gf16_madd_bitsliced.i new file mode 120000 index 00000000..34979f6b --- /dev/null +++ b/crypto_sign/mayo2/m4f/gf16_madd_bitsliced.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_madd_bitsliced.i \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/m4f_asm.h b/crypto_sign/mayo2/m4f/m4f_asm.h new file mode 120000 index 00000000..c333ea2c --- /dev/null +++ b/crypto_sign/mayo2/m4f/m4f_asm.h @@ -0,0 +1 @@ +../../mayo1/m4f/m4f_asm.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/matmul.S b/crypto_sign/mayo2/m4f/matmul.S new file mode 120000 index 00000000..8cc937e0 --- /dev/null +++ b/crypto_sign/mayo2/m4f/matmul.S @@ -0,0 +1 @@ +../../mayo1/m4f/matmul.S \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/matmul.i b/crypto_sign/mayo2/m4f/matmul.i new file mode 120000 index 00000000..d9ff0da8 --- /dev/null +++ b/crypto_sign/mayo2/m4f/matmul.i @@ -0,0 +1 @@ +../../mayo1/m4f/matmul.i \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/mayo.c b/crypto_sign/mayo2/m4f/mayo.c new file mode 120000 index 00000000..aecb8cb9 --- /dev/null +++ b/crypto_sign/mayo2/m4f/mayo.c @@ -0,0 +1 @@ +../../mayo1/m4f/mayo.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/mayo.h b/crypto_sign/mayo2/m4f/mayo.h new file mode 120000 index 00000000..c2eadf63 --- /dev/null +++ b/crypto_sign/mayo2/m4f/mayo.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo2/ref/mayo.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/mem.c b/crypto_sign/mayo2/m4f/mem.c new file mode 120000 index 00000000..76ba7398 --- /dev/null +++ b/crypto_sign/mayo2/m4f/mem.c @@ -0,0 +1 @@ +../../mayo1/m4f/mem.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/mem.h b/crypto_sign/mayo2/m4f/mem.h new file mode 120000 index 00000000..2dac942d --- /dev/null +++ b/crypto_sign/mayo2/m4f/mem.h @@ -0,0 +1 @@ +../../mayo1/m4f/mem.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/params.c b/crypto_sign/mayo2/m4f/params.c new file mode 120000 index 00000000..0ac75ff3 --- /dev/null +++ b/crypto_sign/mayo2/m4f/params.c @@ -0,0 +1 @@ +../../mayo1/m4f/params.c \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/rng.h b/crypto_sign/mayo2/m4f/rng.h new file mode 120000 index 00000000..909c5abe --- /dev/null +++ b/crypto_sign/mayo2/m4f/rng.h @@ -0,0 +1 @@ +../../mayo1/m4f/rng.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/simple_arithmetic.h b/crypto_sign/mayo2/m4f/simple_arithmetic.h new file mode 120000 index 00000000..4c45e10f --- /dev/null +++ b/crypto_sign/mayo2/m4f/simple_arithmetic.h @@ -0,0 +1 @@ +../../mayo1/m4f/simple_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/verification.S b/crypto_sign/mayo2/m4f/verification.S new file mode 120000 index 00000000..f6e8c182 --- /dev/null +++ b/crypto_sign/mayo2/m4f/verification.S @@ -0,0 +1 @@ +../../mayo1/m4f/verification.S \ No newline at end of file diff --git a/crypto_sign/mayo2/m4f/verification.i b/crypto_sign/mayo2/m4f/verification.i new file mode 120000 index 00000000..1d5698e3 --- /dev/null +++ b/crypto_sign/mayo2/m4f/verification.i @@ -0,0 +1 @@ +../../mayo1/m4f/verification.i \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/LICENSE b/crypto_sign/mayo3/m4f/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/crypto_sign/mayo3/m4f/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crypto_sign/mayo3/m4f/aes_ctr.c b/crypto_sign/mayo3/m4f/aes_ctr.c new file mode 120000 index 00000000..a1d10982 --- /dev/null +++ b/crypto_sign/mayo3/m4f/aes_ctr.c @@ -0,0 +1 @@ +../../mayo1/m4f/aes_ctr.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/aes_ctr.h b/crypto_sign/mayo3/m4f/aes_ctr.h new file mode 120000 index 00000000..f7f848c5 --- /dev/null +++ b/crypto_sign/mayo3/m4f/aes_ctr.h @@ -0,0 +1 @@ +../../mayo1/m4f/aes_ctr.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/api.c b/crypto_sign/mayo3/m4f/api.c new file mode 120000 index 00000000..d9500802 --- /dev/null +++ b/crypto_sign/mayo3/m4f/api.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo3/ref/api.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/api.h b/crypto_sign/mayo3/m4f/api.h new file mode 120000 index 00000000..5010a10a --- /dev/null +++ b/crypto_sign/mayo3/m4f/api.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo3/ref/api.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/asm_params.h b/crypto_sign/mayo3/m4f/asm_params.h new file mode 100644 index 00000000..d1956775 --- /dev/null +++ b/crypto_sign/mayo3/m4f/asm_params.h @@ -0,0 +1,5 @@ +#define M 96 +#define N 99 +#define K 11 +#define O 10 +#define V (N-O) diff --git a/crypto_sign/mayo3/m4f/bitsliced_arithmetic.h b/crypto_sign/mayo3/m4f/bitsliced_arithmetic.h new file mode 120000 index 00000000..e4727a11 --- /dev/null +++ b/crypto_sign/mayo3/m4f/bitsliced_arithmetic.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/bitsliced_arithmetic_128.h b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_128.h new file mode 120000 index 00000000..c39b297a --- /dev/null +++ b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_128.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_128.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/bitsliced_arithmetic_64.h b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_64.h new file mode 120000 index 00000000..0ef52f8c --- /dev/null +++ b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_64.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_64.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/bitsliced_arithmetic_96.h b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_96.h new file mode 120000 index 00000000..4d6a2446 --- /dev/null +++ b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_96.h @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_96.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/bitsliced_arithmetic_m4f.c b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_m4f.c new file mode 120000 index 00000000..acf6a1f2 --- /dev/null +++ b/crypto_sign/mayo3/m4f/bitsliced_arithmetic_m4f.c @@ -0,0 +1 @@ +../../mayo1/m4f/bitsliced_arithmetic_m4f.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/debug_bench_tools.h b/crypto_sign/mayo3/m4f/debug_bench_tools.h new file mode 120000 index 00000000..aa49cad1 --- /dev/null +++ b/crypto_sign/mayo3/m4f/debug_bench_tools.h @@ -0,0 +1 @@ +../../mayo1/m4f/debug_bench_tools.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/echelon_form.h b/crypto_sign/mayo3/m4f/echelon_form.h new file mode 120000 index 00000000..1fd7a0a8 --- /dev/null +++ b/crypto_sign/mayo3/m4f/echelon_form.h @@ -0,0 +1 @@ +../../mayo1/m4f/echelon_form.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/ef.S b/crypto_sign/mayo3/m4f/ef.S new file mode 120000 index 00000000..94999f45 --- /dev/null +++ b/crypto_sign/mayo3/m4f/ef.S @@ -0,0 +1 @@ +../../mayo1/m4f/ef.S \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/gf16_bitslice.i b/crypto_sign/mayo3/m4f/gf16_bitslice.i new file mode 120000 index 00000000..cbb67b40 --- /dev/null +++ b/crypto_sign/mayo3/m4f/gf16_bitslice.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_bitslice.i \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/gf16_inverse.i b/crypto_sign/mayo3/m4f/gf16_inverse.i new file mode 120000 index 00000000..2057de90 --- /dev/null +++ b/crypto_sign/mayo3/m4f/gf16_inverse.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_inverse.i \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/gf16_madd_bitsliced.i b/crypto_sign/mayo3/m4f/gf16_madd_bitsliced.i new file mode 120000 index 00000000..34979f6b --- /dev/null +++ b/crypto_sign/mayo3/m4f/gf16_madd_bitsliced.i @@ -0,0 +1 @@ +../../mayo1/m4f/gf16_madd_bitsliced.i \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/m4f_asm.h b/crypto_sign/mayo3/m4f/m4f_asm.h new file mode 120000 index 00000000..c333ea2c --- /dev/null +++ b/crypto_sign/mayo3/m4f/m4f_asm.h @@ -0,0 +1 @@ +../../mayo1/m4f/m4f_asm.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/matmul.S b/crypto_sign/mayo3/m4f/matmul.S new file mode 120000 index 00000000..8cc937e0 --- /dev/null +++ b/crypto_sign/mayo3/m4f/matmul.S @@ -0,0 +1 @@ +../../mayo1/m4f/matmul.S \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/matmul.i b/crypto_sign/mayo3/m4f/matmul.i new file mode 120000 index 00000000..d9ff0da8 --- /dev/null +++ b/crypto_sign/mayo3/m4f/matmul.i @@ -0,0 +1 @@ +../../mayo1/m4f/matmul.i \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/mayo.c b/crypto_sign/mayo3/m4f/mayo.c new file mode 120000 index 00000000..aecb8cb9 --- /dev/null +++ b/crypto_sign/mayo3/m4f/mayo.c @@ -0,0 +1 @@ +../../mayo1/m4f/mayo.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/mayo.h b/crypto_sign/mayo3/m4f/mayo.h new file mode 120000 index 00000000..3bee99aa --- /dev/null +++ b/crypto_sign/mayo3/m4f/mayo.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/mayo3/ref/mayo.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/mem.c b/crypto_sign/mayo3/m4f/mem.c new file mode 120000 index 00000000..76ba7398 --- /dev/null +++ b/crypto_sign/mayo3/m4f/mem.c @@ -0,0 +1 @@ +../../mayo1/m4f/mem.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/mem.h b/crypto_sign/mayo3/m4f/mem.h new file mode 120000 index 00000000..2dac942d --- /dev/null +++ b/crypto_sign/mayo3/m4f/mem.h @@ -0,0 +1 @@ +../../mayo1/m4f/mem.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/params.c b/crypto_sign/mayo3/m4f/params.c new file mode 120000 index 00000000..0ac75ff3 --- /dev/null +++ b/crypto_sign/mayo3/m4f/params.c @@ -0,0 +1 @@ +../../mayo1/m4f/params.c \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/rng.h b/crypto_sign/mayo3/m4f/rng.h new file mode 120000 index 00000000..909c5abe --- /dev/null +++ b/crypto_sign/mayo3/m4f/rng.h @@ -0,0 +1 @@ +../../mayo1/m4f/rng.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/simple_arithmetic.h b/crypto_sign/mayo3/m4f/simple_arithmetic.h new file mode 120000 index 00000000..4c45e10f --- /dev/null +++ b/crypto_sign/mayo3/m4f/simple_arithmetic.h @@ -0,0 +1 @@ +../../mayo1/m4f/simple_arithmetic.h \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/verification.S b/crypto_sign/mayo3/m4f/verification.S new file mode 120000 index 00000000..f6e8c182 --- /dev/null +++ b/crypto_sign/mayo3/m4f/verification.S @@ -0,0 +1 @@ +../../mayo1/m4f/verification.S \ No newline at end of file diff --git a/crypto_sign/mayo3/m4f/verification.i b/crypto_sign/mayo3/m4f/verification.i new file mode 120000 index 00000000..1d5698e3 --- /dev/null +++ b/crypto_sign/mayo3/m4f/verification.i @@ -0,0 +1 @@ +../../mayo1/m4f/verification.i \ No newline at end of file diff --git a/mupq b/mupq index 9998553b..4ee8c918 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 9998553b42bd224fc391f156d2f1bc00bbddd543 +Subproject commit 4ee8c9182e24649c587ec3229a9f9e31aef842e0 diff --git a/skiplist.py b/skiplist.py index b5e657db..6de9cb09 100644 --- a/skiplist.py +++ b/skiplist.py @@ -168,4 +168,10 @@ {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, -] \ No newline at end of file + {'scheme': 'mayo3', 'implementation': 'm4f', 'estmemory': 4201472}, + {'scheme': 'mayo1', 'implementation': 'm4f', 'estmemory': 4199424}, + {'scheme': 'mayo2', 'implementation': 'm4f', 'estmemory': 287744}, + {'scheme': 'mayo3', 'implementation': 'ref', 'estmemory': 4201472}, + {'scheme': 'mayo1', 'implementation': 'ref', 'estmemory': 4199424}, + {'scheme': 'mayo2', 'implementation': 'ref', 'estmemory': 279552}, +] From 9c69acbf7bffa0721c18393d8d26f7a7e348f5a3 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 Nov 2023 10:07:21 +0800 Subject: [PATCH 011/107] update skiplist --- skiplist.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/skiplist.py b/skiplist.py index 6de9cb09..248713ea 100644 --- a/skiplist.py +++ b/skiplist.py @@ -168,10 +168,10 @@ {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, - {'scheme': 'mayo3', 'implementation': 'm4f', 'estmemory': 4201472}, - {'scheme': 'mayo1', 'implementation': 'm4f', 'estmemory': 4199424}, + {'scheme': 'mayo3', 'implementation': 'm4f', 'estmemory': 477184}, + {'scheme': 'mayo1', 'implementation': 'm4f', 'estmemory': 446464}, {'scheme': 'mayo2', 'implementation': 'm4f', 'estmemory': 287744}, - {'scheme': 'mayo3', 'implementation': 'ref', 'estmemory': 4201472}, - {'scheme': 'mayo1', 'implementation': 'ref', 'estmemory': 4199424}, + {'scheme': 'mayo3', 'implementation': 'ref', 'estmemory': 1144832}, + {'scheme': 'mayo1', 'implementation': 'ref', 'estmemory': 404480}, {'scheme': 'mayo2', 'implementation': 'ref', 'estmemory': 279552}, ] From c4aaa789fbfcecb17e302f525911f5ca86f4d4ac Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 24 Oct 2023 22:42:48 +0800 Subject: [PATCH 012/107] add ov-Ip{,-pkc,-pkc-skc} m4f implementations --- common/aes-publicinputs.h | 2 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/api.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_comm.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_u32.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/config.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf16.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256_asm.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256_madd.i | 1 + .../m4fspeed/gf256mat_gauss_elim_44.S | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_22.S | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_44.S | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.S | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.i | 1 + .../gf256trimat_2trimat_madd_68_68_44_44.S | 1 + .../ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval.i | 1 + .../gf256trimat_eval_112_44_publicinputs.S | 1 + .../m4fspeed/gf256trimat_eval_68_44.S | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_blas.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/ov_keypair.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/ov_keypair.h | 1 + .../m4fspeed/ov_keypair_computation.c | 1 + .../m4fspeed/ov_keypair_computation.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/ov_publicmap_m4f.c | 1 + .../m4fspeed/parallel_matrix_op.c | 1 + .../m4fspeed/parallel_matrix_op.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/params.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/sign.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/utils_hash.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/utils_hash.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/utils_malloc.h | 1 + .../ov-Ip-pkc-skc/m4fspeed/utils_prng.c | 1 + .../ov-Ip-pkc-skc/m4fspeed/utils_prng.h | 1 + .../m4fspeed/utils_randombytes.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/api.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/blas.h | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_comm.h | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix.c | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix.h | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.c | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.h | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.c | 1 + .../ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_u32.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/config.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/gf16.h | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256_asm.h | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256_madd.i | 1 + .../m4fstack/gf256mat_gauss_elim_44.S | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256mat_inv_22.S | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256mat_inv_44.S | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256mat_prod.S | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256mat_prod.i | 1 + .../gf256trimat_2trimat_madd_68_68_44_44.S | 1 + .../ov-Ip-pkc-skc/m4fstack/gf256trimat_eval.i | 1 + ...mat_eval_112_44_incremental_publicinputs.S | 1 + .../m4fstack/gf256trimat_eval_68_44.S | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_blas.h | 1 + .../ov-Ip-pkc-skc/m4fstack/ov_keypair.c | 1 + .../ov-Ip-pkc-skc/m4fstack/ov_keypair.h | 1 + .../m4fstack/ov_keypair_computation.c | 1 + .../m4fstack/ov_keypair_computation.h | 1 + .../ov-Ip-pkc-skc/m4fstack/ov_publicmap_m4f.c | 1 + .../m4fstack/parallel_matrix_op.c | 1 + .../m4fstack/parallel_matrix_op.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/params.h | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/sign.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.c | 1 + crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.h | 1 + .../ov-Ip-pkc-skc/m4fstack/utils_hash.c | 1 + .../ov-Ip-pkc-skc/m4fstack/utils_hash.h | 1 + .../ov-Ip-pkc-skc/m4fstack/utils_malloc.h | 1 + .../ov-Ip-pkc-skc/m4fstack/utils_prng.c | 1 + .../ov-Ip-pkc-skc/m4fstack/utils_prng.h | 1 + .../m4fstack/utils_randombytes.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/api.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/blas.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/blas_comm.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.h | 1 + .../ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c | 1 + .../ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h | 1 + .../ov-Ip-pkc/m4fspeed/blas_matrix_ref.c | 1 + .../ov-Ip-pkc/m4fspeed/blas_matrix_ref.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/blas_u32.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/config.h | 30 + crypto_sign/ov-Ip-pkc/m4fspeed/gf16.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/gf256_asm.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/gf256_madd.i | 1 + .../m4fspeed/gf256mat_gauss_elim_44.S | 1 + .../ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S | 1 + .../ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S | 1 + .../ov-Ip-pkc/m4fspeed/gf256mat_prod.S | 1 + .../ov-Ip-pkc/m4fspeed/gf256mat_prod.i | 1 + .../gf256trimat_2trimat_madd_68_68_44_44.S | 1 + .../ov-Ip-pkc/m4fspeed/gf256trimat_eval.i | 1 + .../gf256trimat_eval_112_44_publicinputs.S | 1 + .../m4fspeed/gf256trimat_eval_68_44.S | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/ov.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/ov.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/ov_blas.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.h | 1 + .../m4fspeed/ov_keypair_computation.c | 1 + .../m4fspeed/ov_keypair_computation.h | 1 + .../ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c | 1 + .../ov-Ip-pkc/m4fspeed/parallel_matrix_op.c | 1 + .../ov-Ip-pkc/m4fspeed/parallel_matrix_op.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/params.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/sign.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils_malloc.h | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.c | 1 + crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.h | 1 + .../ov-Ip-pkc/m4fspeed/utils_randombytes.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/api.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/blas.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/blas_comm.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.h | 1 + .../ov-Ip-pkc/m4fstack/blas_matrix_m4f.c | 1 + .../ov-Ip-pkc/m4fstack/blas_matrix_m4f.h | 1 + .../ov-Ip-pkc/m4fstack/blas_matrix_ref.c | 1 + .../ov-Ip-pkc/m4fstack/blas_matrix_ref.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/blas_u32.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/config.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/gf16.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/gf256_asm.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/gf256_madd.i | 1 + .../m4fstack/gf256mat_gauss_elim_44.S | 1 + .../ov-Ip-pkc/m4fstack/gf256mat_inv_22.S | 1 + .../ov-Ip-pkc/m4fstack/gf256mat_inv_44.S | 1 + .../ov-Ip-pkc/m4fstack/gf256mat_prod.S | 1 + .../ov-Ip-pkc/m4fstack/gf256mat_prod.i | 1 + .../gf256trimat_2trimat_madd_68_68_44_44.S | 1 + .../ov-Ip-pkc/m4fstack/gf256trimat_eval.i | 1 + ...mat_eval_112_44_incremental_publicinputs.S | 632 ++++++++++++++++++ .../m4fstack/gf256trimat_eval_68_44.S | 1 + crypto_sign/ov-Ip-pkc/m4fstack/ov.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/ov.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/ov_blas.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.h | 1 + .../m4fstack/ov_keypair_computation.c | 1 + .../m4fstack/ov_keypair_computation.h | 1 + .../ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c | 1 + .../ov-Ip-pkc/m4fstack/parallel_matrix_op.c | 1 + .../ov-Ip-pkc/m4fstack/parallel_matrix_op.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/params.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/sign.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils_malloc.h | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.c | 1 + crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.h | 1 + .../ov-Ip-pkc/m4fstack/utils_randombytes.h | 1 + crypto_sign/ov-Ip/m4f/api.h | 1 + crypto_sign/ov-Ip/m4f/blas.h | 1 + crypto_sign/ov-Ip/m4f/blas_comm.h | 1 + crypto_sign/ov-Ip/m4f/blas_matrix.c | 1 + crypto_sign/ov-Ip/m4f/blas_matrix.h | 1 + crypto_sign/ov-Ip/m4f/blas_matrix_m4f.c | 212 ++++++ crypto_sign/ov-Ip/m4f/blas_matrix_m4f.h | 36 + crypto_sign/ov-Ip/m4f/blas_matrix_ref.c | 532 +++++++++++++++ crypto_sign/ov-Ip/m4f/blas_matrix_ref.h | 64 ++ crypto_sign/ov-Ip/m4f/blas_u32.h | 1 + crypto_sign/ov-Ip/m4f/config.h | 31 + crypto_sign/ov-Ip/m4f/gf16.h | 1 + crypto_sign/ov-Ip/m4f/gf256_asm.h | 33 + crypto_sign/ov-Ip/m4f/gf256_madd.i | 174 +++++ .../ov-Ip/m4f/gf256mat_gauss_elim_44.S | 421 ++++++++++++ crypto_sign/ov-Ip/m4f/gf256mat_inv_22.S | 448 +++++++++++++ crypto_sign/ov-Ip/m4f/gf256mat_inv_44.S | 573 ++++++++++++++++ crypto_sign/ov-Ip/m4f/gf256mat_prod.S | 27 + crypto_sign/ov-Ip/m4f/gf256mat_prod.i | 575 ++++++++++++++++ .../gf256trimat_2trimat_madd_68_68_44_44.S | 251 +++++++ crypto_sign/ov-Ip/m4f/gf256trimat_eval.i | 251 +++++++ .../gf256trimat_eval_112_44_publicinputs.S | 586 ++++++++++++++++ .../ov-Ip/m4f/gf256trimat_eval_68_44.S | 13 + crypto_sign/ov-Ip/m4f/ov.c | 1 + crypto_sign/ov-Ip/m4f/ov.h | 1 + crypto_sign/ov-Ip/m4f/ov_blas.h | 1 + crypto_sign/ov-Ip/m4f/ov_keypair.c | 1 + crypto_sign/ov-Ip/m4f/ov_keypair.h | 1 + .../ov-Ip/m4f/ov_keypair_computation.c | 1 + .../ov-Ip/m4f/ov_keypair_computation.h | 1 + crypto_sign/ov-Ip/m4f/ov_publicmap_m4f.c | 40 ++ crypto_sign/ov-Ip/m4f/parallel_matrix_op.c | 1 + crypto_sign/ov-Ip/m4f/parallel_matrix_op.h | 1 + crypto_sign/ov-Ip/m4f/params.h | 1 + crypto_sign/ov-Ip/m4f/sign.c | 1 + crypto_sign/ov-Ip/m4f/utils.c | 1 + crypto_sign/ov-Ip/m4f/utils.h | 1 + crypto_sign/ov-Ip/m4f/utils_hash.c | 1 + crypto_sign/ov-Ip/m4f/utils_hash.h | 1 + crypto_sign/ov-Ip/m4f/utils_malloc.h | 1 + crypto_sign/ov-Ip/m4f/utils_prng.c | 1 + crypto_sign/ov-Ip/m4f/utils_prng.h | 1 + crypto_sign/ov-Ip/m4f/utils_randombytes.h | 1 + mupq | 2 +- 217 files changed, 5128 insertions(+), 1 deletion(-) create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/api.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_comm.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_u32.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/config.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf16.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_asm.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_madd.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_gauss_elim_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_22.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_68_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_blas.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_publicmap_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/params.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/sign.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_malloc.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_randombytes.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/api.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_comm.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_u32.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/config.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf16.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_asm.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_madd.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_gauss_elim_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_22.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval.i create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_68_44.S create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_blas.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_publicmap_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/params.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/sign.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_malloc.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.c create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.h create mode 120000 crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_randombytes.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/api.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_comm.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/blas_u32.h create mode 100644 crypto_sign/ov-Ip-pkc/m4fspeed/config.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf16.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256_asm.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256_madd.i create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_gauss_elim_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.i create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval.i create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_68_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_blas.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/params.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/sign.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_malloc.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fspeed/utils_randombytes.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/api.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_comm.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/blas_u32.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/config.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf16.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256_asm.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256_madd.i create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_gauss_elim_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_22.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.i create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval.i create mode 100644 crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_68_44.S create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_blas.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/params.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/sign.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_malloc.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.c create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.h create mode 120000 crypto_sign/ov-Ip-pkc/m4fstack/utils_randombytes.h create mode 120000 crypto_sign/ov-Ip/m4f/api.h create mode 120000 crypto_sign/ov-Ip/m4f/blas.h create mode 120000 crypto_sign/ov-Ip/m4f/blas_comm.h create mode 120000 crypto_sign/ov-Ip/m4f/blas_matrix.c create mode 120000 crypto_sign/ov-Ip/m4f/blas_matrix.h create mode 100644 crypto_sign/ov-Ip/m4f/blas_matrix_m4f.c create mode 100644 crypto_sign/ov-Ip/m4f/blas_matrix_m4f.h create mode 100644 crypto_sign/ov-Ip/m4f/blas_matrix_ref.c create mode 100644 crypto_sign/ov-Ip/m4f/blas_matrix_ref.h create mode 120000 crypto_sign/ov-Ip/m4f/blas_u32.h create mode 100644 crypto_sign/ov-Ip/m4f/config.h create mode 120000 crypto_sign/ov-Ip/m4f/gf16.h create mode 100644 crypto_sign/ov-Ip/m4f/gf256_asm.h create mode 100644 crypto_sign/ov-Ip/m4f/gf256_madd.i create mode 100644 crypto_sign/ov-Ip/m4f/gf256mat_gauss_elim_44.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256mat_inv_22.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256mat_inv_44.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256mat_prod.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256mat_prod.i create mode 100644 crypto_sign/ov-Ip/m4f/gf256trimat_2trimat_madd_68_68_44_44.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256trimat_eval.i create mode 100644 crypto_sign/ov-Ip/m4f/gf256trimat_eval_112_44_publicinputs.S create mode 100644 crypto_sign/ov-Ip/m4f/gf256trimat_eval_68_44.S create mode 120000 crypto_sign/ov-Ip/m4f/ov.c create mode 120000 crypto_sign/ov-Ip/m4f/ov.h create mode 120000 crypto_sign/ov-Ip/m4f/ov_blas.h create mode 120000 crypto_sign/ov-Ip/m4f/ov_keypair.c create mode 120000 crypto_sign/ov-Ip/m4f/ov_keypair.h create mode 120000 crypto_sign/ov-Ip/m4f/ov_keypair_computation.c create mode 120000 crypto_sign/ov-Ip/m4f/ov_keypair_computation.h create mode 100644 crypto_sign/ov-Ip/m4f/ov_publicmap_m4f.c create mode 120000 crypto_sign/ov-Ip/m4f/parallel_matrix_op.c create mode 120000 crypto_sign/ov-Ip/m4f/parallel_matrix_op.h create mode 120000 crypto_sign/ov-Ip/m4f/params.h create mode 120000 crypto_sign/ov-Ip/m4f/sign.c create mode 120000 crypto_sign/ov-Ip/m4f/utils.c create mode 120000 crypto_sign/ov-Ip/m4f/utils.h create mode 120000 crypto_sign/ov-Ip/m4f/utils_hash.c create mode 120000 crypto_sign/ov-Ip/m4f/utils_hash.h create mode 120000 crypto_sign/ov-Ip/m4f/utils_malloc.h create mode 120000 crypto_sign/ov-Ip/m4f/utils_prng.c create mode 120000 crypto_sign/ov-Ip/m4f/utils_prng.h create mode 120000 crypto_sign/ov-Ip/m4f/utils_randombytes.h diff --git a/common/aes-publicinputs.h b/common/aes-publicinputs.h index 13fbadde..8305304c 100644 --- a/common/aes-publicinputs.h +++ b/common/aes-publicinputs.h @@ -1,6 +1,8 @@ #ifndef AES_PUBLICINPUTS_H #define AES_PUBLICINPUTS_H +#define PQM4_AES + #include #include diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/api.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/api.h new file mode 120000 index 00000000..2a3b01c0 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/api.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas.h new file mode 120000 index 00000000..d155618b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_comm.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_comm.h new file mode 120000 index 00000000..24597851 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_comm.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_comm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.c new file mode 120000 index 00000000..2077493a --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.h new file mode 120000 index 00000000..59e85226 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.c new file mode 120000 index 00000000..7e52b102 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.h new file mode 120000 index 00000000..2837994a --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_m4f.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.c new file mode 120000 index 00000000..48133373 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix_ref.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.h new file mode 120000 index 00000000..e6b3c398 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_matrix_ref.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_matrix_ref.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_u32.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_u32.h new file mode 120000 index 00000000..521897f3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/blas_u32.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/blas_u32.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/config.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/config.h new file mode 120000 index 00000000..8bc562c6 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/config.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/config.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf16.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf16.h new file mode 120000 index 00000000..395a4c6c --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf16.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf16.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_asm.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_asm.h new file mode 120000 index 00000000..2d9876a4 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_asm.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256_asm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_madd.i b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_madd.i new file mode 120000 index 00000000..3d96bb0e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256_madd.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256_madd.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_gauss_elim_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_gauss_elim_44.S new file mode 120000 index 00000000..44eecf38 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_gauss_elim_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256mat_gauss_elim_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_22.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_22.S new file mode 120000 index 00000000..10028825 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_22.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_44.S new file mode 120000 index 00000000..39918b7b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_inv_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.S new file mode 120000 index 00000000..b536d70e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256mat_prod.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.i b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.i new file mode 120000 index 00000000..efba7fff --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256mat_prod.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256mat_prod.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S new file mode 120000 index 00000000..c261038f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval.i b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval.i new file mode 120000 index 00000000..d78f3c48 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256trimat_eval.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S new file mode 120000 index 00000000..c3f2a92f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_68_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_68_44.S new file mode 120000 index 00000000..3850d317 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/gf256trimat_eval_68_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/gf256trimat_eval_68_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.c new file mode 120000 index 00000000..1566ef76 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.h new file mode 120000 index 00000000..4d6a0e8a --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_blas.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_blas.h new file mode 120000 index 00000000..239523d4 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_blas.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.c new file mode 120000 index 00000000..0a9c3676 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_keypair.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.h new file mode 120000 index 00000000..0f7cc805 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_keypair.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.c new file mode 120000 index 00000000..352452be --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_keypair_computation.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.h new file mode 120000 index 00000000..801948ce --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_keypair_computation.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_keypair_computation.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_publicmap_m4f.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_publicmap_m4f.c new file mode 120000 index 00000000..9a893ecc --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/ov_publicmap_m4f.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.c new file mode 120000 index 00000000..0b08150f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/parallel_matrix_op.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.h new file mode 120000 index 00000000..fddbae87 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/parallel_matrix_op.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/parallel_matrix_op.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/params.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/params.h new file mode 120000 index 00000000..171aee8d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/params.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip-pkc-skc/ref/params.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/sign.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/sign.c new file mode 120000 index 00000000..baf3f44f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/sign.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/sign.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.c new file mode 120000 index 00000000..82843e37 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.h new file mode 120000 index 00000000..792dd126 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.c new file mode 120000 index 00000000..8fe0c64e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_hash.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.h new file mode 120000 index 00000000..8c96ef70 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_hash.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_hash.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_malloc.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_malloc.h new file mode 120000 index 00000000..d8f62511 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_malloc.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_malloc.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.c b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.c new file mode 120000 index 00000000..27c47ca2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_prng.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.h new file mode 120000 index 00000000..7b0ca2bd --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_prng.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_prng.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_randombytes.h b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_randombytes.h new file mode 120000 index 00000000..12d87dbd --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/utils_randombytes.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fspeed/utils_randombytes.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/api.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/api.h new file mode 120000 index 00000000..6fa72b08 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/api.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/api.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas.h new file mode 120000 index 00000000..3f0defb2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_comm.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_comm.h new file mode 120000 index 00000000..9d6d5f7b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_comm.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_comm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.c new file mode 120000 index 00000000..d5bd7c5f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.h new file mode 120000 index 00000000..1edc5fa1 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.c new file mode 120000 index 00000000..6ca0f1fb --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.h new file mode 120000 index 00000000..e44825a5 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_m4f.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix_m4f.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.c new file mode 120000 index 00000000..ba5d6dbf --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix_ref.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.h new file mode 120000 index 00000000..44e699b7 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_matrix_ref.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_matrix_ref.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_u32.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_u32.h new file mode 120000 index 00000000..980f54f3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/blas_u32.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/blas_u32.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/config.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/config.h new file mode 120000 index 00000000..2f1e69d8 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/config.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/config.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf16.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf16.h new file mode 120000 index 00000000..462cc20e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf16.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf16.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_asm.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_asm.h new file mode 120000 index 00000000..94ed8d99 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_asm.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256_asm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_madd.i b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_madd.i new file mode 120000 index 00000000..9cc61443 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256_madd.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256_madd.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_gauss_elim_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_gauss_elim_44.S new file mode 120000 index 00000000..5c14f0e4 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_gauss_elim_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256mat_gauss_elim_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_22.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_22.S new file mode 120000 index 00000000..918c3dc5 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_22.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256mat_inv_22.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_44.S new file mode 120000 index 00000000..9117730f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_inv_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256mat_inv_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.S new file mode 120000 index 00000000..43c3b18c --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256mat_prod.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.i b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.i new file mode 120000 index 00000000..cb7fc02b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256mat_prod.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256mat_prod.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S new file mode 120000 index 00000000..c81836d8 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval.i b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval.i new file mode 120000 index 00000000..1ddef07f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval.i @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256trimat_eval.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S new file mode 120000 index 00000000..68781b43 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_68_44.S b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_68_44.S new file mode 120000 index 00000000..c158e2c7 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/gf256trimat_eval_68_44.S @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/gf256trimat_eval_68_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.c new file mode 120000 index 00000000..4bd7185c --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.h new file mode 120000 index 00000000..1ec5060e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_blas.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_blas.h new file mode 120000 index 00000000..ea010993 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_blas.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.c new file mode 120000 index 00000000..54d2cece --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_keypair.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.h new file mode 120000 index 00000000..e7b89d58 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_keypair.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.c new file mode 120000 index 00000000..309cceee --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_keypair_computation.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.h new file mode 120000 index 00000000..21af87a3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_keypair_computation.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_keypair_computation.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_publicmap_m4f.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_publicmap_m4f.c new file mode 120000 index 00000000..9e16d3ce --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/ov_publicmap_m4f.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.c new file mode 120000 index 00000000..fa9e4f05 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/parallel_matrix_op.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.h new file mode 120000 index 00000000..aeaa191f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/parallel_matrix_op.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/parallel_matrix_op.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/params.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/params.h new file mode 120000 index 00000000..171aee8d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/params.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip-pkc-skc/ref/params.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/sign.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/sign.c new file mode 120000 index 00000000..81be9d4d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/sign.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.c new file mode 120000 index 00000000..ef488faf --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.h new file mode 120000 index 00000000..c81bf3dc --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.c new file mode 120000 index 00000000..88a57ed4 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_hash.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.h new file mode 120000 index 00000000..b8aa605d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_hash.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_hash.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_malloc.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_malloc.h new file mode 120000 index 00000000..40a28f55 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_malloc.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_malloc.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.c b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.c new file mode 120000 index 00000000..302d55b9 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.c @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_prng.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.h new file mode 120000 index 00000000..1f6b0bcc --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_prng.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_prng.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_randombytes.h b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_randombytes.h new file mode 120000 index 00000000..2e723f2d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/utils_randombytes.h @@ -0,0 +1 @@ +../../ov-Ip-pkc/m4fstack/utils_randombytes.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/api.h b/crypto_sign/ov-Ip-pkc/m4fspeed/api.h new file mode 120000 index 00000000..8d09be99 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/api.h @@ -0,0 +1 @@ +../m4fstack/api.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas.h new file mode 120000 index 00000000..fcffc6eb --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas.h @@ -0,0 +1 @@ +../m4fstack/blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_comm.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_comm.h new file mode 120000 index 00000000..f866925d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_comm.h @@ -0,0 +1 @@ +../m4fstack/blas_comm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.c b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.c new file mode 120000 index 00000000..68334c07 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.c @@ -0,0 +1 @@ +../m4fstack/blas_matrix.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.h new file mode 120000 index 00000000..40dace73 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix.h @@ -0,0 +1 @@ +../m4fstack/blas_matrix.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c new file mode 120000 index 00000000..a7ceb6c2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.c @@ -0,0 +1 @@ +../m4fstack/blas_matrix_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h new file mode 120000 index 00000000..d6eef076 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_m4f.h @@ -0,0 +1 @@ +../m4fstack/blas_matrix_m4f.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.c b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.c new file mode 120000 index 00000000..4637f5dd --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.c @@ -0,0 +1 @@ +../m4fstack/blas_matrix_ref.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.h new file mode 120000 index 00000000..d7fd1e65 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_matrix_ref.h @@ -0,0 +1 @@ +../m4fstack/blas_matrix_ref.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/blas_u32.h b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_u32.h new file mode 120000 index 00000000..f50f53c7 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/blas_u32.h @@ -0,0 +1 @@ +../m4fstack/blas_u32.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/config.h b/crypto_sign/ov-Ip-pkc/m4fspeed/config.h new file mode 100644 index 00000000..2bb6d43e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/config.h @@ -0,0 +1,30 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +/* + * This file contains all implementation options that do not affect testvectors + * params.h contains other options. + */ + +// defined from the makefile +//#define _BLAS_UINT64_ +//#define _BLAS_SSE_ +//#define _BLAS_AVX2_ +//#define _BLAS_M4F_ +#define _BLAS_M4F_ +#define NDEBUG +//#define _UTILS_SUPERCOP_ // XXX: un-supported now +#define _UTILS_PQM4_ + +// default: +//`#define _UTILS_OPENSSL_ + + +// +// The following macro will implement randombytes() with C rand() +// Turn on only when there is no proper implementation +// +// #define _DEBUG_RANDOMBYTES_ + + +#endif diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf16.h b/crypto_sign/ov-Ip-pkc/m4fspeed/gf16.h new file mode 120000 index 00000000..f1b2b961 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf16.h @@ -0,0 +1 @@ +../m4fstack/gf16.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_asm.h b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_asm.h new file mode 120000 index 00000000..83929b13 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_asm.h @@ -0,0 +1 @@ +../m4fstack/gf256_asm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_madd.i b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_madd.i new file mode 120000 index 00000000..1bfb398d --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256_madd.i @@ -0,0 +1 @@ +../m4fstack/gf256_madd.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_gauss_elim_44.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_gauss_elim_44.S new file mode 120000 index 00000000..b05205e1 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_gauss_elim_44.S @@ -0,0 +1 @@ +../m4fstack/gf256mat_gauss_elim_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S new file mode 120000 index 00000000..d8d68faa --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_22.S @@ -0,0 +1 @@ +../m4fstack/gf256mat_inv_22.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S new file mode 120000 index 00000000..abbc5ad0 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_inv_44.S @@ -0,0 +1 @@ +../m4fstack/gf256mat_inv_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.S new file mode 120000 index 00000000..c7d3a0ff --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.S @@ -0,0 +1 @@ +../m4fstack/gf256mat_prod.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.i b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.i new file mode 120000 index 00000000..5f910f92 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256mat_prod.i @@ -0,0 +1 @@ +../m4fstack/gf256mat_prod.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S new file mode 120000 index 00000000..34575ab3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_2trimat_madd_68_68_44_44.S @@ -0,0 +1 @@ +../m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval.i b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval.i new file mode 120000 index 00000000..9488fd1b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval.i @@ -0,0 +1 @@ +../m4fstack/gf256trimat_eval.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S new file mode 120000 index 00000000..652cba37 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_112_44_publicinputs.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256trimat_eval_112_44_publicinputs.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_68_44.S b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_68_44.S new file mode 120000 index 00000000..50c84034 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/gf256trimat_eval_68_44.S @@ -0,0 +1 @@ +../m4fstack/gf256trimat_eval_68_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov.c b/crypto_sign/ov-Ip-pkc/m4fspeed/ov.c new file mode 120000 index 00000000..f5946be2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov.c @@ -0,0 +1 @@ +../m4fstack/ov.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov.h b/crypto_sign/ov-Ip-pkc/m4fspeed/ov.h new file mode 120000 index 00000000..06627b11 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov.h @@ -0,0 +1 @@ +../m4fstack/ov.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_blas.h b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_blas.h new file mode 120000 index 00000000..9744a132 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_blas.h @@ -0,0 +1 @@ +../m4fstack/ov_blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.c b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.c new file mode 120000 index 00000000..522e1033 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.c @@ -0,0 +1 @@ +../m4fstack/ov_keypair.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.h b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.h new file mode 120000 index 00000000..b4868924 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair.h @@ -0,0 +1 @@ +../m4fstack/ov_keypair.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.c b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.c new file mode 120000 index 00000000..9ca12831 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.c @@ -0,0 +1 @@ +../m4fstack/ov_keypair_computation.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.h b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.h new file mode 120000 index 00000000..766df4e5 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_keypair_computation.h @@ -0,0 +1 @@ +../m4fstack/ov_keypair_computation.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c new file mode 120000 index 00000000..e52644a6 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/ov_publicmap_m4f.c @@ -0,0 +1 @@ +../m4fstack/ov_publicmap_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.c b/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.c new file mode 120000 index 00000000..1ba01d38 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.c @@ -0,0 +1 @@ +../m4fstack/parallel_matrix_op.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.h b/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.h new file mode 120000 index 00000000..59e3138c --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/parallel_matrix_op.h @@ -0,0 +1 @@ +../m4fstack/parallel_matrix_op.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/params.h b/crypto_sign/ov-Ip-pkc/m4fspeed/params.h new file mode 120000 index 00000000..6b584825 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/params.h @@ -0,0 +1 @@ +../m4fstack/params.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/sign.c b/crypto_sign/ov-Ip-pkc/m4fspeed/sign.c new file mode 120000 index 00000000..03e60b2b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/sign.c @@ -0,0 +1 @@ +../m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils.c b/crypto_sign/ov-Ip-pkc/m4fspeed/utils.c new file mode 120000 index 00000000..975445f6 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils.c @@ -0,0 +1 @@ +../m4fstack/utils.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils.h b/crypto_sign/ov-Ip-pkc/m4fspeed/utils.h new file mode 120000 index 00000000..08d8deee --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils.h @@ -0,0 +1 @@ +../m4fstack/utils.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.c b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.c new file mode 120000 index 00000000..6b090204 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.c @@ -0,0 +1 @@ +../m4fstack/utils_hash.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.h b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.h new file mode 120000 index 00000000..49f3b974 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_hash.h @@ -0,0 +1 @@ +../m4fstack/utils_hash.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_malloc.h b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_malloc.h new file mode 120000 index 00000000..b6a7abe7 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_malloc.h @@ -0,0 +1 @@ +../m4fstack/utils_malloc.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.c b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.c new file mode 120000 index 00000000..d2bca203 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.c @@ -0,0 +1 @@ +../m4fstack/utils_prng.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.h b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.h new file mode 120000 index 00000000..044ac1c1 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_prng.h @@ -0,0 +1 @@ +../m4fstack/utils_prng.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/utils_randombytes.h b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_randombytes.h new file mode 120000 index 00000000..ab46a3d2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/utils_randombytes.h @@ -0,0 +1 @@ +../m4fstack/utils_randombytes.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/api.h b/crypto_sign/ov-Ip-pkc/m4fstack/api.h new file mode 120000 index 00000000..39b8a7eb --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/api.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas.h new file mode 120000 index 00000000..f5aca84a --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_comm.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas_comm.h new file mode 120000 index 00000000..8612664a --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_comm.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_comm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.c b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.c new file mode 120000 index 00000000..ea69d105 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.h new file mode 120000 index 00000000..cc1deaba --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.c b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.c new file mode 120000 index 00000000..83a76775 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.h new file mode 120000 index 00000000..06c32b74 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_m4f.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix_m4f.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.c b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.c new file mode 120000 index 00000000..d0a3cba2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix_ref.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.h new file mode 120000 index 00000000..24cc7b17 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_matrix_ref.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_matrix_ref.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/blas_u32.h b/crypto_sign/ov-Ip-pkc/m4fstack/blas_u32.h new file mode 120000 index 00000000..4323ae69 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/blas_u32.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/blas_u32.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/config.h b/crypto_sign/ov-Ip-pkc/m4fstack/config.h new file mode 120000 index 00000000..86a818e3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/config.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/config.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf16.h b/crypto_sign/ov-Ip-pkc/m4fstack/gf16.h new file mode 120000 index 00000000..9ebec052 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf16.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf16.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256_asm.h b/crypto_sign/ov-Ip-pkc/m4fstack/gf256_asm.h new file mode 120000 index 00000000..c8c70d6f --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256_asm.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256_asm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256_madd.i b/crypto_sign/ov-Ip-pkc/m4fstack/gf256_madd.i new file mode 120000 index 00000000..3e969b12 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256_madd.i @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256_madd.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_gauss_elim_44.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_gauss_elim_44.S new file mode 120000 index 00000000..66461c8b --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_gauss_elim_44.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256mat_gauss_elim_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_22.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_22.S new file mode 120000 index 00000000..444d4b5c --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_22.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256mat_inv_22.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_44.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_44.S new file mode 120000 index 00000000..b6d05202 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_inv_44.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256mat_inv_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.S new file mode 120000 index 00000000..3da0c6e9 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256mat_prod.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.i b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.i new file mode 120000 index 00000000..948f1a33 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256mat_prod.i @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256mat_prod.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S new file mode 120000 index 00000000..84d0e759 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_2trimat_madd_68_68_44_44.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256trimat_2trimat_madd_68_68_44_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval.i b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval.i new file mode 120000 index 00000000..d126e7a2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval.i @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256trimat_eval.i \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S new file mode 100644 index 00000000..33e6567e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_112_44_incremental_publicinputs.S @@ -0,0 +1,632 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256_madd.i" +.macro gf256_mul res, bb, aa0, pconst, tmp1, tmp2 + mov.w \tmp2, #0x01010101 + # bit 0 + ubfx.w \tmp1, \bb, #0, #1 + mul.w \res, \aa0, \tmp1 + + + # bit 1-7 + .set k, 1 + .rept 7 + // 7 cycles + and.w \tmp1, \tmp2, \aa0, lsr #7 + eor.w \aa0, \aa0, \tmp1, lsl #7 + + mul.w \tmp1, \tmp1, \pconst + eor.w \aa0, \tmp1, \aa0, lsl#1 + + ubfx.w \tmp1, \bb, #k, #1 + + mul.w \tmp1, \aa0, \tmp1 + eor.w \res, \res, \tmp1 + .set k, k+1 + .endr +.endm + + +.macro process_Px outerdim, prng, triangular, innerdim + mov.w ctrouter, \outerdim + 1: + vmov.w ctrouterf, ctrouter + + .if \triangular == 1 + mov.w ctrinner, ctrouter + .else + mov.w ctrinner, \innerdim + .endif + + .if \prng == 1 + vmov.w r2, buff + push.w {r0-r3, r12} + vmov.w r0, prngf + mov.w r1, r2 + + .if \triangular == 1 + mov.w r12, #44 + mul.w r2, r12, ctrouter + .else + mov.w r2, #44*44 + .endif + + bl.w prng_gen_publicinputs + pop.w {r0-r3, r12} + .endif + + ldrb.w xi, [xptr], #1 + cmp.w xi, #0 + beq.w 6f + + .if \triangular == 1 + sub.w xptr2, xptr, #1 + .else + vmov.w xptr2, xptr_orig + add.w xptr2, \outerdim + .endif + + 2: + + @ if ctrinner >= 4 + cmp.w ctrinner, #4 + blt.w 3f + + ldr.w xj, [xptr2], #4 + gf256_mul tmp, xi, xj, c1b, tmp3, tmp4 + + .set k, 0 + .rept 4 + // low + ubfx.w tmp3, tmp, #k*8, #4 + add.w tmp2, low, tmp3, lsl#6 + + .set i,0 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat, #i*8] + ldr.w tmp6, [mat, #i*8+4] + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .set i, i+1 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat, #40] + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + + // high + ubfx.w tmp3, tmp, #k*8+4, #4 + add.w tmp2, high, tmp3, lsl#6 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat], #4 + ldr.w tmp6, [mat], #4 + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat], #4 + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + .set k,k+1 + .endr + subs.w ctrinner, ctrinner, #4 + bne.w 2b + b.w 4f + @ else + 3: + ldrb.w xj, [xptr2], #1 + + gf256_mul tmp, xi, xj, c1b, tmp3, tmp4 + + // low + and.w tmp3, tmp, #0xF + add.w tmp2, low, tmp3, lsl#6 + .set i,0 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat, #i*8] + ldr.w tmp6, [mat, #i*8+4] + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .set i, i+1 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat, #40] + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + + // high + ubfx.w tmp3, tmp, #4, #4 + add.w tmp2, high, tmp3, lsl#6 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat], #4 + ldr.w tmp6, [mat], #4 + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat], #4 + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + subs.w ctrinner, ctrinner, #1 + bne.w 2b + 4: + vmov.w ctrouter, ctrouterf + subs.w ctrouter, ctrouter, #1 + bne.w 1b + b 5f + + 6: + vmov.w ctrouter, ctrouterf + .if \prng == 0 + mov.w tmp, #44 + mla.w mat, tmp, ctrouter, mat + .endif + subs.w ctrouter, ctrouter, #1 + bne.w 1b + 5: +.endm + +//void gf256trimat_eval_m4f_112_44_incremental_publicinputs(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256trimat_eval_m4f_112_44_incremental_publicinputs +.type gf256trimat_eval_m4f_112_44_incremental_publicinputs, %function +.align 2 +gf256trimat_eval_m4f_112_44_incremental_publicinputs: + push.w {r4-r11, r14} + vpush.w {s16-s31} + + low .req r0 + high .req r1 + mat .req r2 + xptr .req r3 + xptr2 .req r10 + xi .req r4 + xj .req r5 + + tmp .req r6 + tmp2 .req r7 + tmp3 .req r8 + tmp4 .req r9 + tmp5 .req r5 + tmp6 .req r14 + + + c1b .req r11 + + ctrinner .req r12 + ctrouter .req r14 + + matf .req s16 + ctrouterf .req s17 + yf .req s18 + lowf .req s19 + highf .req s20 + prngf .req s21 + buff .req s22 + xptr_orig .req s23 + + vmov.w xptr_orig, xptr + vmov.w yf, r0 + vmov.w prngf, r1 + vmov.w matf, mat + // _PUB_M_BYTE * _PUB_N + sub.w sp, sp, #44*68 + mov.w r2, sp + vmov.w buff, r2 + + sub.w sp, sp, #64*16 + mov.w r0, sp + vmov.w lowf, r0 + + sub.w sp, sp, #64*16 + mov.w r1, sp + vmov.w highf, r1 + + // init to zero + push.w {r0-r3} + mov.w r0, r1 + mov.w r1, #0 + mov.w r2, #2*16*64 + bl.w memset + pop.w {r0-r3} + + + vmov.w lowf, r0 + vmov.w highf, r1 + mov.w c1b, #0x1b + + + + # P1 (triangular) + process_Px 68, 1, 1, xxx + + # P2 (square) + vmov.w xptr, xptr_orig + process_Px 68, 1, 0, 44 + + # P3 (triangular) + vmov.w xptr, xptr_orig + vmov.w mat, matf + add.w xptr, #68 + process_Px 44, 0, 1, xxx + + b madd_reduce_gf256_incremental + + + + +.macro load_accumulate first, src, incr, t0, t1, t2, t3, t4, t5, t6, t7, tmp, acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10 + .if \first == 1 + vldr.w \acc0, [\src, #4*0] + vldr.w \acc1, [\src, #4*1] + vldr.w \acc2, [\src, #4*2] + vldr.w \acc3, [\src, #4*3] + vldr.w \acc4, [\src, #4*4] + vldr.w \acc5, [\src, #4*5] + vldr.w \acc6, [\src, #4*6] + vldr.w \acc7, [\src, #4*7] + vldr.w \acc8, [\src, #4*8] + vldr.w \acc9, [\src, #4*9] + vldr.w \acc10, [\src, #4*10] + add.w \src, \src, \incr + .else + + + ldr.w \t0, [\src, #8*4] + ldr.w \t1, [\src, #9*4] + ldr.w \t2, [\src, #10*4] + + vmov.w \tmp, \acc8 + eor.w \tmp, \t0 + vmov.w \acc8, \tmp + + vmov.w \tmp, \acc9 + eor.w \tmp, \t1 + vmov.w \acc9, \tmp + + vmov.w \tmp, \acc10 + eor.w \tmp, \t2 + vmov.w \acc10, \tmp + + + ldr.w \t1, [\src, #1*4] + ldr.w \t2, [\src, #2*4] + ldr.w \t3, [\src, #3*4] + ldr.w \t4, [\src, #4*4] + ldr.w \t5, [\src, #5*4] + ldr.w \t6, [\src, #6*4] + ldr.w \t7, [\src, #7*4] + .if \incr < 256 + ldr.w \t0, [\src], #\incr + .else + ldr.w \t0, [\src] + add.w \src, \incr + .endif + + vmov.w \tmp, \acc0 + eor.w \tmp, \t0 + vmov.w \acc0, \tmp + + vmov.w \tmp, \acc1 + eor.w \tmp, \t1 + vmov.w \acc1, \tmp + + vmov.w \tmp, \acc2 + eor.w \tmp, \t2 + vmov.w \acc2, \tmp + + vmov.w \tmp, \acc3 + eor.w \tmp, \t3 + vmov.w \acc3, \tmp + + vmov.w \tmp, \acc4 + eor.w \tmp, \t4 + vmov.w \acc4, \tmp + + vmov.w \tmp, \acc5 + eor.w \tmp, \t5 + vmov.w \acc5, \tmp + + vmov.w \tmp, \acc6 + eor.w \tmp, \t6 + vmov.w \acc6, \tmp + + vmov.w \tmp, \acc7 + eor.w \tmp, \t7 + vmov.w \acc7, \tmp + + .endif +.endm + + +.macro mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, bb, acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \bb, \c01010101, \pconst, \tmp8 + + vmov.w \tmp0, \tt0 + vmov.w \tmp1, \tt1 + vmov.w \tmp2, \tt2 + vmov.w \tmp3, \tt3 + + vmov.w \tmp4, \acc0 + vmov.w \tmp5, \acc1 + vmov.w \tmp6, \acc2 + vmov.w \tmp7, \acc3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc0, \tmp4 + vmov.w \acc1, \tmp5 + vmov.w \acc2, \tmp6 + vmov.w \acc3, \tmp7 + + vmov.w \tmp0, \tt4 + vmov.w \tmp1, \tt5 + vmov.w \tmp2, \tt6 + vmov.w \tmp3, \tt7 + + vmov.w \tmp4, \acc4 + vmov.w \tmp5, \acc5 + vmov.w \tmp6, \acc6 + vmov.w \tmp7, \acc7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc4, \tmp4 + vmov.w \acc5, \tmp5 + vmov.w \acc6, \tmp6 + vmov.w \acc7, \tmp7 + + vmov.w \tmp0, \tt8 + vmov.w \tmp1, \tt9 + vmov.w \tmp2, \tt10 + + vmov.w \tmp4, \acc8 + vmov.w \tmp5, \acc9 + vmov.w \tmp6, \acc10 + + gf256_madd 3, \tmp4, \tmp5, \tmp6, xxx, \tmp0, \tmp1, \tmp2, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc8, \tmp4 + vmov.w \acc9, \tmp5 + vmov.w \acc10, \tmp6 +.endm + + +.align 2 +madd_reduce_gf256_incremental: + vmov.w r0, yf + vmov.w r1, lowf + vmov.w r2, highf + + .unreq low + .unreq high + .unreq mat + .unreq xptr + .unreq xi + .unreq xj + + .unreq tmp + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq c1b + .unreq ctrinner + .unreq ctrouter + + + .unreq buff + .unreq lowf + .unreq highf + .unreq yf + .unreq prngf + + + tmpy .req r0 + lowhigh .req r1 + lowf .req s30 + highf .req s31 + + + tmp0 .req r4 + tmp1 .req r5 + tmp2 .req r6 + tmp3 .req r7 + tmp4 .req r8 + tmp5 .req r9 + tmp6 .req r10 + tmp7 .req r11 + tmp8 .req r1 + tmp9 .req r2 + c01010101 .req r3 + pconst .req r14 + tmp .req r12 + + yy0 .req s0 + yy1 .req s1 + yy2 .req s2 + yy3 .req s3 + yy4 .req s4 + yy5 .req s5 + yy6 .req s6 + yy7 .req s7 + yy8 .req s8 + yy9 .req s9 + yy10 .req s10 + + tt0 .req s11 + tt1 .req s12 + tt2 .req s13 + tt3 .req s14 + tt4 .req s15 + tt5 .req s16 + tt6 .req s17 + tt7 .req s18 + tt8 .req s19 + tt9 .req s20 + tt10 .req s21 + + fbx0 .req s22 + fbx1 .req s23 + fbx2 .req s24 + fbx3 .req s25 + fbx4 .req s26 + fbx5 .req s27 + fbx6 .req s28 + fbx7 .req s29 + + vmov.w lowf, r1 + vmov.w highf, r2 + + mov.w c01010101, #0x01010101 + mov.w pconst, #0x1b + + // x^0 + add.w lowhigh, #64 + .set first, 1 + .rept 8 + load_accumulate first, lowhigh, 64*2, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10 + .set first, 0 + .endr + + // TODO: this can be done much faster; but does not matter much + // x^1 + vmov.w lowhigh, lowf + add.w lowhigh, #2*64 + .set first, 1 + .rept 4 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + load_accumulate 0, lowhigh, 3*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + // acc += tmp*x^1 + mov.w tmp, #2 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + // x^2 + vmov.w lowhigh, lowf + add.w lowhigh, #4*64 + .set first, 1 + .rept 2 + .rept 3 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 5*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^2 + mov.w tmp, #4 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^3 + vmov.w lowhigh, lowf + add.w lowhigh, #8*64 + .set first, 1 + .rept 1 + .rept 7 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 9*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^3 + mov.w tmp, #8 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + // x^4 + vmov.w lowhigh, highf + add.w lowhigh, #64 + .set first, 1 + .rept 8 + load_accumulate first, lowhigh, 2*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + // acc += tmp*x^4 + mov.w tmp, #16 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^5 + vmov.w lowhigh, highf + add.w lowhigh, #2*64 + .set first, 1 + .rept 4 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + load_accumulate 0, lowhigh, 3*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + // acc += tmp*x^5 + mov.w tmp, #32 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^6 + vmov.w lowhigh, highf + add.w lowhigh, #4*64 + .set first, 1 + .rept 2 + .rept 3 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 5*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^6 + mov.w tmp, #64 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + + // x^7 + vmov.w lowhigh, highf + add.w lowhigh, #8*64 + .set first, 1 + .rept 1 + .rept 7 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 9*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^7 + mov.w tmp, #128 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + vstr.w yy0, [tmpy, #0*4] + vstr.w yy1, [tmpy, #1*4] + vstr.w yy2, [tmpy, #2*4] + vstr.w yy3, [tmpy, #3*4] + vstr.w yy4, [tmpy, #4*4] + vstr.w yy5, [tmpy, #5*4] + vstr.w yy6, [tmpy, #6*4] + vstr.w yy7, [tmpy, #7*4] + vstr.w yy8, [tmpy, #8*4] + vstr.w yy9, [tmpy, #9*4] + vstr.w yy10,[tmpy, #10*4] + + mov.w tmp, #44*68+16*64+16*64 + add.w sp, sp, tmp + vpop.w {s16-s31} + pop.w {r4-r11, pc} \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_68_44.S b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_68_44.S new file mode 120000 index 00000000..d4769ebc --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/gf256trimat_eval_68_44.S @@ -0,0 +1 @@ +../../ov-Ip/m4f/gf256trimat_eval_68_44.S \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov.c b/crypto_sign/ov-Ip-pkc/m4fstack/ov.c new file mode 120000 index 00000000..9dd14074 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov.h b/crypto_sign/ov-Ip-pkc/m4fstack/ov.h new file mode 120000 index 00000000..b199dde8 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_blas.h b/crypto_sign/ov-Ip-pkc/m4fstack/ov_blas.h new file mode 120000 index 00000000..7a6c5eea --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_blas.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.c b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.c new file mode 120000 index 00000000..d6523c9e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_keypair.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.h b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.h new file mode 120000 index 00000000..c2ddf464 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_keypair.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.c b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.c new file mode 120000 index 00000000..ab895668 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_keypair_computation.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.h b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.h new file mode 120000 index 00000000..711cfff0 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_keypair_computation.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_keypair_computation.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c b/crypto_sign/ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c new file mode 120000 index 00000000..4875541e --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/ov_publicmap_m4f.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/ov_publicmap_m4f.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.c b/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.c new file mode 120000 index 00000000..e80f84f2 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/parallel_matrix_op.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.h b/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.h new file mode 120000 index 00000000..fd7d01fe --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/parallel_matrix_op.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/parallel_matrix_op.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/params.h b/crypto_sign/ov-Ip-pkc/m4fstack/params.h new file mode 120000 index 00000000..0da1f3c6 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/params.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip-pkc/ref/params.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/sign.c b/crypto_sign/ov-Ip-pkc/m4fstack/sign.c new file mode 120000 index 00000000..397f0c09 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/sign.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils.c b/crypto_sign/ov-Ip-pkc/m4fstack/utils.c new file mode 120000 index 00000000..38272961 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils.h b/crypto_sign/ov-Ip-pkc/m4fstack/utils.h new file mode 120000 index 00000000..5412e4ab --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.c b/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.c new file mode 120000 index 00000000..530142ab --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_hash.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.h b/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.h new file mode 120000 index 00000000..87db8010 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_hash.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_hash.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_malloc.h b/crypto_sign/ov-Ip-pkc/m4fstack/utils_malloc.h new file mode 120000 index 00000000..64ef6f94 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_malloc.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_malloc.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.c b/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.c new file mode 120000 index 00000000..114992e3 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.c @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_prng.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.h b/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.h new file mode 120000 index 00000000..f3410245 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_prng.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_prng.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/utils_randombytes.h b/crypto_sign/ov-Ip-pkc/m4fstack/utils_randombytes.h new file mode 120000 index 00000000..0b9c6b68 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/utils_randombytes.h @@ -0,0 +1 @@ +../../ov-Ip/m4f/utils_randombytes.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/api.h b/crypto_sign/ov-Ip/m4f/api.h new file mode 120000 index 00000000..609e3d35 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/api.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/api.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas.h b/crypto_sign/ov-Ip/m4f/blas.h new file mode 120000 index 00000000..89843ef3 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_comm.h b/crypto_sign/ov-Ip/m4f/blas_comm.h new file mode 120000 index 00000000..2e762201 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_comm.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/blas_comm.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix.c b/crypto_sign/ov-Ip/m4f/blas_matrix.c new file mode 120000 index 00000000..8fce6e1d --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/blas_matrix.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix.h b/crypto_sign/ov-Ip/m4f/blas_matrix.h new file mode 120000 index 00000000..b0629fff --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/blas_matrix.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.c b/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.c new file mode 100644 index 00000000..61ce1aa3 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.c @@ -0,0 +1,212 @@ +#include "blas_matrix_m4f.h" +#include "blas_matrix_ref.h" +#include "blas.h" +#include "params.h" +#include "config.h" + +#ifdef _USE_GF16 +#include "gf16_asm.h" +#else +#include "gf256_asm.h" +#endif + +//TODO: check if this can be removed +#include "parallel_matrix_op.h" + +static inline +void gf256mat_submat( uint8_t * mat2 , unsigned veclen2_byte , unsigned st , const uint8_t * mat , unsigned veclen_byte , unsigned n_vec ) +{ + for(unsigned i=0;iS , Fs->P1 , Fs->O); + #else + gf256trimat_2trimat_madd_m4f_68_68_44_44( Fs->S , Fs->P1 , Fs->O); + #endif +} +#endif + diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.h b/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.h new file mode 100644 index 00000000..1303d2c5 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix_m4f.h @@ -0,0 +1,36 @@ +#ifndef _BLAS_MATRIX_M4F_H_ +#define _BLAS_MATRIX_M4F_H_ + +#include +#include "ov_keypair.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +void gf16mat_prod_m4f(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b); +unsigned gf16mat_LDUinv_m4f(uint8_t *mat_U_AinvB, uint8_t *mat_Ainv, uint8_t *mat_CAinvB_inv, uint8_t *mat_L_C, const uint8_t *matA , unsigned len); +unsigned gf16mat_inv_m4f(uint8_t * inv_a , const uint8_t * a , unsigned H ); +void batch_quad_trimat_eval_gf16_m4f(unsigned char * y, const unsigned char * trimat, const unsigned char * x, unsigned dim , unsigned size_batch); + +void gf256mat_prod_m4f(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b); +unsigned gf256mat_LDUinv_m4f(uint8_t *mat_U_AinvB, uint8_t *mat_Ainv, uint8_t *mat_CAinvB_inv, uint8_t *mat_L_C, const uint8_t *matA , unsigned len); +unsigned gf256mat_inv_m4f(uint8_t * inv_a , const uint8_t * a , unsigned H ); +void batch_quad_trimat_eval_gf256_m4f(unsigned char * y, const unsigned char * trimat, const unsigned char * x, unsigned dim , unsigned size_batch); + +void ov_pkc_calculate_F_from_Q_m4f( sk_t * Fs); + + +unsigned gf256mat_gaussian_elim_m4f(uint8_t *sq_col_mat_a , uint8_t *constant, unsigned len); +unsigned gf16mat_gaussian_elim_m4f(uint8_t *sq_col_mat_a , uint8_t *constant, unsigned len); + + + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix_ref.c b/crypto_sign/ov-Ip/m4f/blas_matrix_ref.c new file mode 100644 index 00000000..c4952ad0 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix_ref.c @@ -0,0 +1,532 @@ +//// @file blas_matrix.c +/// @brief The standard implementations for blas_matrix.h +/// + +#include "blas_comm.h" +#include "blas.h" + +#include "blas_matrix_ref.h" + +#include +#include + +/// This implementation depends on these vector functions : +/// 0. gf16v_mul_scalar +/// gf16v_madd +/// gf256v_add +/// gf256v_mul_scalar +/// gf256v_madd +/// +/// 1. gf256v_conditional_add for _gf(16/256)mat_gauss_elim() +/// these functions have to be defined in blas.h + + + + +/////////// matrix-vector multiplications //////////////////////////////// + +void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + gf256v_set_zero(c, n_A_vec_byte); + for (unsigned i = 0; i < n_A_width; i++) { + uint8_t bb = gf16v_get_ele(b, i); + gf16v_madd(c, matA, bb, n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + gf256v_set_zero(c, n_A_vec_byte); + for (unsigned i = 0; i < n_A_width; i++) { + gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + + + + + + + + + + +static inline +void gf256mat_submat( uint8_t * mat2 , unsigned veclen2_byte , unsigned st , const uint8_t * mat , unsigned veclen_byte , unsigned n_vec ) +{ + for(unsigned i=0;i>1)&(~(_BLAS_UNIT_LEN_-1))); + uint8_t *ai = mat + i*w_byte; + for (unsigned j = i + 1; j < h; j++) { + uint8_t *aj = mat + j*w_byte; + gf256v_conditional_add(ai + i_start, !gf16_is_nonzero(gf16v_get_ele(ai, i)), aj + i_start, w_byte - i_start ); + } + uint8_t pivot = gf16v_get_ele(ai, i); + r8 &= gf16_is_nonzero(pivot); + pivot = gf16_inv(pivot); + gf16v_mul_scalar(ai + i_start, pivot, w_byte - i_start ); + for (unsigned j = 0; j < h; j++) { + if (i == j) continue; + uint8_t *aj = mat + j*w_byte; + gf16v_madd(aj + i_start, ai + i_start, gf16v_get_ele(aj, i), w_byte-i_start); + } + } + return r8; +} + + +static +unsigned gf16mat_gauss_elim_ref(uint8_t *mat, unsigned h, unsigned w) { + const unsigned w_byte = (w+1)>>1; + + unsigned r8 = 1; + for (unsigned i = 0; i < h; i++) { + unsigned i_start = ((i>>1)&(~(_BLAS_UNIT_LEN_-1))); + //unsigned i_start = (i>>1); + uint8_t *ai = mat + i*w_byte; + for (unsigned j = i + 1; j < h; j++) { + uint8_t *aj = mat + j*w_byte; + gf256v_conditional_add(ai + i_start, !gf16_is_nonzero(gf16v_get_ele(ai, i)), aj + i_start, w_byte - i_start ); + } + uint8_t pivot = gf16v_get_ele(ai, i); + r8 &= gf16_is_nonzero(pivot); + pivot = gf16_inv(pivot); + gf16v_mul_scalar(ai + i_start, pivot, w_byte - i_start ); + for (unsigned j = 0; j < h; j++) { + if (i == j) continue; + uint8_t *aj = mat + j*w_byte; + gf16v_madd(aj + i_start, ai + i_start, gf16v_get_ele(aj, i), w_byte-i_start); + } + } + return r8; +} + + +///////////////////////////////////////////////// + + +static +unsigned gf256mat_gauss_elim_ref( uint8_t * mat , unsigned h , unsigned w ) +{ + unsigned r8 = 1; + + for(unsigned i=0;i>1; + for (unsigned i = 0; i < H; i++) { + uint8_t *ai = mat + i * H; + gf256v_set_zero(ai, H ); + gf256v_add(ai, a + i * h_byte, h_byte); + gf16v_set_ele(ai + h_byte, i, 1); + } + uint8_t r8 = gf16mat_gauss_elim_ref(mat, H , H*2); + gf256mat_submat(inv_a, h_byte, h_byte, mat, H, H); + + return r8; +} + + +///////////////////////////////////////////////// + + + + +static +unsigned gf256mat_inv_32x32_ref( uint8_t * inv_a , const uint8_t * a ) +{ + const unsigned H=32; + uint8_t mat[H*H*2]; + for(unsigned i=0;i>1 , mat_a , a_veclen_byte ); +} + + +// +// If matC, matA, and matB are row-major matrices -> matC = matA x matB +// If matC, matA, and matB are column-major matrices -> matC = matB x matA +// XXX: optimization with Strassen multiplication +// +void gf256mat_rowmat_mul_ref(uint8_t *matC, const uint8_t *matA, unsigned src_A_n_vec, unsigned src_A_veclen_byte, const uint8_t *matB, unsigned dest_B_veclen_byte) +{ + gf256v_set_zero( matC , src_A_n_vec*dest_B_veclen_byte ); + for( unsigned i=0; i0;i--) { + for(int j=0;j column-major, i.e., transpose + gf256v_madd( constant , column , constant[i] , i ); + } +} + + +void gf16mat_back_substitute_ref( uint8_t *constant, const uint8_t *sq_row_mat_a, unsigned len) +{ + //const unsigned MAX_H=64; +#define MAX_H (64) + uint8_t column[MAX_H] = {0}; +#undef MAX_H + unsigned width_byte = (len+1)/2; + for(int i=len-1;i>0;i--) { + for(int j=0;j column-major, i.e., transpose + uint8_t ele = gf16v_get_ele( sq_row_mat_a+width_byte*j , i ); + gf16v_set_ele( column , j , ele ); + } + gf16v_set_ele( column , i , 0 ); // pad to last byte + gf16v_madd( constant , column , gf16v_get_ele(constant,i) , (i+1)/2 ); + } +} \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/blas_matrix_ref.h b/crypto_sign/ov-Ip/m4f/blas_matrix_ref.h new file mode 100644 index 00000000..c873bfc1 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_matrix_ref.h @@ -0,0 +1,64 @@ +/// @file blas_matrix_ref.h +/// @brief linear algebra functions for matrix op. +/// +#ifndef _BLAS_MATRIX_REF_H_ +#define _BLAS_MATRIX_REF_H_ + +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + +///////////////// Section: multiplications //////////////////////////////// + +void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b); + +void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b); + + + +void gf16mat_rowmat_mul_ref(uint8_t *matC, const uint8_t *matA, unsigned height_A, unsigned width_A_byte, const uint8_t *matB, unsigned width_B_byte); + +void gf256mat_rowmat_mul_ref(uint8_t *matC, const uint8_t *matA, unsigned height_A, unsigned width_A_byte, const uint8_t *matB, unsigned width_B_byte); + + +void gf16mat_colmat_mul_ref(uint8_t *mat_c, const uint8_t *mat_a, unsigned a_veclen_byte, unsigned a_n_vec, const uint8_t *mat_b, unsigned b_n_vec); + +void gf256mat_colmat_mul_ref(uint8_t *mat_c, const uint8_t *mat_a, unsigned a_veclen_byte, unsigned a_n_vec, const uint8_t *mat_b, unsigned b_n_vec); + + +///////////////////////////////////////////////////// + +unsigned gf16mat_inv_ref(uint8_t *inv_a, const uint8_t *a , unsigned len ); + +unsigned gf256mat_inv_ref(uint8_t *inv_a, const uint8_t *a , unsigned len ); + + +///////////////////////////////////////////////////// + +unsigned gf256mat_LDUinv_ref(uint8_t *mat_U_AinvB, uint8_t *mat_Ainv, uint8_t *mat_CAinvB_inv, uint8_t *mat_L_C, const uint8_t *matA , unsigned len); + +void gf256mat_LDUinv_prod_ref(uint8_t *c, const uint8_t *mat_U_AinvB, const uint8_t *mat_Ainv, const uint8_t *mat_CAinvB_inv, const uint8_t *mat_L_C, const uint8_t * b , unsigned len); + + +unsigned gf16mat_LDUinv_ref(uint8_t *mat_U_AinvB, uint8_t *mat_Ainv, uint8_t *mat_CAinvB_inv, uint8_t *mat_L_C, const uint8_t *matA , unsigned mat_dim); + +void gf16mat_LDUinv_prod_ref(uint8_t *c, const uint8_t *mat_U_AinvB, const uint8_t *mat_Ainv, const uint8_t *mat_CAinvB_inv, const uint8_t *mat_L_C, const uint8_t * b , unsigned veclen_byte ); + + + + +void gf256mat_back_substitute_ref( uint8_t *constant, const uint8_t *sq_row_mat_a, unsigned len); + +void gf16mat_back_substitute_ref( uint8_t *constant, const uint8_t *sq_row_mat_a, unsigned len); + +#ifdef __cplusplus +} +#endif + +#endif // _BLAS_MATRIX_REF_H_ + diff --git a/crypto_sign/ov-Ip/m4f/blas_u32.h b/crypto_sign/ov-Ip/m4f/blas_u32.h new file mode 120000 index 00000000..645ee513 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/blas_u32.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/blas_u32.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/config.h b/crypto_sign/ov-Ip/m4f/config.h new file mode 100644 index 00000000..739dd7cc --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/config.h @@ -0,0 +1,31 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +/* + * This file contains all implementation options that do not affect testvectors + * params.h contains other options. + */ + +// defined from the makefile +//#define _BLAS_UINT64_ +//#define _BLAS_SSE_ +//#define _BLAS_AVX2_ +//#define _BLAS_M4F_ +#define _BLAS_M4F_ +#define NDEBUG +#define _SAVE_MEMORY_ +//#define _UTILS_SUPERCOP_ // XXX: un-supported now +#define _UTILS_PQM4_ + +// default: +//`#define _UTILS_OPENSSL_ + + +// +// The following macro will implement randombytes() with C rand() +// Turn on only when there is no proper implementation +// +// #define _DEBUG_RANDOMBYTES_ + + +#endif diff --git a/crypto_sign/ov-Ip/m4f/gf16.h b/crypto_sign/ov-Ip/m4f/gf16.h new file mode 120000 index 00000000..d0685fea --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf16.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/gf16.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256_asm.h b/crypto_sign/ov-Ip/m4f/gf256_asm.h new file mode 100644 index 00000000..a47ee353 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256_asm.h @@ -0,0 +1,33 @@ +#ifndef GF256_ASM__H +#define GF256_ASM__H + +#include +#include "utils_prng.h" + +// gf256mat_prod.S +void gf256mat_prod_m4f_1936_68_normal_normal(uint8_t *c, const uint8_t *matA, const uint8_t *b); +void gf256mat_prod_m4f_68_44_normal_normal(uint8_t *c, const uint8_t *matA, const uint8_t *b); +void gf256mat_prod_m4f_44_X_normal_normal(uint8_t *c, const uint8_t *matA, const uint8_t *b, size_t n_A_width); + +// gf256mat_inv_22.S +unsigned gf256mat_inv_m4f_22(uint8_t *inv, const uint8_t *mat); + +// gf256mat_inv_44.S +unsigned gf256mat_inv_m4f_44(uint8_t *inv, const uint8_t *mat); + +// gf256trimat_eval_68_44.S +void gf256trimat_eval_m4f_68_44(uint8_t * y, const uint8_t * trimat, const uint8_t * x); + +// gf256trimat_eval_112_44_publicinputs.S +void gf256trimat_eval_m4f_112_44_publicinputs(uint8_t * y, const uint8_t * trimat, const uint8_t * x); + +// gf256trimat_eval_112_44_incremental_publicinputs.S +void gf256trimat_eval_m4f_112_44_incremental_publicinputs(uint8_t * y, prng_publicinputs_t *prng, const uint8_t * trimat, const uint8_t * x); + +// gf256trimat_2trimat_madd_68_68_44_44.S +void gf256trimat_2trimat_madd_m4f_68_68_44_44(uint8_t *c, const uint8_t *a, const uint8_t *b); + +// gf256mat_gauss_elim_44.S +uint8_t gf256mat_gauss_elim_row_echolen_m4f_44(uint8_t *mat); + +#endif \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256_madd.i b/crypto_sign/ov-Ip/m4f/gf256_madd.i new file mode 100644 index 00000000..e669fc50 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256_madd.i @@ -0,0 +1,174 @@ +// GF256 multiplication for uint32_t (i.e., 4 elements packed into one register) + +// 36 cycles +.macro gf256_madd_precompb fbx0, fbx1, fbx2,fbx3, fbx4, fbx5, fbx6, fbx7, bb, c01010101, pconst, tmp1 + // bx^0 + vmov.w \fbx0, \bb + + // bx^1 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx1, \bb + + // bx^2 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx2, \bb + + // bx^3 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx3, \bb + + // bx^4 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx4, \bb + + // bx^5 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx5, \bb + + // bx^6 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx6, \bb + + // bx^7 + and.w \tmp1, \c01010101, \bb, lsr #7 + eor.w \bb, \bb, \tmp1, lsl #7 + mul.w \tmp1, \tmp1, \pconst + eor.w \bb, \tmp1, \bb, lsl#1 + vmov.w \fbx7, \bb +.endm + + +// 13 cc +.macro gf256_madd_inner k, num, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx, c01010101, tmp0, tmp1 + vmov.w \tmp1, \fbx + + and.w \tmp0, \c01010101, \aa0, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc0, \acc0, \tmp0 + + .if \num >= 2 + and.w \tmp0, \c01010101, \aa1, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc1, \acc1, \tmp0 + .endif + + .if \num >= 3 + and.w \tmp0, \c01010101, \aa2, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc2, \acc2, \tmp0 + .endif + + .if \num >= 4 + and.w \tmp0, \c01010101, \aa3, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc3, \acc3, \tmp0 + .endif +.endm + +// 13*8 = 104 cc +.macro gf256_madd num, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, c01010101, tmp0, tmp1 + gf256_madd_inner #0, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx0, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #1, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx1, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #2, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx2, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #3, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx3, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #4, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx4, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #5, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx5, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #6, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx6, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #7, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx7, \c01010101, \tmp0, \tmp1 +.endm + + +// 13 cc +.macro gf256_madd_x4_inner k, idx, num, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx, c01010101, tmp0, tmp1 + vmov.w \tmp1, \fbx + ubfx.w \tmp1, \tmp1, \idx*8, #8 + + and.w \tmp0, \c01010101, \aa0, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc0, \acc0, \tmp0 + + .if \num >= 2 + and.w \tmp0, \c01010101, \aa1, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc1, \acc1, \tmp0 + .endif + + .if \num >= 3 + and.w \tmp0, \c01010101, \aa2, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc2, \acc2, \tmp0 + .endif + + .if \num >= 4 + and.w \tmp0, \c01010101, \aa3, lsr\k + mul.w \tmp0, \tmp1, \tmp0 + eor.w \acc3, \acc3, \tmp0 + .endif +.endm + +// 13*8 = 104 cc +.macro gf256_madd_x4 num, idx, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, c01010101, tmp0, tmp1 + gf256_madd_x4_inner #0, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx0, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #1, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx1, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #2, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx2, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #3, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx3, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #4, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx4, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #5, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx5, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #6, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx6, \c01010101, \tmp0, \tmp1 + gf256_madd_x4_inner #7, \idx, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx7, \c01010101, \tmp0, \tmp1 +.endm + + + +.macro gf256_mul_inner k, num, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx, c01010101, tmp0, tmp1 + vmov.w \tmp1, \fbx + + and.w \tmp0, \c01010101, \aa0, lsr\k + mul.w \acc0, \tmp1, \tmp0 + + + .if \num >= 2 + and.w \tmp0, \c01010101, \aa1, lsr\k + mul.w \acc1, \tmp1, \tmp0 + .endif + + .if \num >= 3 + and.w \tmp0, \c01010101, \aa2, lsr\k + mul.w \acc2, \tmp1, \tmp0 + .endif + + .if \num >= 4 + and.w \tmp0, \c01010101, \aa3, lsr\k + mul.w \acc3, \tmp1, \tmp0 + .endif +.endm + + +.macro gf256_mul_u32 num, acc0, acc1, acc2, acc3, aa0, aa1, aa2, aa3, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, c01010101, tmp0, tmp1 + gf256_mul_inner #0, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx0, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #1, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx1, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #2, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx2, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #3, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx3, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #4, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx4, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #5, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx5, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #6, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx6, \c01010101, \tmp0, \tmp1 + gf256_madd_inner #7, \num, \acc0, \acc1, \acc2, \acc3, \aa0, \aa1, \aa2, \aa3, \fbx7, \c01010101, \tmp0, \tmp1 +.endm diff --git a/crypto_sign/ov-Ip/m4f/gf256mat_gauss_elim_44.S b/crypto_sign/ov-Ip/m4f/gf256mat_gauss_elim_44.S new file mode 100644 index 00000000..251c4491 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256mat_gauss_elim_44.S @@ -0,0 +1,421 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256_madd.i" + +.macro gf256_inv g, f, delta, r, v, mdelta, tmp, tmp2, tmp3 + lsl.w \g, \g, #1 + mov.w \f, #0x11b + mov.w \delta, #1 + mov.w \r, #0x100 + mov.w \v, #0 + + // 15 instructions + .rept 15 + eor.w \tmp, \f, \g + eor.w \tmp2, \v, \r + + lsrs.w \tmp3, \g, #8 + itt ne + eorne.n \g, \g, \f + eorne.w \r, \r, \v + + neg \mdelta, \delta + tst \tmp3, \mdelta, lsr#31 + + nop.n + ittte ne + addne \delta, \mdelta, #1 + eorne \f, \f, \tmp + eorne \v, \v, \tmp2 + addeq.w \delta, #1 + + lsl \g, \g, #1 + lsr \v, \v, #1 + .endr + and \g, \v, #0xff +.endm + + +// computes _gf256v_mul_scalar_u32( ai , pivot , w); +.macro madd_row pivot, aj, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp4, [\aj, #4*0] + ldr.w \tmp5, [\aj, #4*1] + ldr.w \tmp6, [\aj, #4*2] + ldr.w \tmp7, [\aj, #4*3] + + vmov.w \tmp0, \matf0 + vmov.w \tmp1, \matf1 + vmov.w \tmp2, \matf2 + vmov.w \tmp3, \matf3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*0] + str.w \tmp5, [\aj, #4*1] + str.w \tmp6, [\aj, #4*2] + str.w \tmp7, [\aj, #4*3] + + ldr.w \tmp4, [\aj, #4*4] + ldr.w \tmp5, [\aj, #4*5] + ldr.w \tmp6, [\aj, #4*6] + ldr.w \tmp7, [\aj, #4*7] + + vmov.w \tmp0, \matf4 + vmov.w \tmp1, \matf5 + vmov.w \tmp2, \matf6 + vmov.w \tmp3, \matf7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*4] + str.w \tmp5, [\aj, #4*5] + str.w \tmp6, [\aj, #4*6] + str.w \tmp7, [\aj, #4*7] + + ldr.w \tmp4, [\aj, #4*8] + ldr.w \tmp5, [\aj, #4*9] + ldr.w \tmp6, [\aj, #4*10] + ldr.w \tmp7, [\aj, #4*11] + + vmov.w \tmp0, \matf8 + vmov.w \tmp1, \matf9 + vmov.w \tmp2, \matf10 + vmov.w \tmp3, \matf11 + + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*8] + str.w \tmp5, [\aj, #4*9] + str.w \tmp6, [\aj, #4*10] + str.w \tmp7, [\aj, #4*11] +.endm + + + +// computes _gf256v_mul_scalar_u32( ai , pivot , w); +.macro madd_row_second pivot, aj, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + @ ldr.w \tmp4, [\aj, #4*0] + @ ldr.w \tmp5, [\aj, #4*1] + @ ldr.w \tmp6, [\aj, #4*2] + @ ldr.w \tmp7, [\aj, #4*3] + + @ vmov.w \tmp0, \matf0 + @ vmov.w \tmp1, \matf1 + @ vmov.w \tmp2, \matf2 + @ vmov.w \tmp3, \matf3 + + @ gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + @ str.w \tmp4, [\aj, #4*0] + @ str.w \tmp5, [\aj, #4*1] + @ str.w \tmp6, [\aj, #4*2] + @ str.w \tmp7, [\aj, #4*3] + + @ ldr.w \tmp4, [\aj, #4*4] + @ ldr.w \tmp5, [\aj, #4*5] + ldr.w \tmp6, [\aj, #4*6] + ldr.w \tmp7, [\aj, #4*7] + + @ vmov.w \tmp0, \matf4 + @ vmov.w \tmp1, \matf5 + vmov.w \tmp2, \matf6 + vmov.w \tmp3, \matf7 + + //gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + gf256_madd 2, \tmp6, \tmp7, xxx, xxx, \tmp2, \tmp3, xxx, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + + @ str.w \tmp4, [\aj, #4*4] + @ str.w \tmp5, [\aj, #4*5] + str.w \tmp6, [\aj, #4*6] + str.w \tmp7, [\aj, #4*7] + + ldr.w \tmp4, [\aj, #4*8] + ldr.w \tmp5, [\aj, #4*9] + ldr.w \tmp6, [\aj, #4*10] + ldr.w \tmp7, [\aj, #4*11] + + vmov.w \tmp0, \matf8 + vmov.w \tmp1, \matf9 + vmov.w \tmp2, \matf10 + vmov.w \tmp3, \matf11 + + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*8] + str.w \tmp5, [\aj, #4*9] + str.w \tmp6, [\aj, #4*10] + str.w \tmp7, [\aj, #4*11] +.endm + +// computes (r8 is assumbed to be at sp+0): +// r8 &= gf256_is_nonzero(ai[i]); +// uint8_t pivot = ai[i]; +// pivot = gf256_inv( pivot ); +// _gf256v_mul_scalar_u32( ai , pivot , w); +.macro invert_pivot_and_multiply ai, pivotidx, pivot, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + // invert ai[i] + ldrb.w \pivot, [\ai, \pivotidx] + ldrb.w \tmp0, [sp, #0] + cmp.n \pivot, #0 + it eq + moveq.w \tmp0, #0 + strb.w \tmp0, [sp, #0] + + + gf256_inv \pivot, \tmp0, \tmp1, \tmp2, \tmp3, \tmp4, \tmp5, \tmp6, \tmp7 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp0, [\ai, #4*0] + ldr.w \tmp1, [\ai, #4*1] + ldr.w \tmp2, [\ai, #4*2] + ldr.w \tmp3, [\ai, #4*3] + + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf0, \tmp4 + vmov.w \matf1, \tmp5 + vmov.w \matf2, \tmp6 + vmov.w \matf3, \tmp7 + str.w \tmp4, [\ai, #4*0] + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + + ldr.w \tmp0, [\ai, #4*4] + ldr.w \tmp1, [\ai, #4*5] + ldr.w \tmp2, [\ai, #4*6] + ldr.w \tmp3, [\ai, #4*7] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf4, \tmp4 + vmov.w \matf5, \tmp5 + vmov.w \matf6, \tmp6 + vmov.w \matf7, \tmp7 + str.w \tmp4, [\ai, #4*4] + str.w \tmp5, [\ai, #4*5] + str.w \tmp6, [\ai, #4*6] + str.w \tmp7, [\ai, #4*7] + + ldr.w \tmp0, [\ai, #4*8] + ldr.w \tmp1, [\ai, #4*9] + ldr.w \tmp2, [\ai, #4*10] + ldr.w \tmp3, [\ai, #4*11] + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf8, \tmp4 + vmov.w \matf9, \tmp5 + vmov.w \matf10, \tmp6 + vmov.w \matf11, \tmp7 + str.w \tmp4, [\ai, #4*8] + str.w \tmp5, [\ai, #4*9] + str.w \tmp6, [\ai, #4*10] + str.w \tmp7, [\ai, #4*11] +.endm + + +.macro invert_pivot_and_multiply_second ai, pivotidx, pivot, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + // invert ai[i] + ldrb.w \pivot, [\ai, \pivotidx] + ldrb.w \tmp0, [sp, #0] + cmp.n \pivot, #0 + it eq + moveq.w \tmp0, #0 + strb.w \tmp0, [sp, #0] + + + gf256_inv \pivot, \tmp0, \tmp1, \tmp2, \tmp3, \tmp4, \tmp5, \tmp6, \tmp7 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + @ ldr.w \tmp0, [\ai, #4*0] + @ ldr.w \tmp1, [\ai, #4*1] + @ ldr.w \tmp2, [\ai, #4*2] + @ ldr.w \tmp3, [\ai, #4*3] + + + @ gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + @ vmov.w \matf0, \tmp4 + @ vmov.w \matf1, \tmp5 + @ vmov.w \matf2, \tmp6 + @ vmov.w \matf3, \tmp7 + @ str.w \tmp4, [\ai, #4*0] + @ str.w \tmp5, [\ai, #4*1] + @ str.w \tmp6, [\ai, #4*2] + @ str.w \tmp7, [\ai, #4*3] + + @ ldr.w \tmp0, [\ai, #4*4] + @ ldr.w \tmp1, [\ai, #4*5] + ldr.w \tmp2, [\ai, #4*6] + ldr.w \tmp3, [\ai, #4*7] + + //gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + gf256_mul_u32 2, \tmp6, \tmp7, xxx, xxx, \tmp2, \tmp3, xxx, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + @ vmov.w \matf4, \tmp4 + @ vmov.w \matf5, \tmp5 + vmov.w \matf6, \tmp6 + vmov.w \matf7, \tmp7 + @ str.w \tmp4, [\ai, #4*4] + @ str.w \tmp5, [\ai, #4*5] + str.w \tmp6, [\ai, #4*6] + str.w \tmp7, [\ai, #4*7] + + ldr.w \tmp0, [\ai, #4*8] + ldr.w \tmp1, [\ai, #4*9] + ldr.w \tmp2, [\ai, #4*10] + ldr.w \tmp3, [\ai, #4*11] + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf8, \tmp4 + vmov.w \matf9, \tmp5 + vmov.w \matf10, \tmp6 + vmov.w \matf11, \tmp7 + str.w \tmp4, [\ai, #4*8] + str.w \tmp5, [\ai, #4*9] + str.w \tmp6, [\ai, #4*10] + str.w \tmp7, [\ai, #4*11] +.endm + +.macro conditional_add ai, ii, aj, ajmax, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + // for the last row, we don't have rows left to add, so we skip the inner loop + cmp.w \ii, #43 + beq.w 2f + + add.w \aj, \ai, #48 + + cmp.n \ii, #36 + ite lt + movlt.w \ajmax, #8 + rsbge.w \ajmax, \ii, #44 + mov.w \tmp0, #48 + mla.w \ajmax, \ajmax, \tmp0, \ai + + 1: + ldrb.n \tmp0, [\ai, \ii] + cmp.n \tmp0, #0 + + # got 48/4 = 12 words to mult + .rept 3 // 8 words + ldr.w \tmp1, [\aj, #4*1] + ldr.w \tmp2, [\aj, #4*2] + ldr.w \tmp3, [\aj, #4*3] + ldr.w \tmp0, [\aj], #16 + + ldr.w \tmp4, [\ai, #4*0] + ldr.w \tmp5, [\ai, #4*1] + ldr.w \tmp6, [\ai, #4*2] + ldr.w \tmp7, [\ai, #4*3] + + nop.n + itttt eq + eoreq \tmp4, \tmp4, \tmp0 + eoreq \tmp5, \tmp5, \tmp1 + eoreq \tmp6, \tmp6, \tmp2 + eoreq \tmp7, \tmp7, \tmp3 + + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + str.w \tmp4, [\ai], #16 + .endr + + sub.w \ai, \ai, #48 + cmp.w \aj, \ajmax + bne.w 1b + 2: +.endm + +.global gf256mat_gauss_elim_row_echolen_m4f_44 +.type gf256mat_gauss_elim_row_echolen_m4f_44, %function +.align 2 +gf256mat_gauss_elim_row_echolen_m4f_44: + push.w {r4-r11, r14} + vpush.w {s16-s31} + sub.w sp, sp, #4 + mov.w r14, #1 + str.w r14, [sp] + + ii .req s16 + jj .req s17 + ai .req s18 + + mov.w r2, #0 + mov.w r1, r0 + mov.w r12, #0x01010101 + mov.w r14, #0x1b + vmov.w ii, r2 + vmov.w ai, r1 + + 3: + conditional_add r1, r2, r0, r3, r4, r5, r6, r7, r8, r9, r10, r11 + + vmov.w r0, ii + cmp.w r0, #24 + bge second_half + invert_pivot_and_multiply r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r2, r0, r12, r14, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s24, s25, s26, s27, s28, s29, s30, s31 + vmov.w r0, ii + + add.w r3, r0, #1 + vmov.w jj, r3 + + 1: + add.w r1, r1, #48 + vmov.w r0, ii + ldrb.w r2, [r1, r0] + + madd_row r2, r1, r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14, s24, s25, s26, s27, s28, s29, s30, s31, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 + + vmov r3, jj + add.w r3, #1 + vmov jj, r3 + cmp.w r3, #44 + bne 1b + + b.w 2f + second_half: + invert_pivot_and_multiply_second r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r2, r0, r12, r14, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s24, s25, s26, s27, s28, s29, s30, s31 + vmov.w r0, ii + cmp.w r0, #43 + beq 2f + + add.w r3, r0, #1 + vmov.w jj, r3 + + 1: + add.w r1, r1, #48 + vmov.w r0, ii + ldrb.w r2, [r1, r0] + + madd_row_second r2, r1, r0, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14, s24, s25, s26, s27, s28, s29, s30, s31, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 + + vmov r3, jj + add.w r3, #1 + vmov jj, r3 + cmp.w r3, #44 + bne 1b + 2: + vmov.w r2, ii + add.w r2, #1 + vmov.w ii, r2 + vmov.w r1, ai + add.w r1, #48 + vmov.w ai, r1 + + cmp.w r2, #44 + bne.w 3b + + ldr.w r0, [sp] + add.w sp, sp, #4 + vpop.w {s16-s31} + pop {r4-r11, pc} diff --git a/crypto_sign/ov-Ip/m4f/gf256mat_inv_22.S b/crypto_sign/ov-Ip/m4f/gf256mat_inv_22.S new file mode 100644 index 00000000..a6712186 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256mat_inv_22.S @@ -0,0 +1,448 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256_madd.i" + +.macro gf256_inv g, f, delta, r, v, mdelta, tmp, tmp2, tmp3 + lsl.w \g, \g, #1 + mov.w \f, #0x11b + mov.w \delta, #1 + mov.w \r, #0x100 + mov.w \v, #0 + + // 15 instructions + .rept 15 + eor \tmp, \f, \g + eor \tmp2, \v, \r + + lsrs \tmp3, \g, #8 + itt ne + eorne \g, \g, \f + eorne \r, \r, \v + + neg \mdelta, \delta + tst \tmp3, \mdelta, lsr#31 + + ittte ne + addne \delta, \mdelta, #1 + eorne \f, \f, \tmp + eorne \v, \v, \tmp2 + addeq \delta, #1 + + lsl \g, \g, #1 + lsr \v, \v, #1 + .endr + and \g, \v, #0xff +.endm + + +.global gf256mat_inv_m4f_22_init +.type gf256mat_inv_m4f_22_init, %function +.align 2 +gf256mat_inv_m4f_22_init: + push {r4-r11, r14} + inputoutput_fpu .req s18 + extmat_fpu .req s19 + ai .req r3 + ii .req r1 + aj0 .req r9 + aj1 .req r6 + aj2 .req r7 + aj3 .req r8 + vmov.w inputoutput_fpu, r1 + vmov.w extmat_fpu, r0 + + + + // set the entire extended matrix to zero + mov.w r1, #0 + mov.w r2, #22*22*2 + bl.w memset + + mov.w r14, #1 + + // copy over the input matrix to the left half of the extended matrix + vmov.w r0, inputoutput_fpu + vmov.w ai, extmat_fpu + mov.w ii, #22 + 1: + ldr.w aj1, [r0, #4] + ldr.w aj2, [r0, #8] + ldr.w aj3, [r0, #12] + ldr.w aj0, [r0], #16 + + + str.w aj1, [ai, #4] + str.w aj2, [ai, #8] + str.w aj3, [ai, #12] + str.w aj0, [ai], #16 + + ldrh.w aj1, [r0, #4] + ldr.w aj0, [r0], #6 + + strh.w aj1, [ai, #4] + str.w aj0, [ai], #6 + + + add r12, ai, #22 + sub r12, ii + strb r14, [r12] + + add.w ai, #22 + + + subs.w ii, ii, #1 + bne.w 1b + + + .unreq ai + .unreq ii + .unreq aj0 + .unreq aj1 + .unreq aj2 + .unreq aj3 + .unreq inputoutput_fpu + .unreq extmat_fpu + pop {r4-r11, pc} + + +.global gf256mat_inv_m4f_22_extract +.type gf256mat_inv_m4f_22_extract, %function +.align 2 +gf256mat_inv_m4f_22_extract: + push {r4-r11, r14} + ai .req r3 + ii .req r1 + aj0 .req r9 + aj1 .req r6 + aj2 .req r7 + aj3 .req r8 + + inputoutput_fpu .req s11 + extmat_fpu .req s0 + vmov.w inputoutput_fpu, r0 + vmov.w extmat_fpu, r1 + + vmov.w ai, extmat_fpu + vmov.w r2, inputoutput_fpu + mov.w ii, #22 + add.w ai, #22 + 1: + ldr.w aj1, [ai, #4] + ldr.w aj2, [ai, #8] + ldr.w aj3, [ai, #12] + ldr.w aj0, [ai], #16 + + + str.w aj1, [r2, #4] + str.w aj2, [r2, #8] + str.w aj3, [r2, #12] + str.w aj0, [r2], #16 + + ldrh.w aj1, [ai, #4] + ldr.w aj0, [ai], #6+22 + + strh.w aj1, [r2, #4] + str.w aj0, [r2], #6 + + + subs.w ii, #1 + bne.w 1b + + pop {r4-r11, pc} + + .unreq ai + .unreq ii + .unreq aj0 + .unreq aj1 + .unreq aj2 + .unreq aj3 + .unreq inputoutput_fpu + .unreq extmat_fpu + +// computes _gf256v_mul_scalar_u32( ai , pivot , w); +.macro madd_row pivot, aj, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp4, [\aj, #4*0] + ldr.w \tmp5, [\aj, #4*1] + ldr.w \tmp6, [\aj, #4*2] + ldr.w \tmp7, [\aj, #4*3] + + vmov.w \tmp0, \matf0 + vmov.w \tmp1, \matf1 + vmov.w \tmp2, \matf2 + vmov.w \tmp3, \matf3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*0] + str.w \tmp5, [\aj, #4*1] + str.w \tmp6, [\aj, #4*2] + str.w \tmp7, [\aj, #4*3] + + ldr.w \tmp4, [\aj, #4*4] + ldr.w \tmp5, [\aj, #4*5] + ldr.w \tmp6, [\aj, #4*6] + ldr.w \tmp7, [\aj, #4*7] + + vmov.w \tmp0, \matf4 + vmov.w \tmp1, \matf5 + vmov.w \tmp2, \matf6 + vmov.w \tmp3, \matf7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*4] + str.w \tmp5, [\aj, #4*5] + str.w \tmp6, [\aj, #4*6] + str.w \tmp7, [\aj, #4*7] + + ldr.w \tmp4, [\aj, #4*8] + ldr.w \tmp5, [\aj, #4*9] + ldr.w \tmp6, [\aj, #4*10] + + vmov.w \tmp0, \matf8 + vmov.w \tmp1, \matf9 + vmov.w \tmp2, \matf10 + + gf256_madd 3, \tmp4, \tmp5, \tmp6, xxx, \tmp0, \tmp1, \tmp2, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*8] + str.w \tmp5, [\aj, #4*9] + str.w \tmp6, [\aj, #4*10] +.endm + +// computes (r8 is assumbed to be at sp+0): +// r8 &= gf256_is_nonzero(ai[i]); +// uint8_t pivot = ai[i]; +// pivot = gf256_inv( pivot ); +// _gf256v_mul_scalar_u32( ai , pivot , w); +.macro invert_pivot_and_multiply ai, pivotidx, pivot, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + // invert ai[i] + ldrb.w \pivot, [\ai, \pivotidx] + ldrb.w \tmp0, [sp, #0] + cmp.n \pivot, #0 + it eq + moveq.w \tmp0, #0 + strb.w \tmp0, [sp, #0] + + + gf256_inv \pivot, \tmp0, \tmp1, \tmp2, \tmp3, \tmp4, \tmp5, \tmp6, \tmp7 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp0, [\ai, #4*0] + ldr.w \tmp1, [\ai, #4*1] + ldr.w \tmp2, [\ai, #4*2] + ldr.w \tmp3, [\ai, #4*3] + + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf0, \tmp4 + vmov.w \matf1, \tmp5 + vmov.w \matf2, \tmp6 + vmov.w \matf3, \tmp7 + str.w \tmp4, [\ai, #4*0] + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + + ldr.w \tmp0, [\ai, #4*4] + ldr.w \tmp1, [\ai, #4*5] + ldr.w \tmp2, [\ai, #4*6] + ldr.w \tmp3, [\ai, #4*7] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf4, \tmp4 + vmov.w \matf5, \tmp5 + vmov.w \matf6, \tmp6 + vmov.w \matf7, \tmp7 + str.w \tmp4, [\ai, #4*4] + str.w \tmp5, [\ai, #4*5] + str.w \tmp6, [\ai, #4*6] + str.w \tmp7, [\ai, #4*7] + + ldr.w \tmp0, [\ai, #4*8] + ldr.w \tmp1, [\ai, #4*9] + ldr.w \tmp2, [\ai, #4*10] + + gf256_mul_u32 3, \tmp4, \tmp5, \tmp6, xxx, \tmp0, \tmp1, \tmp2, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf8, \tmp4 + vmov.w \matf9, \tmp5 + vmov.w \matf10, \tmp6 + str.w \tmp4, [\ai, #4*8] + str.w \tmp5, [\ai, #4*9] + str.w \tmp6, [\ai, #4*10] +.endm + +.macro conditional_add ai, ii, aj, ajmax, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + // for the last row, we don't have rows left to add, so we skip the inner loop + cmp.w \ii, #21 + beq.w last + + add.w \aj, \ai, #2*22 + rsb.w \ajmax, \ii, #22 + mov.w \tmp0, #2*22 + mla.w \ajmax, \ajmax, \tmp0, \ai + + 1: + ldrb.n \tmp0, [\ai, \ii] + cmp.n \tmp0, #0 + + # got 22*2/4 = 11 words to mult + .rept 2 // 8 words + ldr.w \tmp1, [\aj, #4*1] + ldr.w \tmp2, [\aj, #4*2] + ldr.w \tmp3, [\aj, #4*3] + ldr.w \tmp0, [\aj], #16 + + ldr.w \tmp4, [\ai, #4*0] + ldr.w \tmp5, [\ai, #4*1] + ldr.w \tmp6, [\ai, #4*2] + ldr.w \tmp7, [\ai, #4*3] + + itttt eq + eoreq \tmp4, \tmp4, \tmp0 + eoreq \tmp5, \tmp5, \tmp1 + eoreq \tmp6, \tmp6, \tmp2 + eoreq \tmp7, \tmp7, \tmp3 + + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + str.w \tmp4, [\ai], #16 + .endr + // last 3 words + ldr.w \tmp2, [\aj, #4*2] + ldr.w \tmp1, [\aj, #4*1] + ldr.w \tmp0, [\aj], #12 + ldr.w \tmp4, [\ai, #4*0] + ldr.w \tmp5, [\ai, #4*1] + ldr.w \tmp6, [\ai, #4*2] + + ittt eq + eoreq \tmp4, \tmp4, \tmp0 + eoreq \tmp5, \tmp5, \tmp1 + eoreq \tmp6, \tmp6, \tmp2 + + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp4, [\ai], #-2*16 + + cmp.w \aj, \ajmax + bne.w 1b + last: +.endm + + +.global gf256mat_inv_m4f_22_gauss +.type gf256mat_inv_m4f_22_gauss, %function +.align 2 +gf256mat_inv_m4f_22_gauss: + push.w {r4-r11, r14} + vpush.w {s16-s31} + sub.w sp, sp, #24 + mov.w r2, #0 + str.w r2, [sp, #4] + + // return code (0 if not invertible) + mov.w r3, #1 + str.w r3, [sp, #0] + + // ai + str.w r0, [sp, #16] + // mat + str.w r0, [sp, #20] + + + mov.w r12, #0x01010101 + mov.w r14, #0x1b + + mov.w r1, r0 + 2: + str.w r0, [sp, #8] + + conditional_add r1, r2, r0, r3, r4, r5, r6, r7, r8, r9, r10, r11 + + invert_pivot_and_multiply r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r2, r0, r12, r14, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s24, s25, s26, s27, s28, s29, s30, s31 + + ldr.w r0, [sp, #8] + ldr.w r2, [sp, #4] + add.w r1, r0, #22*22*2 + mov.w r3, #22*2 + mla.w r3, r2, r3, r0 + + str.w r1, [sp, #8] + str.w r3, [sp, #12] + + 1: + // check if i == j + ldr.w r3, [sp, #12] + cmp.w r3, r0 + beq.w skip + + // load pivot + ldr r2, [sp, #4] + ldrb.n r2, [r0, r2] + + // gf256v_madd( aj , ai , aj[i] , w); + madd_row r2, r0, r1, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14, s24, s25, s26, s27, s28, s29, s30, s31, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 + + skip: + ldr.w r1, [sp, #8] + add.w r0, #22*2 + cmp.w r0, r1 + bne.w 1b + + ldr.w r1, [sp, #16] + add.w r1, #2*22 + str.w r1, [sp, #16] + + ldr.w r2, [sp, #4] + add.w r2, #1 + str.w r2, [sp, #4] + + // mat + ldr.w r0, [sp, #20] + cmp.w r2, #22 + bne.w 2b + + + ldr.w r0, [sp, #0] + add.w sp, sp, #24 + + vpop {s16-s31} + pop {r4-r11, pc} + +.global gf256mat_inv_m4f_22 +.type gf256mat_inv_m4f_22, %function +.align 2 +gf256mat_inv_m4f_22: + push.w {r4-r11, r14} + vpush.w {s16-s19} + vmov s16, r0 + vmov s17, r1 + + sub.w sp, sp, #22*22*2 + mov.w r0, sp + // initialize matrix + bl.w gf256mat_inv_m4f_22_init + + mov.w r0, sp + // actual Gauss elimination + bl.w gf256mat_inv_m4f_22_gauss + + vmov.w s17, r0 + mov.w r1, sp + vmov.w r0, s16 + // extract result + bl.w gf256mat_inv_m4f_22_extract + + add.w sp, sp, #22*22*2 + vmov.w r0, s17 + vpop.w {s16-s19} + pop {r4-r11, pc} \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256mat_inv_44.S b/crypto_sign/ov-Ip/m4f/gf256mat_inv_44.S new file mode 100644 index 00000000..f84ef73b --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256mat_inv_44.S @@ -0,0 +1,573 @@ +.syntax unified +.cpu cortex-m4 +.thumb + + +#include "gf256_madd.i" + +.macro gf256_inv g, f, delta, r, v, mdelta, tmp, tmp2, tmp3 + lsl.w \g, \g, #1 + mov.w \f, #0x11b + mov.w \delta, #1 + mov.w \r, #0x100 + mov.w \v, #0 + + // 15 instructions + .rept 15 + eor \tmp, \f, \g + eor \tmp2, \v, \r + + lsrs \tmp3, \g, #8 + itt ne + eorne \g, \g, \f + eorne \r, \r, \v + + neg \mdelta, \delta + tst \tmp3, \mdelta, lsr#31 + + ittte ne + addne \delta, \mdelta, #1 + eorne \f, \f, \tmp + eorne \v, \v, \tmp2 + addeq \delta, #1 + + lsl \g, \g, #1 + lsr \v, \v, #1 + .endr + and \g, \v, #0xff +.endm + + + +.global gf256mat_inv_m4f_44_init +.type gf256mat_inv_m4f_44_init, %function +.align 2 +gf256mat_inv_m4f_44_init: + push {r4-r11, r14} + inputoutput_fpu .req s18 + extmat_fpu .req s19 + ai .req r3 + ii .req r1 + aj0 .req r9 + aj1 .req r6 + aj2 .req r7 + aj3 .req r8 + vmov.w inputoutput_fpu, r1 + vmov.w extmat_fpu, r0 + + // set the entire extended matrix matrix to zero + mov.w r1, #0 + mov.w r2, #44*44*2 + bl.w memset + + mov.w r14, #1 + + // copy over the input matrix to the left half of the extended matrix + vmov.w r0, inputoutput_fpu + vmov.w ai, extmat_fpu + mov.w ii, #44 + 1: + ldr.w aj1, [r0, #4] + ldr.w aj2, [r0, #8] + ldr.w aj3, [r0, #12] + ldr.w aj0, [r0], #16 + + + str.w aj1, [ai, #4] + str.w aj2, [ai, #8] + str.w aj3, [ai, #12] + str.w aj0, [ai], #16 + + ldr.w aj1, [r0, #4] + ldr.w aj2, [r0, #8] + ldr.w aj3, [r0, #12] + ldr.w aj0, [r0], #16 + + str.w aj1, [ai, #4] + str.w aj2, [ai, #8] + str.w aj3, [ai, #12] + str.w aj0, [ai], #16 + + ldr.w aj1, [r0, #4] + ldr.w aj2, [r0, #8] + ldr.w aj0, [r0], #12 + + str.w aj1, [ai, #4] + str.w aj2, [ai, #8] + str.w aj0, [ai], #12 + + + add r12, ai, #44 + sub r12, ii + strb r14, [r12] + + add.w ai, #44 + + + subs.w ii, ii, #1 + bne.w 1b + + .unreq ai + .unreq ii + .unreq aj0 + .unreq aj1 + .unreq aj2 + .unreq aj3 + .unreq inputoutput_fpu + .unreq extmat_fpu + pop {r4-r11, pc} + + +.global gf256mat_inv_m4f_44_extract +.type gf256mat_inv_m4f_44_extract, %function +.align 2 +gf256mat_inv_m4f_44_extract: + push {r4-r11, r14} + ai .req r3 + ii .req r1 + + aj0 .req r4 + aj1 .req r5 + aj2 .req r6 + aj3 .req r7 + aj4 .req r8 + aj5 .req r9 + aj6 .req r10 + aj7 .req r11 + + inputoutput_fpu .req s11 + extmat_fpu .req s0 + vmov.w inputoutput_fpu, r0 + vmov.w extmat_fpu, r1 + + vmov.w ai, extmat_fpu + vmov.w r2, inputoutput_fpu + mov.w ii, #44 + add.w ai, #44 + 1: + ldr.w aj1, [ai, #4] + ldr.w aj2, [ai, #8] + ldr.w aj0, [ai], #12 + + str.w aj1, [r2, #4] + str.w aj2, [r2, #8] + str.w aj0, [r2], #12 + + + ldr.w aj1, [ai, #4] + ldr.w aj2, [ai, #8] + ldr.w aj3, [ai, #12] + ldr.w aj4, [ai, #16] + ldr.w aj5, [ai, #20] + ldr.w aj6, [ai, #24] + ldr.w aj7, [ai, #28] + ldr.w aj0, [ai], #32+44 + + str.w aj1, [r2, #4] + str.w aj2, [r2, #8] + str.w aj3, [r2, #12] + str.w aj4, [r2, #16] + str.w aj5, [r2, #20] + str.w aj6, [r2, #24] + str.w aj7, [r2, #28] + str.w aj0, [r2], #32 + + + subs.w ii, #1 + bne.w 1b + + pop {r4-r11, pc} + + .unreq ai + .unreq ii + .unreq aj0 + .unreq aj1 + .unreq aj2 + .unreq aj3 + .unreq inputoutput_fpu + .unreq extmat_fpu + +// computes _gf256v_mul_scalar_u32( ai , pivot , w); +.macro madd_row pivot, aj, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11, matf12, matf13, matf14, matf15, matf16, matf17, matf18, matf19, matf20, matf21, matf22, matf23 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp4, [\aj, #4*0] + ldr.w \tmp5, [\aj, #4*1] + ldr.w \tmp6, [\aj, #4*2] + ldr.w \tmp7, [\aj, #4*3] + + vmov.w \tmp0, \matf0 + vmov.w \tmp1, \matf1 + vmov.w \tmp2, \matf2 + vmov.w \tmp3, \matf3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*0] + str.w \tmp5, [\aj, #4*1] + str.w \tmp6, [\aj, #4*2] + str.w \tmp7, [\aj, #4*3] + + ldr.w \tmp4, [\aj, #4*4] + ldr.w \tmp5, [\aj, #4*5] + ldr.w \tmp6, [\aj, #4*6] + ldr.w \tmp7, [\aj, #4*7] + + vmov.w \tmp0, \matf4 + vmov.w \tmp1, \matf5 + vmov.w \tmp2, \matf6 + vmov.w \tmp3, \matf7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*4] + str.w \tmp5, [\aj, #4*5] + str.w \tmp6, [\aj, #4*6] + str.w \tmp7, [\aj, #4*7] + + + ldr.w \tmp4, [\aj, #4*8] + ldr.w \tmp5, [\aj, #4*9] + ldr.w \tmp6, [\aj, #4*10] + ldr.w \tmp7, [\aj, #4*11] + + vmov.w \tmp0, \matf8 + vmov.w \tmp1, \matf9 + vmov.w \tmp2, \matf10 + vmov.w \tmp3, \matf11 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*8] + str.w \tmp5, [\aj, #4*9] + str.w \tmp6, [\aj, #4*10] + str.w \tmp7, [\aj, #4*11] + + + ldr.w \tmp4, [\aj, #4*12] + ldr.w \tmp5, [\aj, #4*13] + ldr.w \tmp6, [\aj, #4*14] + ldr.w \tmp7, [\aj, #4*15] + + vmov.w \tmp0, \matf12 + vmov.w \tmp1, \matf13 + vmov.w \tmp2, \matf14 + vmov.w \tmp3, \matf15 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*12] + str.w \tmp5, [\aj, #4*13] + str.w \tmp6, [\aj, #4*14] + str.w \tmp7, [\aj, #4*15] + + ldr.w \tmp4, [\aj, #4*16] + ldr.w \tmp5, [\aj, #4*17] + ldr.w \tmp6, [\aj, #4*18] + ldr.w \tmp7, [\aj, #4*19] + + vmov.w \tmp0, \matf16 + vmov.w \tmp1, \matf17 + vmov.w \tmp2, \matf18 + vmov.w \tmp3, \matf19 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*16] + str.w \tmp5, [\aj, #4*17] + str.w \tmp6, [\aj, #4*18] + str.w \tmp7, [\aj, #4*19] + + + ldr.w \tmp4, [\aj, #4*20] + ldr.w \tmp5, [\aj, #4*21] + + vmov.w \tmp0, \matf20 + vmov.w \tmp1, \matf21 + + gf256_madd 2, \tmp4, \tmp5, xxx, xxx, \tmp0, \tmp1, xxx, xx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + str.w \tmp4, [\aj, #4*20] + str.w \tmp5, [\aj, #4*21] +.endm + +// computes (r8 is assumbed to be at sp+0): +// r8 &= gf256_is_nonzero(ai[i]); +// uint8_t pivot = ai[i]; +// pivot = gf256_inv( pivot ); +// _gf256v_mul_scalar_u32( ai , pivot , w); +.macro invert_pivot_and_multiply ai, pivotidx, pivot, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, matf0, matf1, matf2, matf3, matf4, matf5, matf6, matf7, matf8, matf9, matf10, matf11, matf12, matf13, matf14, matf15, matf16, matf17, matf18, matf19, matf20, matf21, matf22, matf23, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + ldrb.w \pivot, [\ai, \pivotidx] + ldrb.w \tmp0, [sp, #0] + cmp.n \pivot, #0 + it eq + moveq.w \tmp0, #0 + strb.w \tmp0, [sp, #0] + + + gf256_inv \pivot, \tmp0, \tmp1, \tmp2, \tmp3, \tmp4, \tmp5, \tmp6, \tmp7 + + + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \pivot, \c01010101, \pconst, \tmp8 + + ldr.w \tmp0, [\ai, #4*0] + ldr.w \tmp1, [\ai, #4*1] + ldr.w \tmp2, [\ai, #4*2] + ldr.w \tmp3, [\ai, #4*3] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf0, \tmp4 + vmov.w \matf1, \tmp5 + vmov.w \matf2, \tmp6 + vmov.w \matf3, \tmp7 + str.w \tmp4, [\ai, #4*0] + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + + ldr.w \tmp0, [\ai, #4*4] + ldr.w \tmp1, [\ai, #4*5] + ldr.w \tmp2, [\ai, #4*6] + ldr.w \tmp3, [\ai, #4*7] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf4, \tmp4 + vmov.w \matf5, \tmp5 + vmov.w \matf6, \tmp6 + vmov.w \matf7, \tmp7 + str.w \tmp4, [\ai, #4*4] + str.w \tmp5, [\ai, #4*5] + str.w \tmp6, [\ai, #4*6] + str.w \tmp7, [\ai, #4*7] + + + ldr.w \tmp0, [\ai, #4*8] + ldr.w \tmp1, [\ai, #4*9] + ldr.w \tmp2, [\ai, #4*10] + ldr.w \tmp3, [\ai, #4*11] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf8, \tmp4 + vmov.w \matf9, \tmp5 + vmov.w \matf10, \tmp6 + vmov.w \matf11, \tmp7 + str.w \tmp4, [\ai, #4*8] + str.w \tmp5, [\ai, #4*9] + str.w \tmp6, [\ai, #4*10] + str.w \tmp7, [\ai, #4*11] + + + ldr.w \tmp0, [\ai, #4*12] + ldr.w \tmp1, [\ai, #4*13] + ldr.w \tmp2, [\ai, #4*14] + ldr.w \tmp3, [\ai, #4*15] + + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf12, \tmp4 + vmov.w \matf13, \tmp5 + vmov.w \matf14, \tmp6 + vmov.w \matf15, \tmp7 + str.w \tmp4, [\ai, #4*12] + str.w \tmp5, [\ai, #4*13] + str.w \tmp6, [\ai, #4*14] + str.w \tmp7, [\ai, #4*15] + + + ldr.w \tmp0, [\ai, #4*16] + ldr.w \tmp1, [\ai, #4*17] + ldr.w \tmp2, [\ai, #4*18] + ldr.w \tmp3, [\ai, #4*19] + + gf256_mul_u32 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf16, \tmp4 + vmov.w \matf17, \tmp5 + vmov.w \matf18, \tmp6 + vmov.w \matf19, \tmp7 + str.w \tmp4, [\ai, #4*16] + str.w \tmp5, [\ai, #4*17] + str.w \tmp6, [\ai, #4*18] + str.w \tmp7, [\ai, #4*19] + + ldr.w \tmp0, [\ai, #4*20] + ldr.w \tmp1, [\ai, #4*21] + + gf256_mul_u32 2, \tmp4, \tmp5, xxx, xxx, \tmp0, \tmp1, xxx, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \matf20, \tmp4 + vmov.w \matf21, \tmp5 + str.w \tmp4, [\ai, #4*20] + str.w \tmp5, [\ai, #4*21] +.endm + +.macro conditional_add ai, ii, aj, ajmax, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 + // for the last row, we don't have rows left to add, so we skip the inner loop + cmp.w \ii, #43 + beq.w last + + add.w \aj, \ai, #2*44 + rsb.w \ajmax, \ii, #44 + mov.w \tmp0, #2*44 + mla.w \ajmax, \ajmax, \tmp0, \ai + + 1: + ldrb.n \tmp0, [\ai, \ii] + cmp.n \tmp0, #0 + + # got 44*2/4 = 22 words to mult + .rept 5 // 20 words + ldr.w \tmp1, [\aj, #4*1] + ldr.w \tmp2, [\aj, #4*2] + ldr.w \tmp3, [\aj, #4*3] + ldr.w \tmp0, [\aj], #16 + + ldr.w \tmp4, [\ai, #4*0] + ldr.w \tmp5, [\ai, #4*1] + ldr.w \tmp6, [\ai, #4*2] + ldr.w \tmp7, [\ai, #4*3] + + itttt eq + eoreq \tmp4, \tmp4, \tmp0 + eoreq \tmp5, \tmp5, \tmp1 + eoreq \tmp6, \tmp6, \tmp2 + eoreq \tmp7, \tmp7, \tmp3 + + str.w \tmp5, [\ai, #4*1] + str.w \tmp6, [\ai, #4*2] + str.w \tmp7, [\ai, #4*3] + str.w \tmp4, [\ai], #16 + .endr + // last two words + ldr.w \tmp1, [\aj, #4*1] + ldr.w \tmp0, [\aj], #8 + ldr.w \tmp4, [\ai, #4*0] + ldr.w \tmp5, [\ai, #4*1] + + itt eq + eoreq \tmp4, \tmp4, \tmp0 + eoreq \tmp5, \tmp5, \tmp1 + + str.w \tmp5, [\ai, #4*1] + str.w \tmp4, [\ai], #-5*16 + + cmp.w \aj, \ajmax + bne.w 1b + last: +.endm + + +.global gf256mat_inv_m4f_44_gauss +.type gf256mat_inv_m4f_44_gauss, %function +.align 2 +gf256mat_inv_m4f_44_gauss: + push.w {r4-r11, r14} + vpush.w {s16-s31} + + sub.w sp, sp, #24 + + // return code (0 if not invertible) + mov.w r3, #1 + str.w r3, [sp, #0] + + // counter i + mov.w r2, #0 + str.w r2, [sp, #4] + // mat + str.w r0, [sp, #8] + // ai + str.w r0, [sp, #12] + + mov.w r12, #0x01010101 + mov.w r14, #0x1b + + mov.w r1, r0 + 2: + str.w r0, [sp, #20] + + conditional_add r1, r2, r0, r3, r4, r5, r6, r7, r8, r9, r10, r11 + + invert_pivot_and_multiply r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r2, r0, r12, r14, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31 + + ldr.w r0, [sp, #20] + ldr.w r2, [sp, #4] + add.w r1, r0, #44*44*2 + mov.w r3, #44*2 + mla.w r3, r2, r3, r0 + + str.w r1, [sp, #20] + str.w r3, [sp, #16] + + 1: + // check if i == j + ldr.w r3, [sp, #16] + cmp.w r3, r0 + beq.w skip + + // load pivot + ldr r2, [sp, #4] + ldrb.n r2, [r0, r2] + + // gf256v_madd( aj , ai , aj[i] , w); + madd_row r2, r0, r1, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14, s24, s25, s26, s27, s28, s29, s30, s31, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23 + + + skip: + ldr.w r1, [sp, #20] + add.w r0, #44*2 + cmp.w r0, r1 + bne.w 1b + + ldr.w r1, [sp, #12] + add.w r1, #2*44 + str.w r1, [sp, #12] + + ldr.w r2, [sp, #4] + add.w r2, #1 + str.w r2, [sp, #4] + + // mat + ldr.w r0, [sp, #8] + cmp.w r2, #44 + bne.w 2b + + + ldr.w r0, [sp, #0] + add.w sp, sp, #24 + + vpop {s16-s31} + pop {r4-r11, pc} + + +.global gf256mat_inv_m4f_44 +.type gf256mat_inv_m4f_44, %function +.align 2 +gf256mat_inv_m4f_44: + push.w {r4-r11, r14} + vpush.w {s16-s19} + vmov s16, r0 + vmov s17, r1 + + sub.w sp, sp, #44*44*2 + mov.w r0, sp + // initialize matrix + bl.w gf256mat_inv_m4f_44_init + + mov.w r0, sp + // actual Gauss elimination + bl.w gf256mat_inv_m4f_44_gauss + + vmov.w s17, r0 + mov.w r1, sp + vmov.w r0, s16 + // extract result + bl.w gf256mat_inv_m4f_44_extract + + add.w sp, sp, #44*44*2 + vmov.w r0, s17 + vpop.w {s16-s19} + pop {r4-r11, pc} \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256mat_prod.S b/crypto_sign/ov-Ip/m4f/gf256mat_prod.S new file mode 100644 index 00000000..b9f6c4c2 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256mat_prod.S @@ -0,0 +1,27 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256mat_prod.i" + + +//void gf256mat_prod_m4f_1936_68_normal_normal(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256mat_prod_m4f_1936_68_normal_normal +.type gf256mat_prod_m4f_1936_68_normal_normal, %function +.align 2 +gf256mat_prod_m4f_1936_68_normal_normal: + gf256_mat_prod 1936, 68 + +//void gf256mat_prod_m4f_68_44_normal_normal(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256mat_prod_m4f_68_44_normal_normal +.type gf256mat_prod_m4f_68_44_normal_normal, %function +.align 2 +gf256mat_prod_m4f_68_44_normal_normal: + gf256_mat_prod 68, 44 + +//void gf256mat_prod_m4f_44_X_normal_normal(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256mat_prod_m4f_44_X_normal_normal +.type gf256mat_prod_m4f_44_X_normal_normal, %function +.align 2 +gf256mat_prod_m4f_44_X_normal_normal: + gf256_mat_prod_x 44 diff --git a/crypto_sign/ov-Ip/m4f/gf256mat_prod.i b/crypto_sign/ov-Ip/m4f/gf256mat_prod.i new file mode 100644 index 00000000..375f1c27 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256mat_prod.i @@ -0,0 +1,575 @@ +#include "gf256_madd.i" + +.macro shift_fpu f0, f1, f2, f3, f4, f5, f6, f7, tmp + vmov.w \tmp, \f0 + lsr.w \tmp, #8 + vmov.w \f0, \tmp + + vmov.w \tmp, \f1 + lsr.w \tmp, #8 + vmov.w \f1, \tmp + + vmov.w \tmp, \f2 + lsr.w \tmp, #8 + vmov.w \f2, \tmp + + vmov.w \tmp, \f3 + lsr.w \tmp, #8 + vmov.w \f3, \tmp + + vmov.w \tmp, \f4 + lsr.w \tmp, #8 + vmov.w \f4, \tmp + + vmov.w \tmp, \f5 + lsr.w \tmp, #8 + vmov.w \f5, \tmp + + vmov.w \tmp, \f6 + lsr.w \tmp, #8 + vmov.w \f6, \tmp + + vmov.w \tmp, \f7 + lsr.w \tmp, #8 + vmov.w \f7, \tmp +.endm + +.macro gf256_mat_prod_x n_A_vec_byte + push {r4-r11, lr} + vpush {s16-s23} + + cptr .req r0 + aptr .req r1 + bptr .req r2 + n_A_width .req r3 + bb .req r3 + + + tmp1 .req r12 + tmp2 .req r14 + tmp3 .req r2 + tmp4 .req r0 + + accuf0 .req s0 + accuf1 .req s1 + accuf2 .req s2 + accuf3 .req s3 + accuf4 .req s4 + accuf5 .req s5 + accuf6 .req s6 + accuf7 .req s7 + + fbx0 .req s8 + fbx1 .req s9 + fbx2 .req s10 + fbx3 .req s11 + fbx4 .req s12 + fbx5 .req s13 + fbx6 .req s14 + fbx7 .req s15 + + zerof .req s16 + b_ptr_orig_f .req s17 + b_ptr_f .req s18 + c_ptr_f .req s19 + ctrf0 .req s20 + ctrf1 .req s21 + offsetf .req s22 + + n_A_widthf .req s23 + + + vmov.w b_ptr_orig_f, bptr + vmov.w b_ptr_f, bptr + vmov.w c_ptr_f, cptr + vmov.w n_A_widthf, n_A_width + + add.w r4, cptr, #\n_A_vec_byte - (\n_A_vec_byte%32) + vmov.w ctrf0, r4 + + mov.w r4, #0 + vmov.w zerof, r4 + + mov.w r4, #\n_A_vec_byte + mul.w r4, r4, n_A_width + sub.w r4, r4, #32 + vmov.w offsetf, r4 + + mov.w r12, #0x01010101 + mov.w r14, #0x1b + 1: + + vmov.w accuf0, zerof + vmov.w accuf1, zerof + vmov.w accuf2, zerof + vmov.w accuf3, zerof + vmov.w accuf4, zerof + vmov.w accuf5, zerof + vmov.w accuf6, zerof + vmov.w accuf7, zerof + + vmov.w r4, n_A_widthf + 2: + ldr.w bb, [bptr], #4 + vmov.w b_ptr_f, bptr + gf256_madd_precompb fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, bb, r12, r14, tmp3 + + // check if more than 4 elements + cmp.w r4, #4 + bge.w 3f + + 4: + vmov.w ctrf1, r4 + + ldr.w r4, [aptr, #0*4] + ldr.w r5, [aptr, #1*4] + ldr.w r6, [aptr, #2*4] + ldr.w r7, [aptr, #3*4] + + vmov.w r8, accuf0 + vmov.w r9, accuf1 + vmov.w r10, accuf2 + vmov.w r11, accuf3 + + gf256_madd_x4 4, 0, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf0, r8 + vmov.w accuf1, r9 + vmov.w accuf2, r10 + vmov.w accuf3, r11 + + ldr.w r4, [aptr, #4*4] + ldr.w r5, [aptr, #5*4] + ldr.w r6, [aptr, #6*4] + ldr.w r7, [aptr, #7*4] + + vmov.w r8, accuf4 + vmov.w r9, accuf5 + vmov.w r10, accuf6 + vmov.w r11, accuf7 + gf256_madd_x4 4, 0, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf4, r8 + vmov.w accuf5, r9 + vmov.w accuf6, r10 + vmov.w accuf7, r11 + + add.w aptr, #\n_A_vec_byte + shift_fpu fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, tmp2 + + + vmov.w r4, ctrf1 + subs.w r4, r4, #1 + bne 4b + b 5f + + 3: + vmov.w ctrf1, r4 + .set k, 0 + .rept 4 + ldr.w r4, [aptr, #0*4] + ldr.w r5, [aptr, #1*4] + ldr.w r6, [aptr, #2*4] + ldr.w r7, [aptr, #3*4] + + vmov.w r8, accuf0 + vmov.w r9, accuf1 + vmov.w r10, accuf2 + vmov.w r11, accuf3 + + gf256_madd_x4 4, k, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf0, r8 + vmov.w accuf1, r9 + vmov.w accuf2, r10 + vmov.w accuf3, r11 + + ldr.w r4, [aptr, #4*4] + ldr.w r5, [aptr, #5*4] + ldr.w r6, [aptr, #6*4] + ldr.w r7, [aptr, #7*4] + + vmov.w r8, accuf4 + vmov.w r9, accuf5 + vmov.w r10, accuf6 + vmov.w r11, accuf7 + + gf256_madd_x4 4, k, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf4, r8 + vmov.w accuf5, r9 + vmov.w accuf6, r10 + vmov.w accuf7, r11 + + add.w aptr, #\n_A_vec_byte + .set k, k+1 + .endr + + vmov.w bptr, b_ptr_f + vmov.w r4, ctrf1 + subs.w r4, r4, #4 + bne 2b + + 5: + vmov.w bptr, b_ptr_orig_f + + // (\n_A_vec_byte*\n_A_width-32) + vmov.w r4, offsetf + sub.w aptr, r4 + vmov.w cptr, c_ptr_f + vstr.w accuf0, [cptr, #0*4] + vstr.w accuf1, [cptr, #1*4] + vstr.w accuf2, [cptr, #2*4] + vstr.w accuf3, [cptr, #3*4] + vstr.w accuf4, [cptr, #4*4] + vstr.w accuf5, [cptr, #5*4] + vstr.w accuf6, [cptr, #6*4] + vstr.w accuf7, [cptr, #7*4] + add.w cptr, #8*4 + vmov.w c_ptr_f, cptr + + vmov.w r4, ctrf0 + cmp.w r0, r4 + bne.w 1b + + .if \n_A_vec_byte % 32 != 0 + .if \n_A_vec_byte % 4 == 0 + .set num_words, (\n_A_vec_byte % 32)/4 + .if num_words > 4 + ERROR (not implemented yet) + .endif + + + + mov.w r8, #0 + .if num_words >= 2 + mov.w r9, #0 + .endif + .if num_words >= 3 + mov.w r10, #0 + .endif + .if num_words >= 4 + mov.w r11, #0 + .endif + + mov.w r12, #0x1b + mov.w r7, #0x01010101 + + vmov.w r4, n_A_widthf + + + + .if num_words >= 4 + vmov.w b_ptr_f, bptr + .endif + 2: + + ldr.w bb, [bptr], #4 + gf256_madd_precompb fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, bb, r7, r12, tmp2 + // check if more than 4 elements + cmp.w r4, #4 + bge.w 3f + + 4: + vmov.w ctrf1, r4 + + ldr.w r4, [aptr] + .if num_words >= 2 + ldr.w r5, [aptr, #4] + .endif + .if num_words >= 3 + ldr.w r6, [aptr, #8] + .endif + .if num_words >= 4 + ldr.w r2, [aptr, #12] + .endif + add.w aptr, #\n_A_vec_byte + gf256_madd_x4 num_words, 0, r8, r9, r10, r11, r4, r5, r6, r2, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r7, tmp2, tmp4 + + shift_fpu fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, tmp2 + + vmov.w r4, ctrf1 + subs.w r4, r4, #1 + bne 4b + b 5f + + + 3: + .if num_words >= 4 + vmov.w b_ptr_f, bptr + .endif + + vmov.w ctrf1, r4 + .set k, 0 + .rept 4 + ldr.w r4, [aptr] + .if num_words >= 2 + ldr.w r5, [aptr, #4] + .endif + .if num_words >= 3 + ldr.w r6, [aptr, #8] + .endif + .if num_words >= 4 + ldr.w r2, [aptr, #12] + .endif + add.w aptr, #\n_A_vec_byte + gf256_madd_x4 num_words, k, r8, r9, r10, r11, r4, r5, r6, r2, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r7, tmp2, tmp4 + .set k,k+1 + .endr + + + .if num_words >= 4 + vmov.w bptr, b_ptr_f + .endif + vmov.w r4, ctrf1 + subs.w r4, #4 + bne 2b + 5: + + vmov.w cptr, c_ptr_f + str.w r8, [cptr], #4 + .if num_words >= 2 + str.w r9, [cptr], #4 + .endif + .if num_words >= 3 + str.w r10, [cptr], #4 + .endif + .if num_words >= 4 + str.w r11, [cptr], #4 + .endif + .else + ERROR + .endif + .endif + + vpop {s16-s23} + pop {r4-r11, pc} +.endm + + +.macro gf256_mat_prod n_A_vec_byte, n_A_width + .if \n_A_width % 4 != 0 + ERROR (not implemented yet) + .endif + + push {r4-r11, lr} + vpush {s16-s22} + + cptr .req r0 + aptr .req r1 + bptr .req r2 + + bb .req r3 + + + tmp1 .req r12 + tmp2 .req r14 + tmp3 .req r2 + tmp4 .req r0 + + accuf0 .req s0 + accuf1 .req s1 + accuf2 .req s2 + accuf3 .req s3 + accuf4 .req s4 + accuf5 .req s5 + accuf6 .req s6 + accuf7 .req s7 + + fbx0 .req s8 + fbx1 .req s9 + fbx2 .req s10 + fbx3 .req s11 + fbx4 .req s12 + fbx5 .req s13 + fbx6 .req s14 + fbx7 .req s15 + + zerof .req s16 + b_ptr_orig_f .req s17 + b_ptr_f .req s18 + c_ptr_f .req s19 + ctrf0 .req s20 + ctrf1 .req s21 + offsetf .req s22 + + + vmov.w b_ptr_orig_f, bptr + vmov.w b_ptr_f, bptr + vmov.w c_ptr_f, cptr + + add.w r4, cptr, #\n_A_vec_byte - (\n_A_vec_byte%32) + vmov.w ctrf0, r4 + + mov.w r4, #0 + vmov.w zerof, r4 + + movw.w r4, #:lower16:(\n_A_vec_byte*\n_A_width-32) + movt.w r4, #:upper16:(\n_A_vec_byte*\n_A_width-32) + vmov.w offsetf, r4 + mov.w r12, #0x01010101 + mov.w r14, #0x1b + 1: + + vmov.w accuf0, zerof + vmov.w accuf1, zerof + vmov.w accuf2, zerof + vmov.w accuf3, zerof + vmov.w accuf4, zerof + vmov.w accuf5, zerof + vmov.w accuf6, zerof + vmov.w accuf7, zerof + + add.w r4, bptr, #\n_A_width + vmov.w ctrf1, r4 + + 2: + ldr.w bb, [bptr], #4 + vmov.w b_ptr_f, bptr + gf256_madd_precompb fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, bb, r12, r14, tmp3 + + .set k, 0 + .rept 4 + ldr.w r4, [aptr, #0*4] + ldr.w r5, [aptr, #1*4] + ldr.w r6, [aptr, #2*4] + ldr.w r7, [aptr, #3*4] + + vmov.w r8, accuf0 + vmov.w r9, accuf1 + vmov.w r10, accuf2 + vmov.w r11, accuf3 + + gf256_madd_x4 4, k, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf0, r8 + vmov.w accuf1, r9 + vmov.w accuf2, r10 + vmov.w accuf3, r11 + + ldr.w r4, [aptr, #4*4] + ldr.w r5, [aptr, #5*4] + ldr.w r6, [aptr, #6*4] + ldr.w r7, [aptr, #7*4] + + vmov.w r8, accuf4 + vmov.w r9, accuf5 + vmov.w r10, accuf6 + vmov.w r11, accuf7 + + gf256_madd_x4 4, k, r8, r9, r10, r11, r4, r5, r6, r7, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r12, tmp3, tmp4 + + vmov.w accuf4, r8 + vmov.w accuf5, r9 + vmov.w accuf6, r10 + vmov.w accuf7, r11 + + add.w aptr, #\n_A_vec_byte + .set k, k+1 + .endr + + vmov.w bptr, b_ptr_f + vmov.w r4, ctrf1 + cmp.w bptr, r4 + bne 2b + + vmov.w bptr, b_ptr_orig_f + + // (\n_A_vec_byte*\n_A_width-32) + vmov.w r4, offsetf + sub.w aptr, r4 + vmov.w cptr, c_ptr_f + vstr.w accuf0, [cptr, #0*4] + vstr.w accuf1, [cptr, #1*4] + vstr.w accuf2, [cptr, #2*4] + vstr.w accuf3, [cptr, #3*4] + vstr.w accuf4, [cptr, #4*4] + vstr.w accuf5, [cptr, #5*4] + vstr.w accuf6, [cptr, #6*4] + vstr.w accuf7, [cptr, #7*4] + add.w cptr, #8*4 + vmov.w c_ptr_f, cptr + + vmov.w r4, ctrf0 + cmp.w r0, r4 + bne.w 1b + + .if \n_A_vec_byte % 32 != 0 + .if \n_A_vec_byte % 4 == 0 + .set num_words, (\n_A_vec_byte % 32)/4 + .if num_words > 4 + ERROR (not implemented yet) + .endif + + + + mov.w r8, #0 + .if num_words >= 2 + mov.w r9, #0 + .endif + .if num_words >= 3 + mov.w r10, #0 + .endif + .if num_words >= 4 + mov.w r11, #0 + .endif + + mov.w r12, #0x1b + mov.w r7, #0x01010101 + add.w r4, bptr, #\n_A_width + vmov.w ctrf1, r4 + .if num_words >= 4 + vmov.w b_ptr_f, bptr + .endif + 2: + + ldr.w bb, [bptr], #4 + gf256_madd_precompb fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, bb, r7, r12, tmp2 + .if num_words >= 4 + vmov.w b_ptr_f, bptr + .endif + + .set k, 0 + .rept 4 + + ldr.w r4, [aptr] + .if num_words >= 2 + ldr.w r5, [aptr, #4] + .endif + .if num_words >= 3 + ldr.w r6, [aptr, #8] + .endif + .if num_words >= 4 + ldr.w r2, [aptr, #12] + .endif + add.w aptr, #\n_A_vec_byte + gf256_madd_x4 num_words, k, r8, r9, r10, r11, r4, r5, r6, r2, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7, r7, tmp2, tmp4 + .set k,k+1 + .endr + + vmov.w r4, ctrf1 + .if num_words >= 4 + vmov.w bptr, b_ptr_f + .endif + cmp.w bptr, r4 + bne 2b + + vmov.w cptr, c_ptr_f + str.w r8, [cptr], #4 + .if num_words >= 2 + str.w r9, [cptr], #4 + .endif + .if num_words >= 3 + str.w r10, [cptr], #4 + .endif + .if num_words >= 4 + str.w r11, [cptr], #4 + .endif + .else + ERROR + .endif + .endif + + vpop {s16-s22} + pop {r4-r11, pc} +.endm \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256trimat_2trimat_madd_68_68_44_44.S b/crypto_sign/ov-Ip/m4f/gf256trimat_2trimat_madd_68_68_44_44.S new file mode 100644 index 00000000..fbcc6fd6 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256trimat_2trimat_madd_68_68_44_44.S @@ -0,0 +1,251 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256_madd.i" + +.macro madd_44 accf0, accf1, accf2, accf3, accf4, accf5, accf6, accf7, accf8, accf9, accf10, matptr, bb, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \bb, \c01010101, \pconst, \tmp8 + + ldr.w \tmp1, [\matptr, #4*1] + ldr.w \tmp2, [\matptr, #4*2] + ldr.w \tmp3, [\matptr, #4*3] + ldr.w \tmp0, [\matptr], #16 + + vmov.w \tmp4, \accf0 + vmov.w \tmp5, \accf1 + vmov.w \tmp6, \accf2 + vmov.w \tmp7, \accf3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \accf0, \tmp4 + vmov.w \accf1, \tmp5 + vmov.w \accf2, \tmp6 + vmov.w \accf3, \tmp7 + + + ldr.w \tmp1, [\matptr, #4*1] + ldr.w \tmp2, [\matptr, #4*2] + ldr.w \tmp3, [\matptr, #4*3] + ldr.w \tmp0, [\matptr], #16 + + + vmov.w \tmp4, \accf4 + vmov.w \tmp5, \accf5 + vmov.w \tmp6, \accf6 + vmov.w \tmp7, \accf7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \accf4, \tmp4 + vmov.w \accf5, \tmp5 + vmov.w \accf6, \tmp6 + vmov.w \accf7, \tmp7 + + + ldr.w \tmp1, [\matptr, #4*1] + ldr.w \tmp2, [\matptr, #4*2] + ldr.w \tmp0, [\matptr], #12 + + vmov.w \tmp4, \accf8 + vmov.w \tmp5, \accf9 + vmov.w \tmp6, \accf10 + + gf256_madd 3, \tmp4, \tmp5, \tmp6, xxx, \tmp0, \tmp1, \tmp2, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \accf8, \tmp4 + vmov.w \accf9, \tmp5 + vmov.w \accf10, \tmp6 +.endm + + + +//void gf256trimat_2trimat_madd_m4f_68_68_44_44(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256trimat_2trimat_madd_m4f_68_68_44_44 +.type gf256trimat_2trimat_madd_m4f_68_68_44_44, %function +.align 2 +gf256trimat_2trimat_madd_m4f_68_68_44_44: + push.w {r4-r11, r14} + vpush.w {s16-s27} + + cc .req r0 + aa .req r1 + bb .req r2 + + + tmp1 .req r3 + tmp2 .req r0 + c01010101 .req r12 + pconst .req r14 + + mov.w c01010101, #0x01010101 + mov.w pconst, #0x1b + + accf0 .req s0 + accf1 .req s1 + accf2 .req s2 + accf3 .req s3 + accf4 .req s4 + accf5 .req s5 + accf6 .req s6 + accf7 .req s7 + accf8 .req s8 + accf9 .req s9 + accf10 .req s10 + + matf0 .req s11 + matf1 .req s12 + matf2 .req s13 + matf3 .req s14 + matf4 .req s15 + matf5 .req s16 + matf6 .req s17 + matf7 .req s18 + + ccf .req s19 + aaf .req s20 + bbbf .req s21 + iii .req s22 + maxaa .req s23 + kkk .req s23 + maxbb .req s24 + + origAA .req s25 + origBB .req s26 + incrAA .req s27 + + mov.w tmp1, #0 + vmov.w iii, tmp1 + vmov.w ccf, cc + vmov.w origAA, aa + vmov.w origBB, bb + + 4: + vmov.w aa, origAA + vmov.w bbbf, origBB + + // aa = aa + size_batch*((Aheight + Aheight - i + 1 )*i/2 + 1); + vmov.w tmp1, iii + rsb.w tmp2, tmp1, #68+68+1 + mul.w tmp2, tmp1, tmp2 + asr.w tmp2, tmp2, #1 + add.w tmp2, #1 + mov.w tmp1, #44 + mla.w aa, tmp1, tmp2, aa + + vmov.w aaf, aa + vmov.w bb, bbbf + + # maxbb = B+ 44*68 + add.w tmp1, bb, #44*68 + vmov.w maxbb, tmp1 + 3: + + vmov.w cc, ccf + vldr.w accf0, [cc, #4*0] + vldr.w accf1, [cc, #4*1] + vldr.w accf2, [cc, #4*2] + vldr.w accf3, [cc, #4*3] + vldr.w accf4, [cc, #4*4] + vldr.w accf5, [cc, #4*5] + vldr.w accf6, [cc, #4*6] + vldr.w accf7, [cc, #4*7] + vldr.w accf8, [cc, #4*8] + vldr.w accf9, [cc, #4*9] + vldr.w accf10, [cc, #4*10] + + vmov.w tmp1, iii + cmp.w tmp1, #0 + beq.w skip_first + + + // for(unsigned k=0;k= 4 + cmp.w ctrinner, #4 + blt.w 3f + + ldr.w xj, [xptr2], #4 + gf256_mul tmp, xi, xj, c1b, tmp3, tmp4 + + .set k, 0 + .rept 4 + // low + ubfx.w tmp3, tmp, #k*8, #4 + add.w tmp2, low, tmp3, lsl#6 + + .set i,0 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat, #i*8] + ldr.w tmp6, [mat, #i*8+4] + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .set i, i+1 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat, #40] + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + + // high + ubfx.w tmp3, tmp, #k*8+4, #4 + add.w tmp2, high, tmp3, lsl#6 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat], #4 + ldr.w tmp6, [mat], #4 + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat], #4 + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + .set k,k+1 + .endr + subs.w ctrinner, ctrinner, #4 + bne.w 2b + b.w 4f + @ else + 3: + ldrb.w xj, [xptr2], #1 + + gf256_mul tmp, xi, xj, c1b, tmp3, tmp4 + + // low + and.w tmp3, tmp, #0xF + add.w tmp2, low, tmp3, lsl#6 + .set i,0 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat, #i*8] + ldr.w tmp6, [mat, #i*8+4] + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .set i, i+1 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat, #40] + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + + // high + ubfx.w tmp3, tmp, #4, #4 + add.w tmp2, high, tmp3, lsl#6 + .rept 44/8 + ldr.w tmp3, [tmp2] + ldr.w tmp4, [tmp2, #4] + ldr.w tmp5, [mat], #4 + ldr.w tmp6, [mat], #4 + eor.w tmp3, tmp3, tmp5 + eor.w tmp4, tmp4, tmp6 + str.w tmp3, [tmp2], #4 + str.w tmp4, [tmp2], #4 + .endr + ldr.w tmp3, [tmp2] + ldr.w tmp5, [mat], #4 + eor.w tmp3, tmp3, tmp5 + str.w tmp3, [tmp2] + subs.w ctrinner, ctrinner, #1 + bne.w 2b + 4: + vmov.w ctrouter, s0 + subs.w ctrouter, ctrouter, #1 + bne.w 1b + b.w 5f + + 6: + .if \triangular == 1 + mov.w tmp, #44 + mla.w mat, tmp, ctrouter, mat + .else + add.w mat, mat, #44*44 + .endif + subs.w ctrouter, ctrouter, #1 + bne.w 1b + 5: +.endm + +//void gf256trimat_eval_m4f_112_44_publicinputs(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256trimat_eval_m4f_112_44_publicinputs +.type gf256trimat_eval_m4f_112_44_publicinputs, %function +.align 2 +gf256trimat_eval_m4f_112_44_publicinputs: + push.w {r4-r11, r14} + vpush.w {s16-s31} + + low .req r0 + high .req r3 + mat .req r1 + xptr .req r2 + xptr2 .req r10 + xi .req r4 + xj .req r5 + + tmp .req r6 + tmp2 .req r7 + tmp3 .req r8 + tmp4 .req r9 + tmp5 .req r5 + tmp6 .req r14 + + + c1b .req r11 + + ctrinner .req r12 + ctrouter .req r14 + + outputf .req s16 + lowf .req s17 + highf .req s18 + xptr_orig .req s19 + + vmov.w xptr_orig, xptr + vmov.w outputf, r0 + sub.w sp, sp, #2*16*64 + mov.w low, sp + add.w high, sp, #16*64 + vmov.w lowf, low + vmov.w highf, high + + push {r0-r3} + mov.w r1, #0 + mov.w r2, #2*16*64 + bl memset + pop {r0-r3} + + + mov.w c1b, #0x1b + + + # P1 (triangular) + process_Px 68, 1, xxx + + # P2 (square) + vmov.w xptr, xptr_orig + process_Px 68, 0, 44 + + # P3 (triangular) + vmov.w xptr, xptr_orig + add.w xptr, #68 + process_Px 44, 1, xxx + + b madd_reduce_gf256 + + + + +.macro load_accumulate first, src, incr, t0, t1, t2, t3, t4, t5, t6, t7, tmp, acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10 + .if \first == 1 + vldr.w \acc0, [\src, #0*4] + vldr.w \acc1, [\src, #1*4] + vldr.w \acc2, [\src, #2*4] + vldr.w \acc3, [\src, #3*4] + vldr.w \acc4, [\src, #4*4] + vldr.w \acc5, [\src, #5*4] + vldr.w \acc6, [\src, #6*4] + vldr.w \acc7, [\src, #7*4] + vldr.w \acc8, [\src, #8*4] + vldr.w \acc9, [\src, #9*4] + vldr.w \acc10, [\src, #10*4] + add.w \src, \src, \incr + .else + + + ldr.w \t0, [\src, #8*4] + ldr.w \t1, [\src, #9*4] + ldr.w \t2, [\src, #10*4] + + vmov.w \tmp, \acc8 + eor.w \tmp, \t0 + vmov.w \acc8, \tmp + + vmov.w \tmp, \acc9 + eor.w \tmp, \t1 + vmov.w \acc9, \tmp + + vmov.w \tmp, \acc10 + eor.w \tmp, \t2 + vmov.w \acc10, \tmp + + + ldr.w \t1, [\src, #1*4] + ldr.w \t2, [\src, #2*4] + ldr.w \t3, [\src, #3*4] + ldr.w \t4, [\src, #4*4] + ldr.w \t5, [\src, #5*4] + ldr.w \t6, [\src, #6*4] + ldr.w \t7, [\src, #7*4] + .if \incr < 256 + ldr.w \t0, [\src], #\incr + .else + ldr.w \t0, [\src] + add.w \src, \incr + .endif + + vmov.w \tmp, \acc0 + eor.w \tmp, \t0 + vmov.w \acc0, \tmp + + vmov.w \tmp, \acc1 + eor.w \tmp, \t1 + vmov.w \acc1, \tmp + + vmov.w \tmp, \acc2 + eor.w \tmp, \t2 + vmov.w \acc2, \tmp + + vmov.w \tmp, \acc3 + eor.w \tmp, \t3 + vmov.w \acc3, \tmp + + vmov.w \tmp, \acc4 + eor.w \tmp, \t4 + vmov.w \acc4, \tmp + + vmov.w \tmp, \acc5 + eor.w \tmp, \t5 + vmov.w \acc5, \tmp + + vmov.w \tmp, \acc6 + eor.w \tmp, \t6 + vmov.w \acc6, \tmp + + vmov.w \tmp, \acc7 + eor.w \tmp, \t7 + vmov.w \acc7, \tmp + + .endif +.endm + + +.macro mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, bb, acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + gf256_madd_precompb \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \bb, \c01010101, \pconst, \tmp8 + + vmov.w \tmp0, \tt0 + vmov.w \tmp1, \tt1 + vmov.w \tmp2, \tt2 + vmov.w \tmp3, \tt3 + + vmov.w \tmp4, \acc0 + vmov.w \tmp5, \acc1 + vmov.w \tmp6, \acc2 + vmov.w \tmp7, \acc3 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc0, \tmp4 + vmov.w \acc1, \tmp5 + vmov.w \acc2, \tmp6 + vmov.w \acc3, \tmp7 + + vmov.w \tmp0, \tt4 + vmov.w \tmp1, \tt5 + vmov.w \tmp2, \tt6 + vmov.w \tmp3, \tt7 + + vmov.w \tmp4, \acc4 + vmov.w \tmp5, \acc5 + vmov.w \tmp6, \acc6 + vmov.w \tmp7, \acc7 + + gf256_madd 4, \tmp4, \tmp5, \tmp6, \tmp7, \tmp0, \tmp1, \tmp2, \tmp3, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc4, \tmp4 + vmov.w \acc5, \tmp5 + vmov.w \acc6, \tmp6 + vmov.w \acc7, \tmp7 + + vmov.w \tmp0, \tt8 + vmov.w \tmp1, \tt9 + vmov.w \tmp2, \tt10 + + vmov.w \tmp4, \acc8 + vmov.w \tmp5, \acc9 + vmov.w \tmp6, \acc10 + + gf256_madd 3, \tmp4, \tmp5, \tmp6, xxx, \tmp0, \tmp1, \tmp2, xxx, \fbx0, \fbx1, \fbx2, \fbx3, \fbx4, \fbx5, \fbx6, \fbx7, \c01010101, \tmp8, \tmp9 + + vmov.w \acc8, \tmp4 + vmov.w \acc9, \tmp5 + vmov.w \acc10, \tmp6 +.endm + + +.align 2 +madd_reduce_gf256: + vmov.w r0, outputf + vmov.w r1, lowf + vmov.w r2, highf + .unreq low + .unreq high + .unreq mat + .unreq xptr + .unreq xi + .unreq xj + + .unreq tmp + .unreq tmp2 + .unreq tmp3 + .unreq tmp4 + .unreq tmp5 + .unreq tmp6 + .unreq c1b + .unreq ctrinner + .unreq ctrouter + .unreq outputf + //TODO: unifty + .unreq lowf + .unreq highf + + tmpy .req r0 + lowhigh .req r1 + lowf .req s30 + highf .req s31 + + + tmp0 .req r4 + tmp1 .req r5 + tmp2 .req r6 + tmp3 .req r7 + tmp4 .req r8 + tmp5 .req r9 + tmp6 .req r10 + tmp7 .req r11 + tmp8 .req r1 + tmp9 .req r2 + c01010101 .req r3 + pconst .req r14 + tmp .req r12 + + yy0 .req s0 + yy1 .req s1 + yy2 .req s2 + yy3 .req s3 + yy4 .req s4 + yy5 .req s5 + yy6 .req s6 + yy7 .req s7 + yy8 .req s8 + yy9 .req s9 + yy10 .req s10 + + tt0 .req s11 + tt1 .req s12 + tt2 .req s13 + tt3 .req s14 + tt4 .req s15 + tt5 .req s16 + tt6 .req s17 + tt7 .req s18 + tt8 .req s19 + tt9 .req s20 + tt10 .req s21 + + fbx0 .req s22 + fbx1 .req s23 + fbx2 .req s24 + fbx3 .req s25 + fbx4 .req s26 + fbx5 .req s27 + fbx6 .req s28 + fbx7 .req s29 + + + vmov.w lowf, r1 + vmov.w highf, r2 + + mov.w c01010101, #0x01010101 + mov.w pconst, #0x1b + + // x^0 + add.w lowhigh, #64 + .set first, 1 + .rept 8 + load_accumulate first, lowhigh, 64*2, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10 + .set first, 0 + .endr + + // TODO: this can be done much faster; but does not matter much + // x^1 + vmov.w lowhigh, lowf + add.w lowhigh, #2*64 + .set first, 1 + .rept 4 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + load_accumulate 0, lowhigh, 3*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + // acc += tmp*x^1 + mov.w tmp, #2 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + // x^2 + vmov.w lowhigh, lowf + add.w lowhigh, #4*64 + .set first, 1 + .rept 2 + .rept 3 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 5*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^2 + mov.w tmp, #4 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^3 + vmov.w lowhigh, lowf + add.w lowhigh, #8*64 + .set first, 1 + .rept 1 + .rept 7 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 9*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^3 + mov.w tmp, #8 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + // x^4 + vmov.w lowhigh, highf + add.w lowhigh, #64 + .set first, 1 + .rept 8 + load_accumulate first, lowhigh, 2*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + // acc += tmp*x^4 + mov.w tmp, #16 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^5 + vmov.w lowhigh, highf + add.w lowhigh, #2*64 + .set first, 1 + .rept 4 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + load_accumulate 0, lowhigh, 3*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + // acc += tmp*x^5 + mov.w tmp, #32 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + // x^6 + vmov.w lowhigh, highf + add.w lowhigh, #4*64 + .set first, 1 + .rept 2 + .rept 3 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 5*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^6 + mov.w tmp, #64 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + + + // x^7 + vmov.w lowhigh, highf + add.w lowhigh, #8*64 + .set first, 1 + .rept 1 + .rept 7 + load_accumulate first, lowhigh, 64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .set first, 0 + .endr + load_accumulate 0, lowhigh, 9*64, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10 + .endr + + // acc += tmp*x^7 + mov.w tmp, #128 + mult tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, c01010101, pconst, tmp, yy0, yy1, yy2, yy3, yy4, yy5, yy6, yy7, yy8, yy9, yy10, tt0, tt1, tt2, tt3, tt4, tt5, tt6, tt7, tt8, tt9, tt10, fbx0, fbx1, fbx2, fbx3, fbx4, fbx5, fbx6, fbx7 + + vstr.w yy0, [tmpy, #0*4] + vstr.w yy1, [tmpy, #1*4] + vstr.w yy2, [tmpy, #2*4] + vstr.w yy3, [tmpy, #3*4] + vstr.w yy4, [tmpy, #4*4] + vstr.w yy5, [tmpy, #5*4] + vstr.w yy6, [tmpy, #6*4] + vstr.w yy7, [tmpy, #7*4] + vstr.w yy8, [tmpy, #8*4] + vstr.w yy9, [tmpy, #9*4] + vstr.w yy10,[tmpy, #10*4] + + add.w sp, sp, #2*16*64 + vpop.w {s16-s31} + pop.w {r4-r11, pc} \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/gf256trimat_eval_68_44.S b/crypto_sign/ov-Ip/m4f/gf256trimat_eval_68_44.S new file mode 100644 index 00000000..7b184442 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/gf256trimat_eval_68_44.S @@ -0,0 +1,13 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +#include "gf256trimat_eval.i" + + +//void gf256trimat_eval_m4f_68_44(uint32_t *c, uint32_t *a, uint8_t *b); +.global gf256trimat_eval_m4f_68_44 +.type gf256trimat_eval_m4f_68_44, %function +.align 2 +gf256trimat_eval_m4f_68_44: + gf256_trimat_eval 68, 44 diff --git a/crypto_sign/ov-Ip/m4f/ov.c b/crypto_sign/ov-Ip/m4f/ov.c new file mode 120000 index 00000000..0fd21b23 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov.h b/crypto_sign/ov-Ip/m4f/ov.h new file mode 120000 index 00000000..222f249c --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_blas.h b/crypto_sign/ov-Ip/m4f/ov_blas.h new file mode 120000 index 00000000..2830ec23 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_blas.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov_blas.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_keypair.c b/crypto_sign/ov-Ip/m4f/ov_keypair.c new file mode 120000 index 00000000..855e853d --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_keypair.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov_keypair.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_keypair.h b/crypto_sign/ov-Ip/m4f/ov_keypair.h new file mode 120000 index 00000000..cd04967c --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_keypair.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov_keypair.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_keypair_computation.c b/crypto_sign/ov-Ip/m4f/ov_keypair_computation.c new file mode 120000 index 00000000..da7762a0 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_keypair_computation.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov_keypair_computation.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_keypair_computation.h b/crypto_sign/ov-Ip/m4f/ov_keypair_computation.h new file mode 120000 index 00000000..bc56786f --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_keypair_computation.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/ov_keypair_computation.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/ov_publicmap_m4f.c b/crypto_sign/ov-Ip/m4f/ov_publicmap_m4f.c new file mode 100644 index 00000000..09e13091 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/ov_publicmap_m4f.c @@ -0,0 +1,40 @@ +#include "ov_keypair.h" +#include "ov.h" +#include "ov_blas.h" +#include "utils_prng.h" +#include "params.h" + +#ifdef _USE_GF16 +#include "gf16_asm.h" +#else +#include "gf256_asm.h" +#endif + + +#if !(defined(_OV_PKC) || defined(_OV_PKC_SKC)) || !defined(_SAVE_MEMORY_) +void ov_publicmap( unsigned char * y, const unsigned char * trimat, const unsigned char * x ) +{ + #ifdef _OV256_112_44 + gf256trimat_eval_m4f_112_44_publicinputs(y, trimat, x); + #elif defined(_OV16_160_64) + gf16trimat_eval_m4f_160_32_publicinputs(y, trimat, x, gf16mul_lut); + #else + #error ov_publicmap not implemented + #endif +} +#endif + +#if (defined(_OV_PKC) || defined(_OV_PKC_SKC)) && defined(_SAVE_MEMORY_) +void ov_publicmap_pkc(unsigned char * y, const cpk_t * cpk, const unsigned char *signature){ + + prng_publicinputs_t prng0; + prng_set_publicinputs(&prng0 , cpk->pk_seed); + #ifdef _OV256_112_44 + gf256trimat_eval_m4f_112_44_incremental_publicinputs(y, &prng0, cpk->P3, signature); + #elif defined(_OV16_160_64) + gf16trimat_eval_m4f_160_32_incremental_publicinputs(y,cpk->P3, signature, gf16mul_lut, &prng0); + #else + #error ov_publicmap_pkc not implemented + #endif +} +#endif diff --git a/crypto_sign/ov-Ip/m4f/parallel_matrix_op.c b/crypto_sign/ov-Ip/m4f/parallel_matrix_op.c new file mode 120000 index 00000000..63b2a954 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/parallel_matrix_op.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/parallel_matrix_op.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/parallel_matrix_op.h b/crypto_sign/ov-Ip/m4f/parallel_matrix_op.h new file mode 120000 index 00000000..8a475f3f --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/parallel_matrix_op.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/parallel_matrix_op.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/params.h b/crypto_sign/ov-Ip/m4f/params.h new file mode 120000 index 00000000..335d5206 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/params.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/params.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/sign.c b/crypto_sign/ov-Ip/m4f/sign.c new file mode 120000 index 00000000..b1a28887 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/sign.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/sign.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils.c b/crypto_sign/ov-Ip/m4f/utils.c new file mode 120000 index 00000000..91779aab --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils.h b/crypto_sign/ov-Ip/m4f/utils.h new file mode 120000 index 00000000..b6f21f8d --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_hash.c b/crypto_sign/ov-Ip/m4f/utils_hash.c new file mode 120000 index 00000000..e2eb5191 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_hash.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_hash.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_hash.h b/crypto_sign/ov-Ip/m4f/utils_hash.h new file mode 120000 index 00000000..61655501 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_hash.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_hash.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_malloc.h b/crypto_sign/ov-Ip/m4f/utils_malloc.h new file mode 120000 index 00000000..5f61849e --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_malloc.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_malloc.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_prng.c b/crypto_sign/ov-Ip/m4f/utils_prng.c new file mode 120000 index 00000000..1576a1b5 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_prng.c @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_prng.c \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_prng.h b/crypto_sign/ov-Ip/m4f/utils_prng.h new file mode 120000 index 00000000..59f9f694 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_prng.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_prng.h \ No newline at end of file diff --git a/crypto_sign/ov-Ip/m4f/utils_randombytes.h b/crypto_sign/ov-Ip/m4f/utils_randombytes.h new file mode 120000 index 00000000..1225eb9d --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/utils_randombytes.h @@ -0,0 +1 @@ +../../../mupq/crypto_sign/ov-Ip/ref/utils_randombytes.h \ No newline at end of file diff --git a/mupq b/mupq index 9998553b..69d42650 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 9998553b42bd224fc391f156d2f1bc00bbddd543 +Subproject commit 69d42650336bdfaa10cd81cfd2203ffb5354878b From 6b7b698784076ce904a64b8cf56d3be1e4b234c0 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 24 Oct 2023 22:58:11 +0800 Subject: [PATCH 013/107] add LICENSEs to OV --- crypto_sign/ov-Ip-pkc-skc/m4fspeed/LICENSE | 121 +++++++++++++++++++++ crypto_sign/ov-Ip-pkc-skc/m4fstack/LICENSE | 121 +++++++++++++++++++++ crypto_sign/ov-Ip-pkc/m4fspeed/LICENSE | 121 +++++++++++++++++++++ crypto_sign/ov-Ip-pkc/m4fstack/LICENSE | 121 +++++++++++++++++++++ crypto_sign/ov-Ip/m4f/LICENSE | 121 +++++++++++++++++++++ 5 files changed, 605 insertions(+) create mode 100644 crypto_sign/ov-Ip-pkc-skc/m4fspeed/LICENSE create mode 100644 crypto_sign/ov-Ip-pkc-skc/m4fstack/LICENSE create mode 100644 crypto_sign/ov-Ip-pkc/m4fspeed/LICENSE create mode 100644 crypto_sign/ov-Ip-pkc/m4fstack/LICENSE create mode 100644 crypto_sign/ov-Ip/m4f/LICENSE diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fspeed/LICENSE b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fspeed/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/crypto_sign/ov-Ip-pkc-skc/m4fstack/LICENSE b/crypto_sign/ov-Ip-pkc-skc/m4fstack/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc-skc/m4fstack/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/crypto_sign/ov-Ip-pkc/m4fspeed/LICENSE b/crypto_sign/ov-Ip-pkc/m4fspeed/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fspeed/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/crypto_sign/ov-Ip-pkc/m4fstack/LICENSE b/crypto_sign/ov-Ip-pkc/m4fstack/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/crypto_sign/ov-Ip-pkc/m4fstack/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/crypto_sign/ov-Ip/m4f/LICENSE b/crypto_sign/ov-Ip/m4f/LICENSE new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. From f20d2b49e39d4216a95593aebafccdaaf7026574 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 24 Oct 2023 23:06:48 +0800 Subject: [PATCH 014/107] add skiplist entries for OV --- skiplist.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/skiplist.py b/skiplist.py index b5e657db..fa01a9dd 100644 --- a/skiplist.py +++ b/skiplist.py @@ -168,4 +168,12 @@ {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, + {'scheme': 'ov-Ip', 'implementation': 'm4f', 'estmemory': 524288}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fstack', 'estmemory': 361472}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fspeed', 'estmemory': 565248}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fstack', 'estmemory': 332800}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fspeed', 'estmemory': 332800}, + {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 525312}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, ] \ No newline at end of file From 22ea5d82c09d1d4083ec4472e74411b8b8069120 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 27 Oct 2023 17:47:59 +0800 Subject: [PATCH 015/107] add OV benchmarks --- benchmarks-nucleo-l4r5zi.csv | 52 +++++++++++++++++++++++++++++++ benchmarks-nucleo-l4r5zi.md | 60 ++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 benchmarks-nucleo-l4r5zi.csv create mode 100644 benchmarks-nucleo-l4r5zi.md diff --git a/benchmarks-nucleo-l4r5zi.csv b/benchmarks-nucleo-l4r5zi.csv new file mode 100644 index 00000000..5d2eab62 --- /dev/null +++ b/benchmarks-nucleo-l4r5zi.csv @@ -0,0 +1,52 @@ +Speed Evaluation,,,,,,,,,, +Key Encapsulation Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Encapsulation [cycles] (mean),Encapsulation [cycles] (min),Encapsulation [cycles] (max),Decapsulation [cycles] (mean),Decapsulation [cycles] (min),Decapsulation [cycles] (max) +Signature Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) +ov-Ip (100 executions),m4f,138685787,138685772,138685828,2488529,2464562,4861007,993529,970257,996849 +ov-Ip (100 executions),ref,350266803,350266761,350267118,6548206,6484449,12858979,1309303,1309301,1309336 +ov-Ip-pkc (100 executions),m4fspeed,174887930,174887906,174887957,2556235,2483862,4896138,10699967,10679534,10703471 +ov-Ip-pkc (100 executions),m4fstack,174887935,174887911,174887964,2483868,2483862,2483903,11521985,11494511,11525897 +ov-Ip-pkc (100 executions),ref,374601982,374601950,374602024,6933668,6933653,6933693,10946959,10946937,10947004 +ov-Ip-pkc-skc (100 executions),m4fspeed,174888071,174888044,174888099,88664377,88664362,88664408,11458067,11429199,11462352 +ov-Ip-pkc-skc (100 executions),m4fstack,174888061,174888040,174888089,88664370,88664359,88664402,11521533,11491491,11525897 +ov-Ip-pkc-skc (100 executions),ref,374602058,374602033,374602092,241007574,241007551,241007605,11657933,11657906,11657948 +Memory Evaluation,,,,,,,,,, +Key Encapsulation Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [bytes],Encapsulation [bytes],Decapsulation [bytes],,,,,, +Signature Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, +ov-Ip,m4f,1488,5252,2548,,,,,, +ov-Ip,ref,1536,3640,6160,,,,,, +ov-Ip-pkc,m4fspeed,142288,5252,280980,,,,,, +ov-Ip-pkc,m4fstack,133152,5252,6560,,,,,, +ov-Ip-pkc,ref,15752,12872,284704,,,,,, +ov-Ip-pkc-skc,m4fspeed,371072,243164,280980,,,,,, +ov-Ip-pkc-skc,m4fstack,371072,243164,6560,,,,,, +ov-Ip-pkc-skc,ref,253656,253616,284704,,,,,, +Hashing Evaluation,,,,,,,,,, +Key Encapsulation Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [%],Encapsulation [%],Decapsulation [%],,,,,, +Signature Schemes,,,,,,,,,, +Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, +ov-Ip,m4f,7.2,0.9,1.1,,,,,, +ov-Ip,ref,2.8,0.3,0.9,,,,,, +ov-Ip-pkc,m4fspeed,6.1,0.9,90.8,,,,,, +ov-Ip-pkc,m4fstack,6.1,0.9,90.7,,,,,, +ov-Ip-pkc,ref,2.8,0.3,88.8,,,,,, +ov-Ip-pkc-skc,m4fspeed,6.1,12.1,91.2,,,,,, +ov-Ip-pkc-skc,m4fstack,6.1,12.1,90.7,,,,,, +ov-Ip-pkc-skc,ref,2.8,4.4,89.6,,,,,, +Size Evaluation,,,,,,,,,, +Key Encapsulation Schemes,,,,,,,,,, +Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, +Signature Schemes,,,,,,,,,, +Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, +ov-Ip,m4f,116847,0,0,116847,,,,, +ov-Ip,ref,28599,0,0,28599,,,,, +ov-Ip-pkc,m4fspeed,117039,0,0,117039,,,,, +ov-Ip-pkc,m4fstack,116967,0,0,116967,,,,, +ov-Ip-pkc,ref,28807,0,0,28807,,,,, +ov-Ip-pkc-skc,m4fspeed,117083,0,0,117083,,,,, +ov-Ip-pkc-skc,m4fstack,117011,0,0,117011,,,,, +ov-Ip-pkc-skc,ref,28851,0,0,28851,,,,, diff --git a/benchmarks-nucleo-l4r5zi.md b/benchmarks-nucleo-l4r5zi.md new file mode 100644 index 00000000..fc64a71f --- /dev/null +++ b/benchmarks-nucleo-l4r5zi.md @@ -0,0 +1,60 @@ +# Speed Evaluation +## Key Encapsulation Schemes +| scheme | implementation | key generation [cycles] | encapsulation [cycles] | decapsulation [cycles] | +| ------ | -------------- | ----------------------- | ---------------------- | ---------------------- | +## Signature Schemes +| scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | +| ------ | -------------- | ----------------------- | ------------- | --------------- | +| ov-Ip (100 executions) | m4f | AVG: 138,685,787
MIN: 138,685,772
MAX: 138,685,828 | AVG: 2,488,529
MIN: 2,464,562
MAX: 4,861,007 | AVG: 993,529
MIN: 970,257
MAX: 996,849 | +| ov-Ip (100 executions) | ref | AVG: 350,266,803
MIN: 350,266,761
MAX: 350,267,118 | AVG: 6,548,206
MIN: 6,484,449
MAX: 12,858,979 | AVG: 1,309,303
MIN: 1,309,301
MAX: 1,309,336 | +| ov-Ip-pkc (100 executions) | m4fspeed | AVG: 174,887,930
MIN: 174,887,906
MAX: 174,887,957 | AVG: 2,556,235
MIN: 2,483,862
MAX: 4,896,138 | AVG: 10,699,967
MIN: 10,679,534
MAX: 10,703,471 | +| ov-Ip-pkc (100 executions) | m4fstack | AVG: 174,887,935
MIN: 174,887,911
MAX: 174,887,964 | AVG: 2,483,868
MIN: 2,483,862
MAX: 2,483,903 | AVG: 11,521,985
MIN: 11,494,511
MAX: 11,525,897 | +| ov-Ip-pkc (100 executions) | ref | AVG: 374,601,982
MIN: 374,601,950
MAX: 374,602,024 | AVG: 6,933,668
MIN: 6,933,653
MAX: 6,933,693 | AVG: 10,946,959
MIN: 10,946,937
MAX: 10,947,004 | +| ov-Ip-pkc-skc (100 executions) | m4fspeed | AVG: 174,888,071
MIN: 174,888,044
MAX: 174,888,099 | AVG: 88,664,377
MIN: 88,664,362
MAX: 88,664,408 | AVG: 11,458,067
MIN: 11,429,199
MAX: 11,462,352 | +| ov-Ip-pkc-skc (100 executions) | m4fstack | AVG: 174,888,061
MIN: 174,888,040
MAX: 174,888,089 | AVG: 88,664,370
MIN: 88,664,359
MAX: 88,664,402 | AVG: 11,521,533
MIN: 11,491,491
MAX: 11,525,897 | +| ov-Ip-pkc-skc (100 executions) | ref | AVG: 374,602,058
MIN: 374,602,033
MAX: 374,602,092 | AVG: 241,007,574
MIN: 241,007,551
MAX: 241,007,605 | AVG: 11,657,933
MIN: 11,657,906
MAX: 11,657,948 | +# Memory Evaluation +## Key Encapsulation Schemes +| Scheme | Implementation | Key Generation [bytes] | Encapsulation [bytes] | Decapsulation [bytes] | +| ------ | -------------- | ---------------------- | --------------------- | --------------------- | +## Signature Schemes +| Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | +| ------ | -------------- | ---------------------- | ------------ | -------------- | +| ov-Ip | m4f | 1,488 | 5,252 | 2,548 | +| ov-Ip | ref | 1,536 | 3,640 | 6,160 | +| ov-Ip-pkc | m4fspeed | 142,288 | 5,252 | 280,980 | +| ov-Ip-pkc | m4fstack | 133,152 | 5,252 | 6,560 | +| ov-Ip-pkc | ref | 15,752 | 12,872 | 284,704 | +| ov-Ip-pkc-skc | m4fspeed | 371,072 | 243,164 | 280,980 | +| ov-Ip-pkc-skc | m4fstack | 371,072 | 243,164 | 6,560 | +| ov-Ip-pkc-skc | ref | 253,656 | 253,616 | 284,704 | +# Hashing Evaluation +## Key Encapsulation Schemes +| Scheme | Implementation | Key Generation [%] | Encapsulation [%] | Decapsulation [%] | +| ------ | -------------- | ------------------ | ----------------- | ----------------- | +## Signature Schemes +| Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | +| ------ | -------------- | ------------------ | -------- | ---------- | +| ov-Ip | m4f | 7.2% | 0.9% | 1.1% | +| ov-Ip | ref | 2.8% | 0.3% | 0.9% | +| ov-Ip-pkc | m4fspeed | 6.1% | 0.9% | 90.8% | +| ov-Ip-pkc | m4fstack | 6.1% | 0.9% | 90.7% | +| ov-Ip-pkc | ref | 2.8% | 0.3% | 88.8% | +| ov-Ip-pkc-skc | m4fspeed | 6.1% | 12.1% | 91.2% | +| ov-Ip-pkc-skc | m4fstack | 6.1% | 12.1% | 90.7% | +| ov-Ip-pkc-skc | ref | 2.8% | 4.4% | 89.6% | +# Size Evaluation +## Key Encapsulation Schemes +| Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | +| ------ | -------------- | ------------- | ------------- | ------------ | ------------- | +## Signature Schemes +| Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | +| ------ | -------------- | ------------- | ------------- | ------------ | ------------- | +| ov-Ip | m4f | 116,847 | 0 | 0 | 116,847 | +| ov-Ip | ref | 28,599 | 0 | 0 | 28,599 | +| ov-Ip-pkc | m4fspeed | 117,039 | 0 | 0 | 117,039 | +| ov-Ip-pkc | m4fstack | 116,967 | 0 | 0 | 116,967 | +| ov-Ip-pkc | ref | 28,807 | 0 | 0 | 28,807 | +| ov-Ip-pkc-skc | m4fspeed | 117,083 | 0 | 0 | 117,083 | +| ov-Ip-pkc-skc | m4fstack | 117,011 | 0 | 0 | 117,011 | +| ov-Ip-pkc-skc | ref | 28,851 | 0 | 0 | 28,851 | From aed4973446abaf5bee0c00c748fe0d93e5968051 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 30 Oct 2023 11:11:38 +0800 Subject: [PATCH 016/107] switch to low-RAM test for ov-Ip --- crypto_sign/ov-Ip/m4f/config.mk | 1 + 1 file changed, 1 insertion(+) create mode 100644 crypto_sign/ov-Ip/m4f/config.mk diff --git a/crypto_sign/ov-Ip/m4f/config.mk b/crypto_sign/ov-Ip/m4f/config.mk new file mode 100644 index 00000000..9fa9a799 --- /dev/null +++ b/crypto_sign/ov-Ip/m4f/config.mk @@ -0,0 +1 @@ +elf/crypto_sign_ov-Ip_m4f_%.elf: CPPFLAGS += -DBIG_PUBLIC_KEY_TESTS From 19418ddab625f9b6638778bc410c5d3b73e20424 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 2 Nov 2023 16:30:57 +0800 Subject: [PATCH 017/107] remove benchmarks --- benchmarks-nucleo-l4r5zi.csv | 52 ------------------------------- benchmarks-nucleo-l4r5zi.md | 60 ------------------------------------ 2 files changed, 112 deletions(-) delete mode 100644 benchmarks-nucleo-l4r5zi.csv delete mode 100644 benchmarks-nucleo-l4r5zi.md diff --git a/benchmarks-nucleo-l4r5zi.csv b/benchmarks-nucleo-l4r5zi.csv deleted file mode 100644 index 5d2eab62..00000000 --- a/benchmarks-nucleo-l4r5zi.csv +++ /dev/null @@ -1,52 +0,0 @@ -Speed Evaluation,,,,,,,,,, -Key Encapsulation Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Encapsulation [cycles] (mean),Encapsulation [cycles] (min),Encapsulation [cycles] (max),Decapsulation [cycles] (mean),Decapsulation [cycles] (min),Decapsulation [cycles] (max) -Signature Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) -ov-Ip (100 executions),m4f,138685787,138685772,138685828,2488529,2464562,4861007,993529,970257,996849 -ov-Ip (100 executions),ref,350266803,350266761,350267118,6548206,6484449,12858979,1309303,1309301,1309336 -ov-Ip-pkc (100 executions),m4fspeed,174887930,174887906,174887957,2556235,2483862,4896138,10699967,10679534,10703471 -ov-Ip-pkc (100 executions),m4fstack,174887935,174887911,174887964,2483868,2483862,2483903,11521985,11494511,11525897 -ov-Ip-pkc (100 executions),ref,374601982,374601950,374602024,6933668,6933653,6933693,10946959,10946937,10947004 -ov-Ip-pkc-skc (100 executions),m4fspeed,174888071,174888044,174888099,88664377,88664362,88664408,11458067,11429199,11462352 -ov-Ip-pkc-skc (100 executions),m4fstack,174888061,174888040,174888089,88664370,88664359,88664402,11521533,11491491,11525897 -ov-Ip-pkc-skc (100 executions),ref,374602058,374602033,374602092,241007574,241007551,241007605,11657933,11657906,11657948 -Memory Evaluation,,,,,,,,,, -Key Encapsulation Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [bytes],Encapsulation [bytes],Decapsulation [bytes],,,,,, -Signature Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, -ov-Ip,m4f,1488,5252,2548,,,,,, -ov-Ip,ref,1536,3640,6160,,,,,, -ov-Ip-pkc,m4fspeed,142288,5252,280980,,,,,, -ov-Ip-pkc,m4fstack,133152,5252,6560,,,,,, -ov-Ip-pkc,ref,15752,12872,284704,,,,,, -ov-Ip-pkc-skc,m4fspeed,371072,243164,280980,,,,,, -ov-Ip-pkc-skc,m4fstack,371072,243164,6560,,,,,, -ov-Ip-pkc-skc,ref,253656,253616,284704,,,,,, -Hashing Evaluation,,,,,,,,,, -Key Encapsulation Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [%],Encapsulation [%],Decapsulation [%],,,,,, -Signature Schemes,,,,,,,,,, -Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, -ov-Ip,m4f,7.2,0.9,1.1,,,,,, -ov-Ip,ref,2.8,0.3,0.9,,,,,, -ov-Ip-pkc,m4fspeed,6.1,0.9,90.8,,,,,, -ov-Ip-pkc,m4fstack,6.1,0.9,90.7,,,,,, -ov-Ip-pkc,ref,2.8,0.3,88.8,,,,,, -ov-Ip-pkc-skc,m4fspeed,6.1,12.1,91.2,,,,,, -ov-Ip-pkc-skc,m4fstack,6.1,12.1,90.7,,,,,, -ov-Ip-pkc-skc,ref,2.8,4.4,89.6,,,,,, -Size Evaluation,,,,,,,,,, -Key Encapsulation Schemes,,,,,,,,,, -Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, -Signature Schemes,,,,,,,,,, -Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, -ov-Ip,m4f,116847,0,0,116847,,,,, -ov-Ip,ref,28599,0,0,28599,,,,, -ov-Ip-pkc,m4fspeed,117039,0,0,117039,,,,, -ov-Ip-pkc,m4fstack,116967,0,0,116967,,,,, -ov-Ip-pkc,ref,28807,0,0,28807,,,,, -ov-Ip-pkc-skc,m4fspeed,117083,0,0,117083,,,,, -ov-Ip-pkc-skc,m4fstack,117011,0,0,117011,,,,, -ov-Ip-pkc-skc,ref,28851,0,0,28851,,,,, diff --git a/benchmarks-nucleo-l4r5zi.md b/benchmarks-nucleo-l4r5zi.md deleted file mode 100644 index fc64a71f..00000000 --- a/benchmarks-nucleo-l4r5zi.md +++ /dev/null @@ -1,60 +0,0 @@ -# Speed Evaluation -## Key Encapsulation Schemes -| scheme | implementation | key generation [cycles] | encapsulation [cycles] | decapsulation [cycles] | -| ------ | -------------- | ----------------------- | ---------------------- | ---------------------- | -## Signature Schemes -| scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | -| ------ | -------------- | ----------------------- | ------------- | --------------- | -| ov-Ip (100 executions) | m4f | AVG: 138,685,787
MIN: 138,685,772
MAX: 138,685,828 | AVG: 2,488,529
MIN: 2,464,562
MAX: 4,861,007 | AVG: 993,529
MIN: 970,257
MAX: 996,849 | -| ov-Ip (100 executions) | ref | AVG: 350,266,803
MIN: 350,266,761
MAX: 350,267,118 | AVG: 6,548,206
MIN: 6,484,449
MAX: 12,858,979 | AVG: 1,309,303
MIN: 1,309,301
MAX: 1,309,336 | -| ov-Ip-pkc (100 executions) | m4fspeed | AVG: 174,887,930
MIN: 174,887,906
MAX: 174,887,957 | AVG: 2,556,235
MIN: 2,483,862
MAX: 4,896,138 | AVG: 10,699,967
MIN: 10,679,534
MAX: 10,703,471 | -| ov-Ip-pkc (100 executions) | m4fstack | AVG: 174,887,935
MIN: 174,887,911
MAX: 174,887,964 | AVG: 2,483,868
MIN: 2,483,862
MAX: 2,483,903 | AVG: 11,521,985
MIN: 11,494,511
MAX: 11,525,897 | -| ov-Ip-pkc (100 executions) | ref | AVG: 374,601,982
MIN: 374,601,950
MAX: 374,602,024 | AVG: 6,933,668
MIN: 6,933,653
MAX: 6,933,693 | AVG: 10,946,959
MIN: 10,946,937
MAX: 10,947,004 | -| ov-Ip-pkc-skc (100 executions) | m4fspeed | AVG: 174,888,071
MIN: 174,888,044
MAX: 174,888,099 | AVG: 88,664,377
MIN: 88,664,362
MAX: 88,664,408 | AVG: 11,458,067
MIN: 11,429,199
MAX: 11,462,352 | -| ov-Ip-pkc-skc (100 executions) | m4fstack | AVG: 174,888,061
MIN: 174,888,040
MAX: 174,888,089 | AVG: 88,664,370
MIN: 88,664,359
MAX: 88,664,402 | AVG: 11,521,533
MIN: 11,491,491
MAX: 11,525,897 | -| ov-Ip-pkc-skc (100 executions) | ref | AVG: 374,602,058
MIN: 374,602,033
MAX: 374,602,092 | AVG: 241,007,574
MIN: 241,007,551
MAX: 241,007,605 | AVG: 11,657,933
MIN: 11,657,906
MAX: 11,657,948 | -# Memory Evaluation -## Key Encapsulation Schemes -| Scheme | Implementation | Key Generation [bytes] | Encapsulation [bytes] | Decapsulation [bytes] | -| ------ | -------------- | ---------------------- | --------------------- | --------------------- | -## Signature Schemes -| Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | -| ------ | -------------- | ---------------------- | ------------ | -------------- | -| ov-Ip | m4f | 1,488 | 5,252 | 2,548 | -| ov-Ip | ref | 1,536 | 3,640 | 6,160 | -| ov-Ip-pkc | m4fspeed | 142,288 | 5,252 | 280,980 | -| ov-Ip-pkc | m4fstack | 133,152 | 5,252 | 6,560 | -| ov-Ip-pkc | ref | 15,752 | 12,872 | 284,704 | -| ov-Ip-pkc-skc | m4fspeed | 371,072 | 243,164 | 280,980 | -| ov-Ip-pkc-skc | m4fstack | 371,072 | 243,164 | 6,560 | -| ov-Ip-pkc-skc | ref | 253,656 | 253,616 | 284,704 | -# Hashing Evaluation -## Key Encapsulation Schemes -| Scheme | Implementation | Key Generation [%] | Encapsulation [%] | Decapsulation [%] | -| ------ | -------------- | ------------------ | ----------------- | ----------------- | -## Signature Schemes -| Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | -| ------ | -------------- | ------------------ | -------- | ---------- | -| ov-Ip | m4f | 7.2% | 0.9% | 1.1% | -| ov-Ip | ref | 2.8% | 0.3% | 0.9% | -| ov-Ip-pkc | m4fspeed | 6.1% | 0.9% | 90.8% | -| ov-Ip-pkc | m4fstack | 6.1% | 0.9% | 90.7% | -| ov-Ip-pkc | ref | 2.8% | 0.3% | 88.8% | -| ov-Ip-pkc-skc | m4fspeed | 6.1% | 12.1% | 91.2% | -| ov-Ip-pkc-skc | m4fstack | 6.1% | 12.1% | 90.7% | -| ov-Ip-pkc-skc | ref | 2.8% | 4.4% | 89.6% | -# Size Evaluation -## Key Encapsulation Schemes -| Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | -| ------ | -------------- | ------------- | ------------- | ------------ | ------------- | -## Signature Schemes -| Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | -| ------ | -------------- | ------------- | ------------- | ------------ | ------------- | -| ov-Ip | m4f | 116,847 | 0 | 0 | 116,847 | -| ov-Ip | ref | 28,599 | 0 | 0 | 28,599 | -| ov-Ip-pkc | m4fspeed | 117,039 | 0 | 0 | 117,039 | -| ov-Ip-pkc | m4fstack | 116,967 | 0 | 0 | 116,967 | -| ov-Ip-pkc | ref | 28,807 | 0 | 0 | 28,807 | -| ov-Ip-pkc-skc | m4fspeed | 117,083 | 0 | 0 | 117,083 | -| ov-Ip-pkc-skc | m4fstack | 117,011 | 0 | 0 | 117,011 | -| ov-Ip-pkc-skc | ref | 28,851 | 0 | 0 | 28,851 | From 6eb3b6ccc31d30b99ac030c582f59a8c9fc349c7 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 6 Nov 2023 14:36:04 +0800 Subject: [PATCH 018/107] revert unnecessary change in aes-publicinputs.h --- common/aes-publicinputs.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/aes-publicinputs.h b/common/aes-publicinputs.h index 8305304c..13fbadde 100644 --- a/common/aes-publicinputs.h +++ b/common/aes-publicinputs.h @@ -1,8 +1,6 @@ #ifndef AES_PUBLICINPUTS_H #define AES_PUBLICINPUTS_H -#define PQM4_AES - #include #include From 420726ae369f791803e0eba53c8690dea226dc41 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 Nov 2023 10:17:41 +0800 Subject: [PATCH 019/107] update skiplist --- skiplist.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/skiplist.py b/skiplist.py index fa01a9dd..e6a81bce 100644 --- a/skiplist.py +++ b/skiplist.py @@ -168,12 +168,12 @@ {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, - {'scheme': 'ov-Ip', 'implementation': 'm4f', 'estmemory': 524288}, - {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fstack', 'estmemory': 361472}, + {'scheme': 'ov-Ip', 'implementation': 'm4f', 'estmemory': 534528}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fstack', 'estmemory': 425984}, {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fspeed', 'estmemory': 565248}, - {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fstack', 'estmemory': 332800}, - {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fspeed', 'estmemory': 332800}, - {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 525312}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fstack', 'estmemory': 425984}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fspeed', 'estmemory': 425984}, + {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, -] \ No newline at end of file +] From 2b7d3363ebf20204a65f1ec2dae5a31129dcb7a0 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 Nov 2023 14:08:55 +0800 Subject: [PATCH 020/107] Add hawk{256,512,1024} --- mupq | 2 +- skiplist.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mupq b/mupq index 9998553b..ba23c2e4 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 9998553b42bd224fc391f156d2f1bc00bbddd543 +Subproject commit ba23c2e48b3c1591fc281e0ff1fd50986b22053b diff --git a/skiplist.py b/skiplist.py index b5e657db..e85410f7 100644 --- a/skiplist.py +++ b/skiplist.py @@ -168,4 +168,7 @@ {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, -] \ No newline at end of file + {'scheme': 'hawk512', 'implementation': 'ref', 'estmemory': 17408}, + {'scheme': 'hawk1024', 'implementation': 'ref', 'estmemory': 32768}, + {'scheme': 'hawk256', 'implementation': 'ref', 'estmemory': 10240}, +] From 135cca9a746fee8b46b87b4d005a550a945d00bb Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 7 Nov 2023 08:26:49 +0100 Subject: [PATCH 021/107] Update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 69d42650..b39deb51 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 69d42650336bdfaa10cd81cfd2203ffb5354878b +Subproject commit b39deb519813f44a9da620e6136f5a3b9cd9c632 From c96e268731d61771196eca49bf1dd90bef90fd4b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 Nov 2023 15:22:21 +0800 Subject: [PATCH 022/107] Add perk perk-128-fast-{3,5} should be able to run on the 640 KB RAM board. The perk-{192,256}-short-* are out of reach even with 4 MB RAM in qemu, so I did not include those. The remaining ones run in 4 MB RAM, but won't run on the board. --- mupq | 2 +- skiplist.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index b39deb51..1b9f2504 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit b39deb519813f44a9da620e6136f5a3b9cd9c632 +Subproject commit 1b9f250468a7ac59581fb696c415c7af11a1f679 diff --git a/skiplist.py b/skiplist.py index e6a81bce..e69a59a2 100644 --- a/skiplist.py +++ b/skiplist.py @@ -176,4 +176,12 @@ {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, + {'scheme': 'perk-192-fast-3', 'implementation': 'ref', 'estmemory': 1036288}, + {'scheme': 'perk-192-fast-5', 'implementation': 'ref', 'estmemory': 1001472}, + {'scheme': 'perk-128-fast-5', 'implementation': 'ref', 'estmemory': 463872}, + {'scheme': 'perk-256-fast-5', 'implementation': 'ref', 'estmemory': 1722368}, + {'scheme': 'perk-128-fast-3', 'implementation': 'ref', 'estmemory': 475136}, + {'scheme': 'perk-128-short-5', 'implementation': 'ref', 'estmemory': 2235392}, + {'scheme': 'perk-256-fast-3', 'implementation': 'ref', 'estmemory': 1797120}, + {'scheme': 'perk-128-short-3', 'implementation': 'ref', 'estmemory': 2377728}, ] From f638ce67f59ae1a96c33bfe6bf677b2f1ee71dec Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 13 Nov 2023 17:06:08 +0800 Subject: [PATCH 023/107] Add ascon-sign{128,192}{s,f}-{simple,robust} --- mupq | 2 +- skiplist.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index b39deb51..332fd4f5 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit b39deb519813f44a9da620e6136f5a3b9cd9c632 +Subproject commit 332fd4f52d985e38b805acda2ebda74d4de1aa78 diff --git a/skiplist.py b/skiplist.py index e6a81bce..feec4ce9 100644 --- a/skiplist.py +++ b/skiplist.py @@ -176,4 +176,12 @@ {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, + {'scheme': 'ascon-sign-128s-simple', 'implementation': 'ref', 'estmemory': 12288}, + {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, + {'scheme': 'ascon-sign-192s-simple', 'implementation': 'ref', 'estmemory': 22528}, + {'scheme': 'ascon-sign-192f-robust', 'implementation': 'ref', 'estmemory': 43008}, + {'scheme': 'ascon-sign-192f-simple', 'implementation': 'ref', 'estmemory': 41984}, + {'scheme': 'ascon-sign-192s-robust', 'implementation': 'ref', 'estmemory': 23552}, + {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, + {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, ] From 179b50bf2d62d50a7da7e78f1c4e6384796754c3 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 14 Nov 2023 15:11:47 +0800 Subject: [PATCH 024/107] Add cross-{sha2,sha3}-r-sdp{,g}-{1,3,5}-{small,fast} --- mupq | 2 +- skiplist.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index b39deb51..ea21ef58 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit b39deb519813f44a9da620e6136f5a3b9cd9c632 +Subproject commit ea21ef587b69dc2a8072993174f646f24fca4f87 diff --git a/skiplist.py b/skiplist.py index e6a81bce..cda4e180 100644 --- a/skiplist.py +++ b/skiplist.py @@ -176,4 +176,28 @@ {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, + {'scheme': 'cross-sha3-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, + {'scheme': 'cross-sha3-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, + {'scheme': 'cross-sha3-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, + {'scheme': 'cross-sha2-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, + {'scheme': 'cross-sha2-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, + {'scheme': 'cross-sha2-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, + {'scheme': 'cross-sha2-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, + {'scheme': 'cross-sha3-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, + {'scheme': 'cross-sha2-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'cross-sha3-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, + {'scheme': 'cross-sha2-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, + {'scheme': 'cross-sha3-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, + {'scheme': 'cross-sha3-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, + {'scheme': 'cross-sha2-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, + {'scheme': 'cross-sha2-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, + {'scheme': 'cross-sha2-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, + {'scheme': 'cross-sha2-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, + {'scheme': 'cross-sha3-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, + {'scheme': 'cross-sha3-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, + {'scheme': 'cross-sha2-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, + {'scheme': 'cross-sha2-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, + {'scheme': 'cross-sha3-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, + {'scheme': 'cross-sha3-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, + {'scheme': 'cross-sha3-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, ] From f8fdca265c77cac2082e75e976c5a74b51cc16ed Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 14 Nov 2023 15:54:37 +0800 Subject: [PATCH 025/107] use pqm4/mupq sha2 --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index ea21ef58..150f06d0 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit ea21ef587b69dc2a8072993174f646f24fca4f87 +Subproject commit 150f06d08d6292f1f58f058ef2e5feee21b23a80 From ec5c8448559bd585f33762faadba33dde1d5ba56 Mon Sep 17 00:00:00 2001 From: rpls Date: Wed, 15 Nov 2023 16:56:12 +0100 Subject: [PATCH 026/107] Add progress bar support (#307) * Add progress bar support * Raise exit-code if tests fail * Update mupq * Add forgotten import * Update mupq --- benchmarks.py | 13 +++++++++---- interface.py | 3 ++- mupq | 2 +- requirements.txt | 1 + test.py | 3 ++- testvectors.py | 4 +++- 6 files changed, 18 insertions(+), 8 deletions(-) diff --git a/benchmarks.py b/benchmarks.py index fdc93ee9..5895fc0e 100755 --- a/benchmarks.py +++ b/benchmarks.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from mupq import mupq from interface import parse_arguments, get_platform +import sys if __name__ == "__main__": args, rest = parse_arguments() @@ -12,16 +13,20 @@ '--nosize']] if "--nostack" not in rest: test = mupq.StackBenchmark(settings, platform) - test.test_all(schemes) + if test.test_all(schemes): + sys.exit(1) if "--nospeed" not in rest: test = mupq.SpeedBenchmark(settings, platform) - test.test_all(schemes) + if test.test_all(schemes): + sys.exit(1) if "--nohashing" not in rest: test = mupq.HashingBenchmark(settings, platform) - test.test_all(schemes) + if test.test_all(schemes): + sys.exit(1) if "--nosize" not in rest: test = mupq.SizeBenchmark(settings, platform) - test.test_all(schemes) + if test.test_all(schemes): + sys.exit(1) diff --git a/interface.py b/interface.py index 3b83fa7c..64278507 100644 --- a/interface.py +++ b/interface.py @@ -27,7 +27,7 @@ def parse_arguments(): "--no-aio", help="Disable all-in-one compilation", default=False, action="store_true" ) parser.add_argument("-u", "--uart", default="/dev/ttyUSB0", help="Path to UART output") - parser.add_argument("-i", "--iterations", default=1, help="Number of iterations for benchmarks") + parser.add_argument("-i", "--iterations", type=int, default=1, help="Number of iterations for benchmarks") return parser.parse_known_args() @@ -88,6 +88,7 @@ def __init__(self, platform, opt="speed", lto=False, aio=False, iterations=1, bi self.makeflags = [f"PLATFORM={platform}"] self.makeflags += [f"MUPQ_ITERATIONS={iterations}"] self.makeflags += optflags[opt] + self.iterations = iterations if lto: self.makeflags += ["LTO=1"] else: diff --git a/mupq b/mupq index b39deb51..0abc3dfa 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit b39deb519813f44a9da620e6136f5a3b9cd9c632 +Subproject commit 0abc3dfa42e966ebbd674da9db5967e7ca64f506 diff --git a/requirements.txt b/requirements.txt index 205196f8..4a96b58d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ pyserial==3.4 +tqdm diff --git a/test.py b/test.py index 61872ede..2d6686af 100755 --- a/test.py +++ b/test.py @@ -9,4 +9,5 @@ platform, settings = get_platform(args) with platform: test = mupq.SimpleTest(settings, platform) - test.test_all(rest) + if test.test_all(rest): + sys.exit(1) diff --git a/testvectors.py b/testvectors.py index f6bbc51e..2424a483 100755 --- a/testvectors.py +++ b/testvectors.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 from mupq import mupq from interface import parse_arguments, get_platform +import sys if __name__ == "__main__": args, rest = parse_arguments() platform, settings = get_platform(args) with platform: test = mupq.TestVectors(settings, platform) - test.test_all(rest) + if test.test_all(rest): + sys.exit(1) From 92f01872ca05db0d9930987f03db23466ac71ec2 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 16 Nov 2023 14:32:42 +0800 Subject: [PATCH 027/107] Add SNOVA --- mupq | 2 +- skiplist.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 0abc3dfa..97c1c0a3 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 0abc3dfa42e966ebbd674da9db5967e7ca64f506 +Subproject commit 97c1c0a3c42d9102384717510d1f5d22faf344b2 diff --git a/skiplist.py b/skiplist.py index e6a81bce..7f57ec15 100644 --- a/skiplist.py +++ b/skiplist.py @@ -176,4 +176,22 @@ {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, + {'scheme': 'snova-43-25-16-2-esk', 'implementation': 'ref', 'estmemory': 1274880}, + {'scheme': 'snova-43-25-16-2-ssk', 'implementation': 'ref', 'estmemory': 1072128}, + {'scheme': 'snova-61-33-16-2-esk', 'implementation': 'ref', 'estmemory': 3232768}, + {'scheme': 'snova-28-17-16-2-ssk', 'implementation': 'ref', 'estmemory': 320512}, + {'scheme': 'snova-25-8-16-3-ssk', 'implementation': 'ref', 'estmemory': 194560}, + {'scheme': 'snova-25-8-16-3-esk', 'implementation': 'ref', 'estmemory': 232448}, + {'scheme': 'snova-24-5-16-4-ssk', 'implementation': 'ref', 'estmemory': 172032}, + {'scheme': 'snova-24-5-16-4-esk', 'implementation': 'ref', 'estmemory': 205824}, + {'scheme': 'snova-60-10-16-4-esk', 'implementation': 'ref', 'estmemory': 2342912}, + {'scheme': 'snova-66-15-16-3-ssk', 'implementation': 'ref', 'estmemory': 2185216}, + {'scheme': 'snova-66-15-16-3-esk', 'implementation': 'ref', 'estmemory': 2617344}, + {'scheme': 'snova-49-11-16-3-ssk', 'implementation': 'ref', 'estmemory': 880640}, + {'scheme': 'snova-49-11-16-3-esk', 'implementation': 'ref', 'estmemory': 1055744}, + {'scheme': 'snova-61-33-16-2-ssk', 'implementation': 'ref', 'estmemory': 2716672}, + {'scheme': 'snova-28-17-16-2-esk', 'implementation': 'ref', 'estmemory': 380928}, + {'scheme': 'snova-60-10-16-4-ssk', 'implementation': 'ref', 'estmemory': 1953792}, + {'scheme': 'snova-37-8-16-4-esk', 'implementation': 'ref', 'estmemory': 775168}, + {'scheme': 'snova-37-8-16-4-ssk', 'implementation': 'ref', 'estmemory': 646144}, ] From 564ac86e091ab49b3ef4fc9f984000aeb2f61e93 Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 21 Nov 2023 00:01:11 +0100 Subject: [PATCH 028/107] initial commit of HAETAE M4F version corresponds to reference version of 2023-10-21. --- crypto_sign/haetae2/m4f/api.h | 6 + crypto_sign/haetae2/m4f/arm_simd.h | 28 + crypto_sign/haetae2/m4f/config.h | 19 + crypto_sign/haetae2/m4f/decompose.c | 69 ++ crypto_sign/haetae2/m4f/decompose.h | 16 + crypto_sign/haetae2/m4f/encoding.c | 227 ++++++ crypto_sign/haetae2/m4f/encoding.h | 17 + crypto_sign/haetae2/m4f/fast_exp_asm.S | 197 +++++ crypto_sign/haetae2/m4f/fast_exp_asm.h | 8 + crypto_sign/haetae2/m4f/fast_sampler.S | 94 +++ crypto_sign/haetae2/m4f/fast_sampler.h | 8 + crypto_sign/haetae2/m4f/fft.c | 231 ++++++ crypto_sign/haetae2/m4f/fft.h | 19 + crypto_sign/haetae2/m4f/fips202.h | 174 ++++ crypto_sign/haetae2/m4f/fixpoint.c | 141 ++++ crypto_sign/haetae2/m4f/fixpoint.h | 123 +++ crypto_sign/haetae2/m4f/fp84_76.c | 282 +++++++ crypto_sign/haetae2/m4f/fp84_76.h | 36 + crypto_sign/haetae2/m4f/fpa.h | 47 ++ crypto_sign/haetae2/m4f/header_macros.i | 59 ++ crypto_sign/haetae2/m4f/ntt332.S | 659 ++++++++++++++++ crypto_sign/haetae2/m4f/ntt332.h | 14 + crypto_sign/haetae2/m4f/ntt332_macros.i | 193 +++++ crypto_sign/haetae2/m4f/packing.c | 266 +++++++ crypto_sign/haetae2/m4f/packing.h | 26 + crypto_sign/haetae2/m4f/params.h | 140 ++++ crypto_sign/haetae2/m4f/poly.c | 825 +++++++++++++++++++ crypto_sign/haetae2/m4f/poly.h | 116 +++ crypto_sign/haetae2/m4f/polyfix.c | 382 +++++++++ crypto_sign/haetae2/m4f/polyfix.h | 71 ++ crypto_sign/haetae2/m4f/polymat.c | 175 ++++ crypto_sign/haetae2/m4f/polymat.h | 34 + crypto_sign/haetae2/m4f/polyvec.c | 547 +++++++++++++ crypto_sign/haetae2/m4f/polyvec.h | 141 ++++ crypto_sign/haetae2/m4f/rans_byte.h | 333 ++++++++ crypto_sign/haetae2/m4f/reduce.c | 95 +++ crypto_sign/haetae2/m4f/reduce.h | 41 + crypto_sign/haetae2/m4f/sampler.c | 377 +++++++++ crypto_sign/haetae2/m4f/sampler.h | 35 + crypto_sign/haetae2/m4f/sign.c | 919 ++++++++++++++++++++++ crypto_sign/haetae2/m4f/sign.h | 40 + crypto_sign/haetae2/m4f/symmetric-shake.c | 59 ++ crypto_sign/haetae2/m4f/symmetric.h | 85 ++ crypto_sign/haetae3/m4f/api.h | 1 + crypto_sign/haetae3/m4f/arm_simd.h | 1 + crypto_sign/haetae3/m4f/config.h | 19 + crypto_sign/haetae3/m4f/decompose.c | 1 + crypto_sign/haetae3/m4f/decompose.h | 1 + crypto_sign/haetae3/m4f/encoding.c | 1 + crypto_sign/haetae3/m4f/encoding.h | 1 + crypto_sign/haetae3/m4f/fast_exp_asm.S | 1 + crypto_sign/haetae3/m4f/fast_exp_asm.h | 1 + crypto_sign/haetae3/m4f/fast_sampler.S | 1 + crypto_sign/haetae3/m4f/fast_sampler.h | 1 + crypto_sign/haetae3/m4f/fft.c | 1 + crypto_sign/haetae3/m4f/fft.h | 1 + crypto_sign/haetae3/m4f/fips202.h | 1 + crypto_sign/haetae3/m4f/fixpoint.c | 1 + crypto_sign/haetae3/m4f/fixpoint.h | 1 + crypto_sign/haetae3/m4f/fp84_76.c | 1 + crypto_sign/haetae3/m4f/fp84_76.h | 1 + crypto_sign/haetae3/m4f/fpa.h | 1 + crypto_sign/haetae3/m4f/header_macros.i | 1 + crypto_sign/haetae3/m4f/ntt332.S | 1 + crypto_sign/haetae3/m4f/ntt332.h | 1 + crypto_sign/haetae3/m4f/ntt332_macros.i | 1 + crypto_sign/haetae3/m4f/packing.c | 1 + crypto_sign/haetae3/m4f/packing.h | 1 + crypto_sign/haetae3/m4f/params.h | 1 + crypto_sign/haetae3/m4f/poly.c | 1 + crypto_sign/haetae3/m4f/poly.h | 1 + crypto_sign/haetae3/m4f/polyfix.c | 1 + crypto_sign/haetae3/m4f/polyfix.h | 1 + crypto_sign/haetae3/m4f/polymat.c | 1 + crypto_sign/haetae3/m4f/polymat.h | 1 + crypto_sign/haetae3/m4f/polyvec.c | 1 + crypto_sign/haetae3/m4f/polyvec.h | 1 + crypto_sign/haetae3/m4f/rans_byte.h | 1 + crypto_sign/haetae3/m4f/reduce.c | 1 + crypto_sign/haetae3/m4f/reduce.h | 1 + crypto_sign/haetae3/m4f/sampler.c | 1 + crypto_sign/haetae3/m4f/sampler.h | 1 + crypto_sign/haetae3/m4f/sign.c | 1 + crypto_sign/haetae3/m4f/sign.h | 1 + crypto_sign/haetae3/m4f/symmetric-shake.c | 1 + crypto_sign/haetae3/m4f/symmetric.h | 1 + crypto_sign/haetae5/m4f/api.h | 1 + crypto_sign/haetae5/m4f/arm_simd.h | 1 + crypto_sign/haetae5/m4f/config.h | 19 + crypto_sign/haetae5/m4f/decompose.c | 1 + crypto_sign/haetae5/m4f/decompose.h | 1 + crypto_sign/haetae5/m4f/encoding.c | 1 + crypto_sign/haetae5/m4f/encoding.h | 1 + crypto_sign/haetae5/m4f/fast_exp_asm.S | 1 + crypto_sign/haetae5/m4f/fast_exp_asm.h | 1 + crypto_sign/haetae5/m4f/fast_sampler.S | 1 + crypto_sign/haetae5/m4f/fast_sampler.h | 1 + crypto_sign/haetae5/m4f/fft.c | 1 + crypto_sign/haetae5/m4f/fft.h | 1 + crypto_sign/haetae5/m4f/fips202.h | 1 + crypto_sign/haetae5/m4f/fixpoint.c | 1 + crypto_sign/haetae5/m4f/fixpoint.h | 1 + crypto_sign/haetae5/m4f/fp84_76.c | 1 + crypto_sign/haetae5/m4f/fp84_76.h | 1 + crypto_sign/haetae5/m4f/fpa.h | 1 + crypto_sign/haetae5/m4f/header_macros.i | 1 + crypto_sign/haetae5/m4f/ntt332.S | 1 + crypto_sign/haetae5/m4f/ntt332.h | 1 + crypto_sign/haetae5/m4f/ntt332_macros.i | 1 + crypto_sign/haetae5/m4f/packing.c | 1 + crypto_sign/haetae5/m4f/packing.h | 1 + crypto_sign/haetae5/m4f/params.h | 1 + crypto_sign/haetae5/m4f/poly.c | 1 + crypto_sign/haetae5/m4f/poly.h | 1 + crypto_sign/haetae5/m4f/polyfix.c | 1 + crypto_sign/haetae5/m4f/polyfix.h | 1 + crypto_sign/haetae5/m4f/polymat.c | 1 + crypto_sign/haetae5/m4f/polymat.h | 1 + crypto_sign/haetae5/m4f/polyvec.c | 1 + crypto_sign/haetae5/m4f/polyvec.h | 1 + crypto_sign/haetae5/m4f/rans_byte.h | 1 + crypto_sign/haetae5/m4f/reduce.c | 1 + crypto_sign/haetae5/m4f/reduce.h | 1 + crypto_sign/haetae5/m4f/sampler.c | 1 + crypto_sign/haetae5/m4f/sampler.h | 1 + crypto_sign/haetae5/m4f/sign.c | 1 + crypto_sign/haetae5/m4f/sign.h | 1 + crypto_sign/haetae5/m4f/symmetric-shake.c | 1 + crypto_sign/haetae5/m4f/symmetric.h | 1 + 129 files changed, 7496 insertions(+) create mode 100644 crypto_sign/haetae2/m4f/api.h create mode 100644 crypto_sign/haetae2/m4f/arm_simd.h create mode 100644 crypto_sign/haetae2/m4f/config.h create mode 100644 crypto_sign/haetae2/m4f/decompose.c create mode 100644 crypto_sign/haetae2/m4f/decompose.h create mode 100644 crypto_sign/haetae2/m4f/encoding.c create mode 100644 crypto_sign/haetae2/m4f/encoding.h create mode 100644 crypto_sign/haetae2/m4f/fast_exp_asm.S create mode 100644 crypto_sign/haetae2/m4f/fast_exp_asm.h create mode 100644 crypto_sign/haetae2/m4f/fast_sampler.S create mode 100644 crypto_sign/haetae2/m4f/fast_sampler.h create mode 100644 crypto_sign/haetae2/m4f/fft.c create mode 100644 crypto_sign/haetae2/m4f/fft.h create mode 100644 crypto_sign/haetae2/m4f/fips202.h create mode 100644 crypto_sign/haetae2/m4f/fixpoint.c create mode 100644 crypto_sign/haetae2/m4f/fixpoint.h create mode 100644 crypto_sign/haetae2/m4f/fp84_76.c create mode 100644 crypto_sign/haetae2/m4f/fp84_76.h create mode 100644 crypto_sign/haetae2/m4f/fpa.h create mode 100644 crypto_sign/haetae2/m4f/header_macros.i create mode 100644 crypto_sign/haetae2/m4f/ntt332.S create mode 100644 crypto_sign/haetae2/m4f/ntt332.h create mode 100644 crypto_sign/haetae2/m4f/ntt332_macros.i create mode 100644 crypto_sign/haetae2/m4f/packing.c create mode 100644 crypto_sign/haetae2/m4f/packing.h create mode 100644 crypto_sign/haetae2/m4f/params.h create mode 100644 crypto_sign/haetae2/m4f/poly.c create mode 100644 crypto_sign/haetae2/m4f/poly.h create mode 100644 crypto_sign/haetae2/m4f/polyfix.c create mode 100644 crypto_sign/haetae2/m4f/polyfix.h create mode 100644 crypto_sign/haetae2/m4f/polymat.c create mode 100644 crypto_sign/haetae2/m4f/polymat.h create mode 100644 crypto_sign/haetae2/m4f/polyvec.c create mode 100644 crypto_sign/haetae2/m4f/polyvec.h create mode 100644 crypto_sign/haetae2/m4f/rans_byte.h create mode 100644 crypto_sign/haetae2/m4f/reduce.c create mode 100644 crypto_sign/haetae2/m4f/reduce.h create mode 100644 crypto_sign/haetae2/m4f/sampler.c create mode 100644 crypto_sign/haetae2/m4f/sampler.h create mode 100644 crypto_sign/haetae2/m4f/sign.c create mode 100644 crypto_sign/haetae2/m4f/sign.h create mode 100644 crypto_sign/haetae2/m4f/symmetric-shake.c create mode 100644 crypto_sign/haetae2/m4f/symmetric.h create mode 120000 crypto_sign/haetae3/m4f/api.h create mode 120000 crypto_sign/haetae3/m4f/arm_simd.h create mode 100644 crypto_sign/haetae3/m4f/config.h create mode 120000 crypto_sign/haetae3/m4f/decompose.c create mode 120000 crypto_sign/haetae3/m4f/decompose.h create mode 120000 crypto_sign/haetae3/m4f/encoding.c create mode 120000 crypto_sign/haetae3/m4f/encoding.h create mode 120000 crypto_sign/haetae3/m4f/fast_exp_asm.S create mode 120000 crypto_sign/haetae3/m4f/fast_exp_asm.h create mode 120000 crypto_sign/haetae3/m4f/fast_sampler.S create mode 120000 crypto_sign/haetae3/m4f/fast_sampler.h create mode 120000 crypto_sign/haetae3/m4f/fft.c create mode 120000 crypto_sign/haetae3/m4f/fft.h create mode 120000 crypto_sign/haetae3/m4f/fips202.h create mode 120000 crypto_sign/haetae3/m4f/fixpoint.c create mode 120000 crypto_sign/haetae3/m4f/fixpoint.h create mode 120000 crypto_sign/haetae3/m4f/fp84_76.c create mode 120000 crypto_sign/haetae3/m4f/fp84_76.h create mode 120000 crypto_sign/haetae3/m4f/fpa.h create mode 120000 crypto_sign/haetae3/m4f/header_macros.i create mode 120000 crypto_sign/haetae3/m4f/ntt332.S create mode 120000 crypto_sign/haetae3/m4f/ntt332.h create mode 120000 crypto_sign/haetae3/m4f/ntt332_macros.i create mode 120000 crypto_sign/haetae3/m4f/packing.c create mode 120000 crypto_sign/haetae3/m4f/packing.h create mode 120000 crypto_sign/haetae3/m4f/params.h create mode 120000 crypto_sign/haetae3/m4f/poly.c create mode 120000 crypto_sign/haetae3/m4f/poly.h create mode 120000 crypto_sign/haetae3/m4f/polyfix.c create mode 120000 crypto_sign/haetae3/m4f/polyfix.h create mode 120000 crypto_sign/haetae3/m4f/polymat.c create mode 120000 crypto_sign/haetae3/m4f/polymat.h create mode 120000 crypto_sign/haetae3/m4f/polyvec.c create mode 120000 crypto_sign/haetae3/m4f/polyvec.h create mode 120000 crypto_sign/haetae3/m4f/rans_byte.h create mode 120000 crypto_sign/haetae3/m4f/reduce.c create mode 120000 crypto_sign/haetae3/m4f/reduce.h create mode 120000 crypto_sign/haetae3/m4f/sampler.c create mode 120000 crypto_sign/haetae3/m4f/sampler.h create mode 120000 crypto_sign/haetae3/m4f/sign.c create mode 120000 crypto_sign/haetae3/m4f/sign.h create mode 120000 crypto_sign/haetae3/m4f/symmetric-shake.c create mode 120000 crypto_sign/haetae3/m4f/symmetric.h create mode 120000 crypto_sign/haetae5/m4f/api.h create mode 120000 crypto_sign/haetae5/m4f/arm_simd.h create mode 100644 crypto_sign/haetae5/m4f/config.h create mode 120000 crypto_sign/haetae5/m4f/decompose.c create mode 120000 crypto_sign/haetae5/m4f/decompose.h create mode 120000 crypto_sign/haetae5/m4f/encoding.c create mode 120000 crypto_sign/haetae5/m4f/encoding.h create mode 120000 crypto_sign/haetae5/m4f/fast_exp_asm.S create mode 120000 crypto_sign/haetae5/m4f/fast_exp_asm.h create mode 120000 crypto_sign/haetae5/m4f/fast_sampler.S create mode 120000 crypto_sign/haetae5/m4f/fast_sampler.h create mode 120000 crypto_sign/haetae5/m4f/fft.c create mode 120000 crypto_sign/haetae5/m4f/fft.h create mode 120000 crypto_sign/haetae5/m4f/fips202.h create mode 120000 crypto_sign/haetae5/m4f/fixpoint.c create mode 120000 crypto_sign/haetae5/m4f/fixpoint.h create mode 120000 crypto_sign/haetae5/m4f/fp84_76.c create mode 120000 crypto_sign/haetae5/m4f/fp84_76.h create mode 120000 crypto_sign/haetae5/m4f/fpa.h create mode 120000 crypto_sign/haetae5/m4f/header_macros.i create mode 120000 crypto_sign/haetae5/m4f/ntt332.S create mode 120000 crypto_sign/haetae5/m4f/ntt332.h create mode 120000 crypto_sign/haetae5/m4f/ntt332_macros.i create mode 120000 crypto_sign/haetae5/m4f/packing.c create mode 120000 crypto_sign/haetae5/m4f/packing.h create mode 120000 crypto_sign/haetae5/m4f/params.h create mode 120000 crypto_sign/haetae5/m4f/poly.c create mode 120000 crypto_sign/haetae5/m4f/poly.h create mode 120000 crypto_sign/haetae5/m4f/polyfix.c create mode 120000 crypto_sign/haetae5/m4f/polyfix.h create mode 120000 crypto_sign/haetae5/m4f/polymat.c create mode 120000 crypto_sign/haetae5/m4f/polymat.h create mode 120000 crypto_sign/haetae5/m4f/polyvec.c create mode 120000 crypto_sign/haetae5/m4f/polyvec.h create mode 120000 crypto_sign/haetae5/m4f/rans_byte.h create mode 120000 crypto_sign/haetae5/m4f/reduce.c create mode 120000 crypto_sign/haetae5/m4f/reduce.h create mode 120000 crypto_sign/haetae5/m4f/sampler.c create mode 120000 crypto_sign/haetae5/m4f/sampler.h create mode 120000 crypto_sign/haetae5/m4f/sign.c create mode 120000 crypto_sign/haetae5/m4f/sign.h create mode 120000 crypto_sign/haetae5/m4f/symmetric-shake.c create mode 120000 crypto_sign/haetae5/m4f/symmetric.h diff --git a/crypto_sign/haetae2/m4f/api.h b/crypto_sign/haetae2/m4f/api.h new file mode 100644 index 00000000..28d58fca --- /dev/null +++ b/crypto_sign/haetae2/m4f/api.h @@ -0,0 +1,6 @@ +#ifndef API_H +#define API_H + +#include "sign.h" + +#endif diff --git a/crypto_sign/haetae2/m4f/arm_simd.h b/crypto_sign/haetae2/m4f/arm_simd.h new file mode 100644 index 00000000..406d2a9a --- /dev/null +++ b/crypto_sign/haetae2/m4f/arm_simd.h @@ -0,0 +1,28 @@ +#ifndef ARM_SIMD_H +#define ARM_SIMD_H + +#include +#include + +typedef uint32_t uint16x2_t; + +/********************************************************************** + * Name: load_uint16x2_t + * Description: Loads two consecutive unsigned 16-bit values + * into one 32-bit register. We use half_index to + * ensure we read from the aligned address 2*half_index. + * This function is implemented to avoid typepunning; + * it should compile as a single load instruction + * for optimization levels -O1 and higher. + * Arguments: a: aligned head of the array to read from + * half_index: half the index to be read from. + * Returns: Two unsigned 16-bit values packed as bottom and + * top part of a 32-bit register value. + *********************************************************************/ +static inline uint16x2_t load_uint16x2_t(const uint16_t a[], size_t half_index){ + uint16x2_t t; + memcpy(&t, &a[half_index << 1], sizeof(t)); + return t; +} + +#endif /* ARM_SIMD_H */ diff --git a/crypto_sign/haetae2/m4f/config.h b/crypto_sign/haetae2/m4f/config.h new file mode 100644 index 00000000..52c9e87b --- /dev/null +++ b/crypto_sign/haetae2/m4f/config.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 2 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif +#endif diff --git a/crypto_sign/haetae2/m4f/decompose.c b/crypto_sign/haetae2/m4f/decompose.c new file mode 100644 index 00000000..467767e5 --- /dev/null +++ b/crypto_sign/haetae2/m4f/decompose.c @@ -0,0 +1,69 @@ +#include "decompose.h" +#include "params.h" +#include + +/************************************************* + * Name: decompose_z1 + * + * Description: For finite field element r, compute high and lowbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *lowbits: pointer to output element lb + * - int32_t *highbits: pointer to output element hb + **************************************************/ +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r) { + const int alpha = 256; // TODO magic numbers! + const int log_alpha = 8; + + int32_t lb, center; + uint32_t alpha_mask = alpha - 1; + + lb = r & alpha_mask; + center = ((alpha >> 1) - (lb + 1)) >> 31; // if lb >= HALF_ALPHA + lb -= alpha & center; + *lowbits = lb; + *highbits = (r + (alpha >> 1)) >> log_alpha; +} + +/************************************************* + * Name: decompose_hint + * + * Description: For finite field element r, compute highbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *highbits: pointer to output element hb + **************************************************/ + +void decompose_hint(int32_t *highbits, const int32_t r) { + int32_t hb, edgecase; + + hb = (r + HALF_ALPHA_HINT) >> LOG_ALPHA_HINT; + edgecase = + ((DQ - 2) / ALPHA_HINT - (hb + 1)) >> 31; // if hb == (DQ-2)/ALPHA + hb -= (DQ - 2) / ALPHA_HINT & edgecase; // hb = 0 + + *highbits = hb; +} + +/************************************************* + * Name: decompose_vk + * + * Description: For finite field element a, compute a0, a1 such that + * a mod^+ Q = a1*2^D + a0 with -2^{D-1} <= a0 < 2^{D-1}. + * Assumes a to be standard representative. + * + * Arguments: - int32_t a: input element + * - int32_t *a0: pointer to output element a0 + * + * Returns a1 + **************************************************/ +int32_t decompose_vk(int32_t *a0, const int32_t a) { +#if D > 1 +#error "Only implemented for D = 1" +#endif + *a0 = a & 1; + *a0 -= ((a >> 1) & *a0) << 1; + return (a - *a0) >> 1; +} diff --git a/crypto_sign/haetae2/m4f/decompose.h b/crypto_sign/haetae2/m4f/decompose.h new file mode 100644 index 00000000..67146cf1 --- /dev/null +++ b/crypto_sign/haetae2/m4f/decompose.h @@ -0,0 +1,16 @@ +#ifndef HAETAE_ROUNDING_H +#define HAETAE_ROUNDING_H + +#include "params.h" +#include + +#define decompose_z1 HAETAE_NAMESPACE(decompose_z1) +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r); + +#define decompose_hint HAETAE_NAMESPACE(decompose_hint) +void decompose_hint(int32_t *highbits, const int32_t r); + +#define decompose_vk HAETAE_NAMESPACE(decompose_vk) +int32_t decompose_vk(int32_t *a0, const int32_t a); + +#endif diff --git a/crypto_sign/haetae2/m4f/encoding.c b/crypto_sign/haetae2/m4f/encoding.c new file mode 100644 index 00000000..ca6a182f --- /dev/null +++ b/crypto_sign/haetae2/m4f/encoding.c @@ -0,0 +1,227 @@ +#include "encoding.h" +#include "params.h" +#include "rans_byte.h" + +#include +#include +#include + +#define SCALE_BITS 10 +#define SCALE (1u << SCALE_BITS) + +#if HAETAE_MODE == 2 +#define M_H 13 +#define OFFSET_H 239 +#define M_HB_Z1 13 +#define OFFSET_HB_Z1 6 +static RansEncSymbol esyms_h[M_H] = {{801112064, -1416664605, 0, 642, 8}, {515899392, -2060187564, 382, 778, 7}, {136314880, -66076419, 628, 959, 6}, {14680064, -1840700269, 693, 1017, 2}, {2097152, -1, 1723, 1023, 0}, {2097152, -1, 1724, 1023, 0}, {2097152, -1, 1725, 1023, 0}, {2097152, -1, 1726, 1023, 0}, {2097152, -1, 1727, 1023, 0}, {2097152, -1, 1728, 1023, 0}, {14680064, -1840700269, 706, 1017, 2}, {136314880, -66076419, 713, 959, 6}, {515899392, -2060187564, 778, 778, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 382}, {382, 246}, {628, 65}, {693, 7}, {700, 1}, {701, 1}, {702, 1}, {703, 1}, {704, 1}, {705, 1}, {706, 7}, {713, 65}, {778, 246}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {10485760, -858993459, 3, 1019, 2}, {121634816, -1925330167, 8, 966, 5}, {515899392, -2060187564, 66, 778, 7}, {834666496, -1532375266, 312, 626, 8}, {517996544, -2069235255, 710, 777, 7}, {123731968, -1965493508, 957, 965, 5}, {10485760, -858993459, 1016, 1019, 2}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 5}, {8, 58}, {66, 246}, {312, 398}, {710, 247}, {957, 59}, {1016, 5}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 11, 12, }; + +#elif HAETAE_MODE == 3 +#define M_H 17 +#define OFFSET_H 235 +#define M_HB_Z1 17 +#define OFFSET_HB_Z1 8 +static RansEncSymbol esyms_h[M_H] = {{557842432, -161464935, 0, 758, 8}, {446693376, -1713954085, 266, 811, 7}, {236978176, -1862419446, 479, 911, 6}, {83886080, -858993459, 592, 984, 5}, {18874368, -477218588, 632, 1015, 3}, {2097152, -1, 1664, 1023, 0}, {2097152, -1, 1665, 1023, 0}, {2097152, -1, 1666, 1023, 0}, {2097152, -1, 1667, 1023, 0}, {2097152, -1, 1668, 1023, 0}, {2097152, -1, 1669, 1023, 0}, {2097152, -1, 1670, 1023, 0}, {2097152, -1, 1671, 1023, 0}, {18874368, -477218588, 649, 1015, 3}, {83886080, -858993459, 658, 984, 5}, {236978176, -1862419446, 698, 911, 6}, {446693376, -1713954085, 811, 811, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 266}, {266, 213}, {479, 113}, {592, 40}, {632, 9}, {641, 1}, {642, 1}, {643, 1}, {644, 1}, {645, 1}, {646, 1}, {647, 1}, {648, 1}, {649, 9}, {658, 40}, {698, 113}, {811, 213}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {16777216, -2147483648, 4, 1016, 2}, {77594624, -580400985, 12, 987, 5}, {234881024, -1840700269, 49, 912, 6}, {452984832, -1749801490, 161, 808, 7}, {564133888, -207563475, 377, 755, 8}, {452984832, -1749801490, 646, 808, 7}, {234881024, -1840700269, 862, 912, 6}, {79691776, -678152730, 974, 986, 5}, {16777216, -2147483648, 1012, 1016, 2}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 8}, {12, 37}, {49, 112}, {161, 216}, {377, 269}, {646, 216}, {862, 112}, {974, 38}, {1012, 8}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, }; + +#elif HAETAE_MODE == 5 +#define M_H 33 +#define OFFSET_H 471 +#define M_HB_Z1 19 +#define OFFSET_HB_Z1 9 +static RansEncSymbol esyms_h[M_H] = {{255852544, -2041869698, 0, 902, 6}, {245366784, -1945583475, 122, 907, 6}, {213909504, -1600085855, 239, 922, 6}, {169869312, -901412889, 341, 943, 6}, {123731968, -1965493508, 422, 965, 5}, {81788928, -770891565, 481, 985, 5}, {48234496, -1307163959, 520, 1001, 4}, {27262976, -1651910498, 543, 1011, 3}, {12582912, -1431655765, 556, 1018, 2}, {6291456, -1431655765, 562, 1021, 1}, {2097152, -1, 1588, 1023, 0}, {2097152, -1, 1589, 1023, 0}, {2097152, -1, 1590, 1023, 0}, {2097152, -1, 1591, 1023, 0}, {2097152, -1, 1592, 1023, 0}, {2097152, -1, 1593, 1023, 0}, {2097152, -1, 1594, 1023, 0}, {2097152, -1, 1595, 1023, 0}, {2097152, -1, 1596, 1023, 0}, {2097152, -1, 1597, 1023, 0}, {2097152, -1, 1598, 1023, 0}, {2097152, -1, 1599, 1023, 0}, {2097152, -1, 1600, 1023, 0}, {2097152, -1, 1601, 1023, 0}, {6291456, -1431655765, 579, 1021, 1}, {12582912, -1431655765, 582, 1018, 2}, {27262976, -1651910498, 588, 1011, 3}, {50331648, -1431655765, 601, 1000, 4}, {81788928, -770891565, 625, 985, 5}, {123731968, -1965493508, 664, 965, 5}, {169869312, -901412889, 723, 943, 6}, {213909504, -1600085855, 804, 922, 6}, {247463936, -1965493508, 906, 906, 6}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 122}, {122, 117}, {239, 102}, {341, 81}, {422, 59}, {481, 39}, {520, 23}, {543, 13}, {556, 6}, {562, 3}, {565, 1}, {566, 1}, {567, 1}, {568, 1}, {569, 1}, {570, 1}, {571, 1}, {572, 1}, {573, 1}, {574, 1}, {575, 1}, {576, 1}, {577, 1}, {578, 1}, {579, 3}, {582, 6}, {588, 13}, {601, 24}, {625, 39}, {664, 59}, {723, 81}, {804, 102}, {906, 118}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {4194304, -2147483648, 4, 1022, 0}, {27262976, -1651910498, 6, 1011, 3}, {100663296, -1431655765, 19, 976, 5}, {247463936, -1965493508, 67, 906, 6}, {427819008, -1600085855, 185, 820, 7}, {513802240, -2051066014, 389, 779, 7}, {427819008, -1600085855, 634, 820, 7}, {247463936, -1965493508, 838, 906, 6}, {100663296, -1431655765, 956, 976, 5}, {29360128, -1840700269, 1004, 1010, 3}, {4194304, -2147483648, 1018, 1022, 0}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 2}, {6, 13}, {19, 48}, {67, 118}, {185, 204}, {389, 245}, {634, 204}, {838, 118}, {956, 48}, {1004, 14}, {1018, 2}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 15, 16, 17, 18, }; + +#endif // HAETAE_MODE +#define H_CUT ((M_H -1) >>1) + +/************************************************* + * Name: encode_h + * + * Description: rANS encode polynomial vector h + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *h: pointer to polynomial vector h + **************************************************/ +uint16_t encode_h(uint8_t *buf, const int32_t *h) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + uint8_t encoding[size_h]; // size_h is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_h; // end of encoding buffer + + for (size_t i = size_h; i > 0; i--) { + tmp = h[i - 1]; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(H_CUT < tmp && tmp <= H_CUT + OFFSET_H) { + return 0; + } + // map the upper likely part of symbols next to the lower part + // to have a dense and compact distribution: + tmp = (tmp > (H_CUT + OFFSET_H)) ? tmp - OFFSET_H : tmp; + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_h[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_h - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_h + * + * Description: rANS decode polynomial vector h + * + * Arguments: - int32_t *h: pointer to polynomial vector h + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_h; i++) { + s = symbol_h[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_H) { + return 1; // invalid symbol + } + tmp = (H_CUT < tmp) ? (tmp + OFFSET_H) : tmp; + h[i] = tmp; + RansDecAdvanceSymbol(&rans, (uint8_t **) &buf, buf_end, &dsyms_h[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} + +/************************************************* + * Name: encode_hb_z1 + * + * Description: rANS encode polynomial vector HighBits(z1) + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *hb_z1: pointer to polynomial vector + *HighBits(z1) + **************************************************/ +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_hb_z1 = N * L; + int8_t s; + int32_t tmp; + uint8_t encoding[size_hb_z1]; // size_hb_z1 is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_hb_z1; // end of output buffer + + for (size_t i = size_hb_z1; i > 0; i--) { + // from centered to positive representation: + tmp = hb_z1[i - 1] + OFFSET_HB_Z1; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(tmp < 0 || M_HB_Z1 <= tmp) { + return 0; + } + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_hb_z1[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_hb_z1 - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_hb_z1 + * + * Description: rANS decode polynomial vector HighBits(z1) + * + * Arguments: - int32_t *hb_z1: pointer to polynomial vector HighBits(z1) + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_hb_z1 = N * L; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_hb_z1; i++) { + s = symbol_hb_z1[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_HB_Z1) { + return 1; // invalid symbol + } + // from positive to centered representation: + hb_z1[i] = tmp - OFFSET_HB_Z1; + RansDecAdvanceSymbol(&rans, (uint8_t **)&buf, buf_end, &dsyms_hb_z1[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/encoding.h b/crypto_sign/haetae2/m4f/encoding.h new file mode 100644 index 00000000..b1e6239d --- /dev/null +++ b/crypto_sign/haetae2/m4f/encoding.h @@ -0,0 +1,17 @@ +#ifndef HAETAE_ENCODING_H +#define HAETAE_ENCODING_H + +#include "params.h" +#include +#include + +#define encode_h HAETAE_NAMESPACE(encode_h) +uint16_t encode_h(uint8_t *buf, const int32_t *h); +#define decode_h HAETAE_NAMESPACE(decode_h) +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in); +#define encode_hb_z1 HAETAE_NAMESPACE(encode_hb_z1) +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1); +#define decode_hb_z1 HAETAE_NAMESPACE(decode_hb_z1) +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in); + +#endif // HAETAE_ENCODING_H diff --git a/crypto_sign/haetae2/m4f/fast_exp_asm.S b/crypto_sign/haetae2/m4f/fast_exp_asm.S new file mode 100644 index 00000000..555db03b --- /dev/null +++ b/crypto_sign/haetae2/m4f/fast_exp_asm.S @@ -0,0 +1,197 @@ +.syntax unified +.thumb + +.cpu cortex-m4 +.arch armv7e-m +.fpu fpv4-sp-d16 + +.global haetae_approx_exp_asm +.type haetae_approx_exp_asm,%function +.align +haetae_approx_exp_asm: + lsrs r2, r0, #24 + orr r2, r2, r1, lsl #8 + push {r4, r5, r6, r7, r8, r9, r10, fp, lr} + ldr r5, haetae_approx_exp_asm_constants + ldr r4, haetae_approx_exp_asm_constants+4 + ldr r7, haetae_approx_exp_asm_constants+8 + sub r0, r0, r2, lsl #24 + smull r3, r1, r0, r5 + lsrs r3, r3, #24 + orr r3, r3, r1, lsl #8 + asrs r1, r1, #24 + smlal r3, r1, r0, r4 + smlal r3, r1, r2, r5 + adds r3, r3, #0x00800000 + adc r1, r1, #0 + lsrs r3, r3, #24 + orr r3, r3, r1, lsl #8 + asrs r1, r1, #24 + smlal r3, r1, r2, r4 + adds r3, r3, #4 + adc r1, r1, #0 + ldr r4, haetae_approx_exp_asm_constants+12 + lsrs r3, r3, #3 + orr r3, r3, r1, lsl #29 + adds r3, r3, r4 + movw lr, #46269 + adc lr, lr, r1, asr #3 + lsr ip, r3, #24 + orr ip, ip, lr, lsl #8 + sub r3, r3, ip, lsl #24 + smull r6, r10, r3, r0 + asr lr, lr, #24 + asrs r1, r0, #31 + mul r5, r0, lr + lsrs r6, r6, #24 + umull r4, fp, r0, ip + mla r5, ip, r1, r5 + orr r6, r6, r10, lsl #8 + adds r4, r4, r6 + add r5, r5, fp + adc r5, r5, r10, asr #24 + smlal r4, r5, r3, r2 + adds r4, r4, #0x00800000 + adc r5, r5, #0 + asrs r1, r2, #31 + mul lr, r2, lr + lsrs r4, r4, #24 + mla lr, ip, r1, lr + orr r4, r4, r5, lsl #8 + umull ip, r3, r2, ip + adds ip, ip, r4 + add lr, lr, r3 + adc lr, lr, r5, asr #24 + adds ip, ip, #4 + adc lr, lr, #0 + ldr r1, haetae_approx_exp_asm_constants+16 + lsr ip, ip, #3 + orr ip, ip, lr, lsl #29 + adds ip, ip, r1 + adc r7, r7, lr, asr #3 + lsr r1, ip, #24 + orr r1, r1, r7, lsl #8 + sub ip, ip, r1, lsl #24 + smull r3, r4, ip, r0 + lsrs r3, r3, #24 + orr r3, r3, r4, lsl #8 + asrs r4, r4, #24 + smlal r3, r4, r1, r0 + smlal r3, r4, ip, r2 + adds r3, r3, #0x00800000 + adc r4, r4, #0 + lsrs r3, r3, #24 + orr r3, r3, r4, lsl #8 + asrs r4, r4, #24 + smlal r3, r4, r1, r2 + adds r3, r3, #2 + adc r1, r4, #0 + lsrs r4, r3, #2 + ldr r3, haetae_approx_exp_asm_constants+20 + orr r4, r4, r1, lsl #30 + adds r4, r4, r3 + movw r3, #43690 + adc r3, r3, r1, asr #2 + lsrs r1, r4, #24 + orr r1, r1, r3, lsl #8 + sub r4, r4, r1, lsl #24 + smull r3, r5, r4, r0 + lsrs r3, r3, #24 + orr r3, r3, r5, lsl #8 + asrs r5, r5, #24 + smlal r3, r5, r1, r0 + smlal r3, r5, r4, r2 + adds r3, r3, #0x00800000 + adc r4, r5, #0 + lsrs r3, r3, #24 + orr r3, r3, r4, lsl #8 + asrs r4, r4, #24 + smlal r3, r4, r1, r2 + adds r3, r3, #2 + adc r1, r4, #0 + lsrs r3, r3, #2 + ldr r4, haetae_approx_exp_asm_constants+24 + orr r3, r3, r1, lsl #30 + adds r3, r3, r4 + ldr r4, haetae_approx_exp_asm_constants+28 + adc r4, r4, r1, asr #2 + lsrs r1, r3, #24 + orr r1, r1, r4, lsl #8 + sub r4, r3, r1, lsl #24 + smull r3, r5, r4, r0 + lsrs r3, r3, #24 + orr r3, r3, r5, lsl #8 + asrs r5, r5, #24 + smlal r3, r5, r1, r0 + smlal r3, r5, r4, r2 + adds r3, r3, #0x00800000 + adc r4, r5, #0 + lsrs r3, r3, #24 + orr r3, r3, r4, lsl #8 + asrs r4, r4, #24 + smlal r3, r4, r1, r2 + adds r3, r3, #1 + adc r1, r4, #0 + lsrs r3, r3, #1 + ldr r4, haetae_approx_exp_asm_constants+32 + orr r3, r3, r1, lsl #31 + adds r3, r3, r4 + movw r8, #65535 + adc r4, r8, r1, asr #1 + lsrs r1, r3, #24 + orr r1, r1, r4, lsl #8 + sub r4, r3, r1, lsl #24 + smull r3, r5, r4, r0 + lsrs r3, r3, #24 + orr r3, r3, r5, lsl #8 + asrs r5, r5, #24 + smlal r3, r5, r1, r0 + smlal r3, r5, r4, r2 + adds r3, r3, #0x00800000 + adc r4, r5, #0 + lsrs r3, r3, #24 + orr r3, r3, r4, lsl #8 + asrs r4, r4, #24 + smlal r3, r4, r1, r2 + adds r3, r3, #1 + adc r1, r4, #0 + lsrs r3, r3, #1 + orr r3, r3, r1, lsl #31 + movw r4, #1953 + adds r3, r3, r4 + ldr r4, haetae_approx_exp_asm_constants+36 + lsr r5, r3, #24 + adc r1, r4, r1, asr #1 + orr r5, r5, r1, lsl #8 + sub r3, r3, r5, lsl #24 + smull r4, r1, r3, r0 + lsrs r4, r4, #24 + orr r4, r4, r1, lsl #8 + asrs r1, r1, #24 + smlal r4, r1, r5, r0 + smlal r4, r1, r3, r2 + adds r0, r4, #0x00800000 + adc r1, r1, #0 + lsrs r0, r0, #24 + orr r0, r0, r1, lsl #8 + asrs r1, r1, #24 + smlal r0, r1, r5, r2 + mvn r9, #3 + adds r0, r0, r9 + adc r1, r8, r1 + pop {r4, r5, r6, r7, r8, r9, r10, fp, pc} + +.ltorg +.align +haetae_approx_exp_asm_constants: + .4byte 16177746 + .4byte -11978293 + .4byte -34944 + .4byte 1308119591 + .4byte -1920242146 + .4byte 1681686157 + .4byte 1451132442 + .4byte -43691 + .4byte -315782 + .4byte -65536 +.size haetae_approx_exp_asm,.-haetae_approx_exp_asm \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/fast_exp_asm.h b/crypto_sign/haetae2/m4f/fast_exp_asm.h new file mode 100644 index 00000000..052b001c --- /dev/null +++ b/crypto_sign/haetae2/m4f/fast_exp_asm.h @@ -0,0 +1,8 @@ +#ifndef FAST_EXP_ASM_H +#define FAST_EXP_ASM_H + +#include "fpa.h" + +fp63_48 haetae_approx_exp_asm(const fp63_48 x); + +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/fast_sampler.S b/crypto_sign/haetae2/m4f/fast_sampler.S new file mode 100644 index 00000000..51f62aad --- /dev/null +++ b/crypto_sign/haetae2/m4f/fast_sampler.S @@ -0,0 +1,94 @@ +.syntax unified +.thumb + +.cpu cortex-m4 +.arch armv7e-m +.fpu fpv4-sp-d16 + + +// This code uses UMULL - which is constant time on the M4, but not on the M3 +// Make sure that this code is never used on an M3 +smlad r0,r0,r0,r0 + + +// ################################################################ +// ############ CONFIGURATION ################### +// ################################################################ + +#define CDT_GAUSS16 cdt_gauss16 + +// ################################################################ +// ############ END CONFIGURATION ################### +// ################################################################ + + +//void haetae_fast_sample_gauss16(const uint64_t rand16); +.global haetae_fast_sample_gauss16 +.type haetae_fast_sample_gauss16,%function +.align +haetae_fast_sample_gauss16: + //bind aliases + rand16x2 .req R0 + accum .req R1 + ptr_cdt .req R2 + ptr_end_cdt .req R7 + ones .req R8 + zeros .req R9 + + //preserve registers + push {R4-R9, R14} + orr rand16x2, rand16x2, rand16x2, lsl #16 + mov accum, #0x00000000 + ldr ptr_cdt, =#CDT_GAUSS16 + mov ones, #0x00010001 + mov zeros, #0x00000000 + add ptr_end_cdt, ptr_cdt, #(2*8*8) + b haetae_fast_sample_gauss16_check +.align +haetae_fast_sample_gauss16_loop: + ldm ptr_cdt!, {R3-R6} + usub16 R3, R3, rand16x2 + sel R3, zeros, ones + uadd16 accum, accum, R3 + usub16 R4, R4, rand16x2 + sel R4, zeros, ones + uadd16 accum, accum, R4 + usub16 R5, R5, rand16x2 + sel R5, zeros, ones + uadd16 accum, accum, R5 + usub16 R6, R6, rand16x2 + sel R6, zeros, ones + uadd16 accum, accum, R6 +haetae_fast_sample_gauss16_check: + cmp ptr_cdt, ptr_end_cdt + blo haetae_fast_sample_gauss16_loop + + add r0, accum, accum, lsr #16 + uxth r0, r0 +// movs r1, #0 // output type changed to fp8_4 (aka int32_t) + + //restore registers + pop {R4-R9, PC} + + //unbind aliases + .unreq rand16x2 + .unreq accum + .unreq ptr_cdt + .unreq ptr_end_cdt + .unreq ones + .unreq zeros + +.ltorg // + +.type cdt_gauss16, %object +.align 4 +cdt_gauss16: +.2byte 3266, 6520, 9748, 12938, 16079, 19159, 22168, 25096 +.2byte 27934, 30674, 33309, 35833, 38241, 40531, 42698, 44742 +.2byte 46663, 48460, 50135, 51690, 53128, 54454, 55670, 56781 +.2byte 57794, 58712, 59541, 60287, 60956, 61554, 62085, 62556 +.2byte 62972, 63337, 63657, 63936, 64178, 64388, 64569, 64724 +.2byte 64857, 64970, 65066, 65148, 65216, 65273, 65321, 65361 +.2byte 65394, 65422, 65444, 65463, 65478, 65490, 65500, 65508 +.2byte 65514, 65519, 65523, 65527, 65529, 65531, 65533, 65534 +.size cdt_gauss16,.-cdt_gauss16 diff --git a/crypto_sign/haetae2/m4f/fast_sampler.h b/crypto_sign/haetae2/m4f/fast_sampler.h new file mode 100644 index 00000000..6da21c51 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fast_sampler.h @@ -0,0 +1,8 @@ +#ifndef FAST_SAMPLER_H +#define FAST_SAMPLER_H + +#include "fpa.h" + +fp8_4 haetae_fast_sample_gauss16(const uint16_t rand16); + +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/fft.c b/crypto_sign/haetae2/m4f/fft.c new file mode 100644 index 00000000..f625ad79 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fft.c @@ -0,0 +1,231 @@ +#include "fft.h" + +static const complex_fp32_16 roots[] = { + {.real = +65536L, .imag = +0L}, {.real = +65531L, .imag = -804L}, + {.real = +65516L, .imag = -1608L}, {.real = +65492L, .imag = -2412L}, + {.real = +65457L, .imag = -3216L}, {.real = +65413L, .imag = -4019L}, + {.real = +65358L, .imag = -4821L}, {.real = +65294L, .imag = -5623L}, + {.real = +65220L, .imag = -6424L}, {.real = +65137L, .imag = -7224L}, + {.real = +65043L, .imag = -8022L}, {.real = +64940L, .imag = -8820L}, + {.real = +64827L, .imag = -9616L}, {.real = +64704L, .imag = -10411L}, + {.real = +64571L, .imag = -11204L}, {.real = +64429L, .imag = -11996L}, + {.real = +64277L, .imag = -12785L}, {.real = +64115L, .imag = -13573L}, + {.real = +63944L, .imag = -14359L}, {.real = +63763L, .imag = -15143L}, + {.real = +63572L, .imag = -15924L}, {.real = +63372L, .imag = -16703L}, + {.real = +63162L, .imag = -17479L}, {.real = +62943L, .imag = -18253L}, + {.real = +62714L, .imag = -19024L}, {.real = +62476L, .imag = -19792L}, + {.real = +62228L, .imag = -20557L}, {.real = +61971L, .imag = -21320L}, + {.real = +61705L, .imag = -22078L}, {.real = +61429L, .imag = -22834L}, + {.real = +61145L, .imag = -23586L}, {.real = +60851L, .imag = -24335L}, + {.real = +60547L, .imag = -25080L}, {.real = +60235L, .imag = -25821L}, + {.real = +59914L, .imag = -26558L}, {.real = +59583L, .imag = -27291L}, + {.real = +59244L, .imag = -28020L}, {.real = +58896L, .imag = -28745L}, + {.real = +58538L, .imag = -29466L}, {.real = +58172L, .imag = -30182L}, + {.real = +57798L, .imag = -30893L}, {.real = +57414L, .imag = -31600L}, + {.real = +57022L, .imag = -32303L}, {.real = +56621L, .imag = -33000L}, + {.real = +56212L, .imag = -33692L}, {.real = +55794L, .imag = -34380L}, + {.real = +55368L, .imag = -35062L}, {.real = +54934L, .imag = -35738L}, + {.real = +54491L, .imag = -36410L}, {.real = +54040L, .imag = -37076L}, + {.real = +53581L, .imag = -37736L}, {.real = +53114L, .imag = -38391L}, + {.real = +52639L, .imag = -39040L}, {.real = +52156L, .imag = -39683L}, + {.real = +51665L, .imag = -40320L}, {.real = +51166L, .imag = -40951L}, + {.real = +50660L, .imag = -41576L}, {.real = +50146L, .imag = -42194L}, + {.real = +49624L, .imag = -42806L}, {.real = +49095L, .imag = -43412L}, + {.real = +48559L, .imag = -44011L}, {.real = +48015L, .imag = -44604L}, + {.real = +47464L, .imag = -45190L}, {.real = +46906L, .imag = -45769L}, + {.real = +46341L, .imag = -46341L}, {.real = +45769L, .imag = -46906L}, + {.real = +45190L, .imag = -47464L}, {.real = +44604L, .imag = -48015L}, + {.real = +44011L, .imag = -48559L}, {.real = +43412L, .imag = -49095L}, + {.real = +42806L, .imag = -49624L}, {.real = +42194L, .imag = -50146L}, + {.real = +41576L, .imag = -50660L}, {.real = +40951L, .imag = -51166L}, + {.real = +40320L, .imag = -51665L}, {.real = +39683L, .imag = -52156L}, + {.real = +39040L, .imag = -52639L}, {.real = +38391L, .imag = -53114L}, + {.real = +37736L, .imag = -53581L}, {.real = +37076L, .imag = -54040L}, + {.real = +36410L, .imag = -54491L}, {.real = +35738L, .imag = -54934L}, + {.real = +35062L, .imag = -55368L}, {.real = +34380L, .imag = -55794L}, + {.real = +33692L, .imag = -56212L}, {.real = +33000L, .imag = -56621L}, + {.real = +32303L, .imag = -57022L}, {.real = +31600L, .imag = -57414L}, + {.real = +30893L, .imag = -57798L}, {.real = +30182L, .imag = -58172L}, + {.real = +29466L, .imag = -58538L}, {.real = +28745L, .imag = -58896L}, + {.real = +28020L, .imag = -59244L}, {.real = +27291L, .imag = -59583L}, + {.real = +26558L, .imag = -59914L}, {.real = +25821L, .imag = -60235L}, + {.real = +25080L, .imag = -60547L}, {.real = +24335L, .imag = -60851L}, + {.real = +23586L, .imag = -61145L}, {.real = +22834L, .imag = -61429L}, + {.real = +22078L, .imag = -61705L}, {.real = +21320L, .imag = -61971L}, + {.real = +20557L, .imag = -62228L}, {.real = +19792L, .imag = -62476L}, + {.real = +19024L, .imag = -62714L}, {.real = +18253L, .imag = -62943L}, + {.real = +17479L, .imag = -63162L}, {.real = +16703L, .imag = -63372L}, + {.real = +15924L, .imag = -63572L}, {.real = +15143L, .imag = -63763L}, + {.real = +14359L, .imag = -63944L}, {.real = +13573L, .imag = -64115L}, + {.real = +12785L, .imag = -64277L}, {.real = +11996L, .imag = -64429L}, + {.real = +11204L, .imag = -64571L}, {.real = +10411L, .imag = -64704L}, + {.real = +9616L, .imag = -64827L}, {.real = +8820L, .imag = -64940L}, + {.real = +8022L, .imag = -65043L}, {.real = +7224L, .imag = -65137L}, + {.real = +6424L, .imag = -65220L}, {.real = +5623L, .imag = -65294L}, + {.real = +4821L, .imag = -65358L}, {.real = +4019L, .imag = -65413L}, + {.real = +3216L, .imag = -65457L}, {.real = +2412L, .imag = -65492L}, + {.real = +1608L, .imag = -65516L}, {.real = +804L, .imag = -65531L}, + {.real = +0L, .imag = -65536L}, {.real = -804L, .imag = -65531L}, + {.real = -1608L, .imag = -65516L}, {.real = -2412L, .imag = -65492L}, + {.real = -3216L, .imag = -65457L}, {.real = -4019L, .imag = -65413L}, + {.real = -4821L, .imag = -65358L}, {.real = -5623L, .imag = -65294L}, + {.real = -6424L, .imag = -65220L}, {.real = -7224L, .imag = -65137L}, + {.real = -8022L, .imag = -65043L}, {.real = -8820L, .imag = -64940L}, + {.real = -9616L, .imag = -64827L}, {.real = -10411L, .imag = -64704L}, + {.real = -11204L, .imag = -64571L}, {.real = -11996L, .imag = -64429L}, + {.real = -12785L, .imag = -64277L}, {.real = -13573L, .imag = -64115L}, + {.real = -14359L, .imag = -63944L}, {.real = -15143L, .imag = -63763L}, + {.real = -15924L, .imag = -63572L}, {.real = -16703L, .imag = -63372L}, + {.real = -17479L, .imag = -63162L}, {.real = -18253L, .imag = -62943L}, + {.real = -19024L, .imag = -62714L}, {.real = -19792L, .imag = -62476L}, + {.real = -20557L, .imag = -62228L}, {.real = -21320L, .imag = -61971L}, + {.real = -22078L, .imag = -61705L}, {.real = -22834L, .imag = -61429L}, + {.real = -23586L, .imag = -61145L}, {.real = -24335L, .imag = -60851L}, + {.real = -25080L, .imag = -60547L}, {.real = -25821L, .imag = -60235L}, + {.real = -26558L, .imag = -59914L}, {.real = -27291L, .imag = -59583L}, + {.real = -28020L, .imag = -59244L}, {.real = -28745L, .imag = -58896L}, + {.real = -29466L, .imag = -58538L}, {.real = -30182L, .imag = -58172L}, + {.real = -30893L, .imag = -57798L}, {.real = -31600L, .imag = -57414L}, + {.real = -32303L, .imag = -57022L}, {.real = -33000L, .imag = -56621L}, + {.real = -33692L, .imag = -56212L}, {.real = -34380L, .imag = -55794L}, + {.real = -35062L, .imag = -55368L}, {.real = -35738L, .imag = -54934L}, + {.real = -36410L, .imag = -54491L}, {.real = -37076L, .imag = -54040L}, + {.real = -37736L, .imag = -53581L}, {.real = -38391L, .imag = -53114L}, + {.real = -39040L, .imag = -52639L}, {.real = -39683L, .imag = -52156L}, + {.real = -40320L, .imag = -51665L}, {.real = -40951L, .imag = -51166L}, + {.real = -41576L, .imag = -50660L}, {.real = -42194L, .imag = -50146L}, + {.real = -42806L, .imag = -49624L}, {.real = -43412L, .imag = -49095L}, + {.real = -44011L, .imag = -48559L}, {.real = -44604L, .imag = -48015L}, + {.real = -45190L, .imag = -47464L}, {.real = -45769L, .imag = -46906L}, + {.real = -46341L, .imag = -46341L}, {.real = -46906L, .imag = -45769L}, + {.real = -47464L, .imag = -45190L}, {.real = -48015L, .imag = -44604L}, + {.real = -48559L, .imag = -44011L}, {.real = -49095L, .imag = -43412L}, + {.real = -49624L, .imag = -42806L}, {.real = -50146L, .imag = -42194L}, + {.real = -50660L, .imag = -41576L}, {.real = -51166L, .imag = -40951L}, + {.real = -51665L, .imag = -40320L}, {.real = -52156L, .imag = -39683L}, + {.real = -52639L, .imag = -39040L}, {.real = -53114L, .imag = -38391L}, + {.real = -53581L, .imag = -37736L}, {.real = -54040L, .imag = -37076L}, + {.real = -54491L, .imag = -36410L}, {.real = -54934L, .imag = -35738L}, + {.real = -55368L, .imag = -35062L}, {.real = -55794L, .imag = -34380L}, + {.real = -56212L, .imag = -33692L}, {.real = -56621L, .imag = -33000L}, + {.real = -57022L, .imag = -32303L}, {.real = -57414L, .imag = -31600L}, + {.real = -57798L, .imag = -30893L}, {.real = -58172L, .imag = -30182L}, + {.real = -58538L, .imag = -29466L}, {.real = -58896L, .imag = -28745L}, + {.real = -59244L, .imag = -28020L}, {.real = -59583L, .imag = -27291L}, + {.real = -59914L, .imag = -26558L}, {.real = -60235L, .imag = -25821L}, + {.real = -60547L, .imag = -25080L}, {.real = -60851L, .imag = -24335L}, + {.real = -61145L, .imag = -23586L}, {.real = -61429L, .imag = -22834L}, + {.real = -61705L, .imag = -22078L}, {.real = -61971L, .imag = -21320L}, + {.real = -62228L, .imag = -20557L}, {.real = -62476L, .imag = -19792L}, + {.real = -62714L, .imag = -19024L}, {.real = -62943L, .imag = -18253L}, + {.real = -63162L, .imag = -17479L}, {.real = -63372L, .imag = -16703L}, + {.real = -63572L, .imag = -15924L}, {.real = -63763L, .imag = -15143L}, + {.real = -63944L, .imag = -14359L}, {.real = -64115L, .imag = -13573L}, + {.real = -64277L, .imag = -12785L}, {.real = -64429L, .imag = -11996L}, + {.real = -64571L, .imag = -11204L}, {.real = -64704L, .imag = -10411L}, + {.real = -64827L, .imag = -9616L}, {.real = -64940L, .imag = -8820L}, + {.real = -65043L, .imag = -8022L}, {.real = -65137L, .imag = -7224L}, + {.real = -65220L, .imag = -6424L}, {.real = -65294L, .imag = -5623L}, + {.real = -65358L, .imag = -4821L}, {.real = -65413L, .imag = -4019L}, + {.real = -65457L, .imag = -3216L}, {.real = -65492L, .imag = -2412L}, + {.real = -65516L, .imag = -1608L}, {.real = -65531L, .imag = -804L}}; + +static inline int32_t _mulrnd16(const int32_t x, const int32_t y) { + int64_t r = ((int64_t)x * (int64_t)y) + (1 << 15); + return r >> 16; +} + +static inline int32_t _complex_mul_real(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.real) - _mulrnd16(x.imag, y.imag); +} + +static inline int32_t _complex_mul_imag(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.imag) + _mulrnd16(x.imag, y.real); +} + +static void _complex_mul(complex_fp32_16 *r, const complex_fp32_16 x, + const complex_fp32_16 y) { + r->real = _complex_mul_real(x, y); + r->imag = _complex_mul_imag(x, y); +} + +const uint16_t brv9[] = { + 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, + 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, + 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, + 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, + 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, + 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, + 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, + 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, + 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, + 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, + 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, + 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, + 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, + 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, + 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, + 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, + 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, + 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, + 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, + 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, + 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, + 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, + 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, + 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, + 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, + 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, + 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, + 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, + 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, + 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 263, + 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, + 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, + 15, 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, + 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, + 255, 511}; + +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x) { + int i, inv_i; + for (i = 0; i < N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = x->coeffs[i] << 16; + } + for (i = N; i < FFT_N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = 0; + } +} + +int32_t complex_fp_sqabs(complex_fp32_16 x) { + return _mulrnd16(x.real, x.real) + _mulrnd16(x.imag, x.imag); +} + +void fft(complex_fp32_16 data[FFT_N]) { + unsigned int r, m, md2, n, k, even, odd, twid; + complex_fp32_16 u, t; + + for (r = 1; r <= FFT_LOGN; r++) { + m = 1 << r; + md2 = m >> 1; + for (n = 0; n < FFT_N; n += m) { + for (k = 0; k < md2; k++) { + even = n + k; + odd = even + md2; + twid = k << (FFT_LOGN - r); + + u = data[even]; + _complex_mul(&t, roots[twid], data[odd]); + data[even].real = u.real + t.real; + data[even].imag = u.imag + t.imag; + data[odd].real = u.real - t.real; + data[odd].imag = u.imag - t.imag; + } + } + } +} diff --git a/crypto_sign/haetae2/m4f/fft.h b/crypto_sign/haetae2/m4f/fft.h new file mode 100644 index 00000000..46a365ce --- /dev/null +++ b/crypto_sign/haetae2/m4f/fft.h @@ -0,0 +1,19 @@ +#ifndef FFT__H +#define FFT__H + +#include "poly.h" +#include + +#define FFT_N 512 +#define FFT_LOGN 9 + +typedef struct { + int32_t real; + int32_t imag; +} complex_fp32_16; + +void fft(complex_fp32_16 data[FFT_N]); +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x); +int32_t complex_fp_sqabs(complex_fp32_16 x); + +#endif diff --git a/crypto_sign/haetae2/m4f/fips202.h b/crypto_sign/haetae2/m4f/fips202.h new file mode 100644 index 00000000..c8dc22fa --- /dev/null +++ b/crypto_sign/haetae2/m4f/fips202.h @@ -0,0 +1,174 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_384_RATE 104 +#define SHA3_512_RATE 72 + + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} shake128incctx; + +// Context for non-incremental API +typedef struct { + uint64_t ctx[25]; +} shake128ctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} shake256incctx; + +// Context for non-incremental API +typedef struct { + uint64_t ctx[25]; +} shake256ctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} sha3_256incctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} sha3_384incctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} sha3_512incctx; + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); +/* Free the state */ +void shake128_ctx_release(shake128ctx *state); +/* Copy the state. */ +void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src); + +void cshake128_simple_absorb(shake128ctx *state, uint16_t cstm, const uint8_t *input, size_t inlen); +void cshake128_simple_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); +void cshake128_simple(uint8_t *output, size_t outlen, uint16_t cstm, const uint8_t *input, size_t inlen); + +/* Initialize incremental hashing API */ +void shake128_inc_init(shake128incctx *state); +/* Absorb more information into the XOF. + * + * Can be called multiple times. + */ +void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); +/* Finalize the XOF for squeezing */ +void shake128_inc_finalize(shake128incctx *state); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); +/* Copy the context of the SHAKE128 XOF */ +void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx *src); +/* Free the context of the SHAKE128 XOF */ +void shake128_inc_ctx_release(shake128incctx *state); + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); +/* Free the context held by this XOF */ +void shake256_ctx_release(shake256ctx *state); +/* Copy the context held by this XOF */ +void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src); + +void cshake256_simple_absorb(shake256ctx *state, uint16_t cstm, const uint8_t *input, size_t inlen); +void cshake256_simple_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); +void cshake256_simple(uint8_t *output, size_t outlen, uint16_t cstm, const uint8_t *input, size_t inlen); + +/* Initialize incremental hashing API */ +void shake256_inc_init(shake256incctx *state); +void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); +/* Prepares for squeeze phase */ +void shake256_inc_finalize(shake256incctx *state); + + + +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); +/* Copy the state */ +void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx *src); +/* Free the state */ +void shake256_inc_ctx_release(shake256incctx *state); + +/* One-stop SHAKE128 call */ +void shake128(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +/* One-stop SHAKE256 call */ +void shake256(uint8_t *output, size_t outlen, + const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_256_inc_init(sha3_256incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state); +/* Copy the context */ +void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_256_inc_ctx_release(sha3_256incctx *state); + +void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_384_inc_init(sha3_384incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state); +/* Copy the context */ +void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_384_inc_ctx_release(sha3_384incctx *state); + +/* One-stop SHA3-384 shop */ +void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_512_inc_init(sha3_512incctx *state); +/* Absorb blocks into SHA3 */ +void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state); +/* Copy the context */ +void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_512_inc_ctx_release(sha3_512incctx *state); + +/* One-stop SHA3-512 shop */ +void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); +#endif diff --git a/crypto_sign/haetae2/m4f/fixpoint.c b/crypto_sign/haetae2/m4f/fixpoint.c new file mode 100644 index 00000000..c1bb0727 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fixpoint.c @@ -0,0 +1,141 @@ +#include "fpa.h" +#include "fixpoint.h" +#include "params.h" +#include +#include + +static void __cneg(fp96_76 *x, const uint8_t sign) { + x->limb48[0] ^= (-(int64_t)sign) & ((1ULL << 48) - 1); + x->limb48[1] ^= -(int64_t)sign; + x->limb48[0] += sign; + renormalize(x); +} + +static void __copy_cneg(fp96_76 *y, const fp96_76 *x, const uint8_t sign) { + y->limb48[0] = ((-(int64_t)sign) & ((1ULL << 48) - 1)) ^ x->limb48[0]; + ; + y->limb48[1] = x->limb48[1] ^ (-(int64_t)sign); + y->limb48[0] += sign; + renormalize(y); +} + +static void fixpoint_mul(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y->limb48[0]); + + // shift right by 48, rounding + xy->limb48[0] = xy->limb48[1] + (((xy->limb48[0] >> 47) + 1) >> 1); + + mul48(tmp, x->limb48[0], y->limb48[1]); + xy->limb48[0] += tmp[0]; + xy->limb48[1] = tmp[1]; + mulacc48(&xy->limb48[0], x->limb48[1], y->limb48[0]); + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + mul64(tmp, x->limb48[1], y->limb48[1]); + xy->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(xy); +} + +static void fixpoint_unsigned_signed_mul(fp96_76 *xy, const fp96_76 *y) { + fp96_76 x, z; + uint8_t sign = (y->limb48[1] >> 63) & 1; + __copy_cneg(&x, y, sign); + fixpoint_mul(&z, &x, xy); + __copy_cneg(xy, &z, sign); +} + +static void fixpoint_sub(fp96_76 *xminy, const fp96_76 *x, const fp96_76 *y) { + fp96_76 yneg; + __copy_cneg(&yneg, y, 1); + fixpoint_add(xminy, x, &yneg); +} + +static void fixpoint_sub_from_threehalves(fp96_76 *x) { + __cneg(x, 1); + x->limb48[1] += 3ULL << 27; // left shift by 28 would be "3" + renormalize(x); +} + +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x) { + uint64_t tmp[2]; + sq48(&sqx->limb48[0], x->limb48[0]); + + // shift right by 48, rounding + //sqx->limb48[0] += 1ULL << 47; + sqx->limb48[0] >>= 48; + sqx->limb48[0] += sqx->limb48[1]; + + // mul + mul48(tmp, x->limb48[0], x->limb48[1]); + sqx->limb48[0] += tmp[0] << 1; + sqx->limb48[1] = tmp[1] << 1; + + // shift right by 28, rounding + //sqx->limb48[0] += 1ULL << 27; + sqx->limb48[0] >>= 28; + sqx->limb48[0] += (sqx->limb48[1] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] >>= 28; + + sq64(tmp, x->limb48[1]); + sqx->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(sqx); +} + +// start_cube = hex(round(2^64/(sqrt((K + L)*N + 2)^3))) +// start_times_threehalfs = hex(round(2^64 * 2/(3 * sqrt((K + L)*N + 2)))) +#if L == 4 +const fp96_76 start_cube = {.limb48 = {0x770077e2e41aULL, 0x1162ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x693861ad937bULL, 0x9caa56ULL}}; +#elif L == 6 +const fp96_76 start_cube = {.limb48 = {0x1a2935cfae68ULL, 0x978ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x7ad215218533ULL, 0x7ff1c9ULL}}; +#elif L == 7 +const fp96_76 start_cube = {.limb48 = {0x700ff3e8890dULL, 0x702ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x5768588eed31ULL, 0x73bd40ULL}}; +#endif + +// implements Newton's method +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf) { + fp96_76 tmp, tmp2; + fixpoint_mul(&tmp, xhalf, &start_cube); // definitely two positive values + fixpoint_sub(invsqrtx, &start_times_threehalves, + &tmp); // first Newton iteration done, might be negative (very + // improbable) + + for (int i = 0; i < 6; i++) // 6 more iterations + { + fixpoint_square(&tmp, invsqrtx); // tmp = y^2, never negative + fixpoint_mul(&tmp2, xhalf, &tmp); // tmp2 = x/2 * y^2, never negative + fixpoint_sub_from_threehalves(&tmp2); // tmp = 3/2 - x/2 * y^2 + fixpoint_unsigned_signed_mul(invsqrtx, &tmp2); // y * (3/2 - x/2 * y^2) + } +} + +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign) { + int64_t res; + fp96_76 tmp, xx; + xx.limb48[1] = x >> 32; + xx.limb48[0] = (x & ((1ULL << 32) - 1)) << 16; + fixpoint_mul(&tmp, &xx, y); + res = (tmp.limb48[1] + (1UL << 14)) >> 15; // rounding + return (1 - 2 * (int32_t)sign) * res; +} + +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + xy->limb48[0] = x->limb48[0] + y->limb48[0]; + xy->limb48[1] = x->limb48[1] + y->limb48[1]; +} diff --git a/crypto_sign/haetae2/m4f/fixpoint.h b/crypto_sign/haetae2/m4f/fixpoint.h new file mode 100644 index 00000000..12ce8a80 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fixpoint.h @@ -0,0 +1,123 @@ +#ifndef FP__H +#define FP__H + +#include "config.h" +#include "fpa.h" +#include +#include + +#ifdef __SIZEOF_INT128__ +__extension__ typedef __int128 int128; +__extension__ typedef unsigned __int128 uint128; +#endif + +#define fixpoint_square HAETAE_NAMESPACE(fixpoint_square) +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x); + +#define fixpoint_newton_invsqrt HAETAE_NAMESPACE(fixpoint_newton_invsqrt) +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf); + +#define fixpoint_mul_rnd13 HAETAE_NAMESPACE(fixpoint_mul_rnd13) +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign); + +#define fixpoint_add HAETAE_NAMESPACE(fixpoint_add) +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y); + +static inline void renormalize(fp96_76 *x) { + x->limb48[1] += x->limb48[0] >> 48; + x->limb48[0] &= (1ULL << 48) - 1; +} + +static inline int64_t smulh48(int64_t a, uint64_t b) { +#ifndef __SIZEOF_INT128__ + int64_t ah = a >> 24; + int64_t al = a - (ah << 24); + int64_t bl = b & ((1<<24)-1); + int64_t bh = b >> 24; + + int64_t res = (al*bl) >> 24; + res += al * bh + ah * bl + (1 << 23); // rounding + res >>= 24; + return res + (ah * bh); +#else + return ((int128)a * (int128)b + (1ULL << 47)) >> 48; // rounding +#endif +} + +static inline void mul64(uint64_t r[2], const uint64_t b, const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), bl = b & ((1ULL << 32) - 1), + ah = a >> 32, bh = b >> 32; + r[0] = a * b; + r[1] = ah * bl + al * bh + ((al * bl) >> 32); + r[1] >>= 32; + r[1] += ah * bh; +#else + uint128 res = ((uint128)a * (uint128)b); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void sq64(uint64_t r[2], const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = ah * al * 2; + r[1] >>= 32; + r[1] += ah * ah; +#else + uint128 res = ((uint128)a * (uint128)a); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void mul48(uint64_t r[2], const uint64_t b, const uint64_t a) { + mul64(r, b, a); + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void mulacc48(uint64_t r[2], const uint64_t b, const uint64_t a) { + uint64_t tmp[2]; + mul48(tmp, b, a); + r[0] += tmp[0]; + r[1] += tmp[1]; +} + +// (a0 + a1*2^32)^2 = a0^2 + 2^33*a0*a1 + 2^64*a1^2 +static inline void sq48(uint64_t r[2], const uint64_t a) { + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = al * ah << 1; + r[1] >>= 32; + r[1] += ah * ah; + + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void fixpoint_mul_high(fp96_76 *xy, const fp96_76 *x, + const uint64_t y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y); // implicitly shifted right by 48 + + mul48(tmp, x->limb48[1], y); + xy->limb48[1] += tmp[0]; + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + xy->limb48[1] += tmp[1] << 20; + + renormalize(xy); +} + +#endif diff --git a/crypto_sign/haetae2/m4f/fp84_76.c b/crypto_sign/haetae2/m4f/fp84_76.c new file mode 100644 index 00000000..913a9406 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fp84_76.c @@ -0,0 +1,282 @@ +#include "fp84_76.h" +#include "fpa.h" +#include "inttypes.h" +#include + +// we only need positive values, the accumulator will be different data type + +void fp_convert_84_76_to_96_76(fp96_76 *dest, const fp84_76 *src){ + uint32_t s0 = src->digit[0]; + uint32_t s1 = src->digit[1]; + uint32_t s2 = src->digit[2]; + + uint64_t d0_mask = ((1ULL<limb48[0] = (((uint64_t) s1 << shmnt84) | s0) & d0_mask; + dest->limb48[1] = (((uint64_t) s2 << shmnt84) | s1) >> d1_shmnt; +} + +static inline uint32_t low_word(int64_t x){ + return (uint32_t) (x & ((1ULL << 32)-1)); +} + +static inline int32_t extract_bits_20_to_27(uint32_t bits){ + // extract bit 20..27 from bits + return (int32_t) ((bits >> 20) & ((1<<8)-1)); +} + +static inline int32_t assemble_8_and_20_bits(int32_t lo_bits, uint32_t hi_bits){ + return (int32_t) ((lo_bits | (hi_bits << 8)) & ((1<<28)-1));; +} + +/********************************************************************** + * Name: fp84_76_square + * Description: Square a normalized, positive, 80-bit value using + * schoolbook multiplication. + * + * Input: + * fp84_76 *x: The value to be squared. + * Output: + * fp84_76 *sqx: The square of x as a positive, normalized + * 84-bit value. + **********************************************************************/ +void fp84_76_square(fp84_76 *sqx, const fp84_76 *x){ + digit28 xl = x->digit[0]; + digit28 xm = x->digit[1]; + digit28 xh = x->digit[2]; + digit28 sl = 0; + digit28 sm = 0; + digit28 sh = 0; + int64_t tmp; + int64_t tmp2; + uint32_t bits; + + tmp = (int64_t) xl * xl; + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) xm * (xl << 1); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) xh * (xl << 1); + tmp += (int64_t) xm * xm; + tmp += (1ULL<<19); // rounding + bits = low_word(tmp); + sl = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp2 = (int64_t) xh * xm; + tmp += tmp2; + tmp += tmp2; + bits = low_word(tmp); + sl = assemble_8_and_20_bits(sl, bits); + sm = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) xh * xh; + bits = low_word(tmp); + sm = assemble_8_and_20_bits(sm, bits); + bits = low_word(tmp >> 20); + sh = bits & ((1<<28)-1); + + sqx->digit[0] = sl; + sqx->digit[1] = sm; + sqx->digit[2] = sh; +} + + +/********************************************************************** + * Name: fp84_76_mul + * Description: Multiply two normalized, positive, 80-bit value using + * schoolbook multiplication. + * + * Input: + * fp84_76 *a: The first factor of the product + * fp84_76 *b: The second factor of the product + * Output: + * fp84_76 *result: The product of a and b. + **********************************************************************/ +void fp84_76_mul(fp84_76 *result, const fp84_76 *a, const fp84_76 *b){ + const digit28 al = a->digit[0]; + const digit28 am = a->digit[1]; + const digit28 ah = a->digit[2]; + const digit28 bl = b->digit[0]; + const digit28 bm = b->digit[1]; + const digit28 bh = b->digit[2]; + digit28 rl = 0; + digit28 rm = 0; + digit28 rh = 0; + int64_t tmp; + uint32_t bits; + + tmp = (int64_t) al * bl; + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) am * bl; + tmp += (int64_t) al * bm; + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) ah * bl; + tmp += (int64_t) am * bm; + tmp += (int64_t) al * bh; + tmp += (1ULL<<19); // rounding + bits = low_word(tmp); + rl = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) ah * bm; + tmp += (int64_t) am * bh; + bits = low_word(tmp); + rl = assemble_8_and_20_bits(rl, bits); + rm = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) ah * bh; + bits = low_word(tmp); + rm = assemble_8_and_20_bits(rm, bits); + bits = low_word(tmp >> 20); + rh = bits & ((1<<28)-1); + + result->digit[0] = rl; + result->digit[1] = rm; + result->digit[2] = rh; +} + +/********************************************************************** + * Name: fp84_76_mul_high + * Description: Multiply two normalized, positive, 80-bit value using + * schoolbook multiplication. + * + * Input: + * fp84_76 *a: The first factor of the product + * fp84_76 *b: The second factor of the product + * Output: + * fp84_76 *result: The product of a and b. + **********************************************************************/ +void fp84_76_mul_high(fp84_76 *result, const fp84_76 *a, const fp8_4 bits_73_to_80){ + const digit28 al = a->digit[0]; // fp_28_76 + const digit28 am = a->digit[1]; // fp_28_48 + const digit28 ah = a->digit[2]; // fp_28_20 + const digit28 bh = bits_73_to_80 << 16; + digit28 rl = 0; + digit28 rm = 0; + digit28 rh = 0; + int64_t tmp; + uint32_t bits; + + tmp = (int64_t) al * bh; + tmp += (1ULL<<19); // rounding + bits = low_word(tmp); + rl = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) am * bh; + bits = low_word(tmp); + rl = assemble_8_and_20_bits(rl, bits); + rm = extract_bits_20_to_27(bits); + tmp >>= FP_84_76_DIGIT_SIZE; + + tmp += (int64_t) ah * bh; + bits = low_word(tmp); + rm = assemble_8_and_20_bits(rm, bits); + bits = low_word(tmp >> 20); + rh = bits & ((1<<28)-1); + + result->digit[0] = rl; + result->digit[1] = rm; + result->digit[2] = rh; +} + +void convert_fp112_76_to_fp96_76(fp96_76 *dest, const fp112_76 *src){ + digit28 src0 = src->digit[0]; + digit28 src1 = src->digit[1]; + digit28 src2 = src->digit[2]; + digit28 src3 = src->digit[3]; + uint64_t dest0; + uint64_t dest1; + + dest0 = (uint64_t) src1 << 28; + dest0 += src0; + dest0 &= ((1ULL<> (FP_96_76_DIGIT_SIZE - FP_112_76_DIGIT_SIZE); // 20 + + dest->limb48[0] = dest0; + dest->limb48[1] = dest1; +} + +void conditional_accumulate_fp112_96(fp112_76 *accum, const fp84_76 *x, int accepted){ + accum->digit[0] += x->digit[0] & -(digit28)accepted; + accum->digit[1] += x->digit[1] & -(digit28)accepted; + accum->digit[2] += x->digit[2] & -(digit28)accepted; + // There are only three digits in x, so the fourth digit + // of accum remains untouched. + return; +} + +void normalize_fp112_96(fp112_76 *x){ + digit28 x0 = x->digit[0]; + digit28 x1 = x->digit[1]; + digit28 x2 = x->digit[2]; + digit28 x3 = x->digit[3]; + digit28 carry; + + carry = x0 >> FP_112_76_DIGIT_SIZE; + x1 += carry; + x0 -= carry << FP_112_76_DIGIT_SIZE; + + carry = x1 >> FP_112_76_DIGIT_SIZE; + x2 += carry; + x1 -= carry << FP_112_76_DIGIT_SIZE; + + carry = x2 >> FP_112_76_DIGIT_SIZE; + x3 += carry; + x2 -= carry << FP_112_76_DIGIT_SIZE; + + x->digit[0] = x0; + x->digit[1] = x1; + x->digit[2] = x2; + x->digit[3] = x3; + return; +} + +void convert_fp96_76_to_fp112_76(fp112_76 *dest, const fp96_76 *src){ + // untested + uint64_t src0 = src->limb48[0]; + uint64_t src1 = src->limb48[1]; + digit28 dest0; + digit28 dest1; + digit28 dest2; + digit28 dest3; + + dest0 = src0 & FP_112_76_DIGIT_MASK; + dest1 = (src0 >> 28) & ((1<<20)-1); + dest1 |= (src1 & ((1<<8)-1)<<20); + dest2 = (src1 >> 8) & FP_112_76_DIGIT_MASK; + dest3 = src1 >> (8+28); + + dest->digit[0] = dest0; + dest->digit[1] = dest1; + dest->digit[2] = dest2; + dest->digit[3] = dest3; + +} + +int32_t first_is_lt_second_fp112_76(const fp112_76 *first, const fp112_76 *second){ + int32_t carry; + int32_t sign; + carry = (first->digit[0] - second->digit[0] ) >> FP_112_76_DIGIT_SIZE; + carry = (first->digit[1] - second->digit[1] + carry) >> FP_112_76_DIGIT_SIZE; + carry = (first->digit[2] - second->digit[2] + carry) >> FP_112_76_DIGIT_SIZE; + sign = (first->digit[3] - second->digit[3] + carry) >> (FP_112_76_WORD_LEN - 1); // 0 or -1 + return sign + 1; +} + +void set_to_zero_112(fp112_76 *x){ + x->digit[0] = 0; + x->digit[1] = 0; + x->digit[2] = 0; + x->digit[3] = 0; +}; \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/fp84_76.h b/crypto_sign/haetae2/m4f/fp84_76.h new file mode 100644 index 00000000..463be7ac --- /dev/null +++ b/crypto_sign/haetae2/m4f/fp84_76.h @@ -0,0 +1,36 @@ +#ifndef FP84_76_H +#define FP84_76_H + +#include "config.h" +#include "fpa.h" + +#define fp76_30_to_48_bit_digits HAETAE_NAMESPACE(fp76_30_to_48_bit_digits) +void fp_convert_84_76_to_96_76(fp96_76 *dest, const fp84_76 *src); + +#define fp84_76_square HAETAE_NAMESPACE(fp84_76_square) +void fp84_76_square(fp84_76 *sqx, const fp84_76 *x); + +#define fp84_76_mul HAETAE_NAMESPACE(fp84_76_mul) +void fp84_76_mul(fp84_76 *result, const fp84_76 *a, const fp84_76 *b); + +#define fp84_76_mul_high HAETAE_NAMESPACE(fp84_76_mul_high) +void fp84_76_mul_high(fp84_76 *result, const fp84_76 *a, const fp8_4 bits_73_to_80); + +#define conditional_accumulate_fp112_96 HAETAE_NAMESPACE(conditional_accumulate_fp112_96) +void conditional_accumulate_fp112_96(fp112_76 *accum, const fp84_76 *x, int accepted); + +#define normalize_fp112_96 HAETAE_NAMESPACE(normalize_fp112_96) +void normalize_fp112_96(fp112_76 *x); + +#define convert_fp112_76_to_fp96_76 HAETAE_NAMESPACE(convert_fp112_76_to_fp96_76) +void convert_fp112_76_to_fp96_76(fp96_76 *dest, const fp112_76 *src); + +#define convert_fp96_76_to_fp112_76 HAETAE_NAMESPACE(convert_fp96_76_to_fp112_76) +void convert_fp96_76_to_fp112_76(fp112_76 *dest, const fp96_76 *src); + +#define first_is_lt_second_fp112_76 HAETAE_NAMESPACE(first_is_lt_second_fp112_76) +int32_t first_is_lt_second_fp112_76(const fp112_76 *first, const fp112_76 *second); + +//#define set_to_zero_112 HAETAE_NAMESPACE(set_to_zero_112) +void set_to_zero_112(fp112_76 *x); +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/fpa.h b/crypto_sign/haetae2/m4f/fpa.h new file mode 100644 index 00000000..da5617c2 --- /dev/null +++ b/crypto_sign/haetae2/m4f/fpa.h @@ -0,0 +1,47 @@ +#ifndef FPA_H +#define FPA_H + +#include + +#define FP_63_48_SCALE (48) +#define FP_63_48_DIGIT_SIZE (24) // bit-length of the digits +#define FP_63_48_WORD_LEN (32) // bit-length of the word the digit is embedded in +#define FP_63_48_WORD_MASK ((1LL << FP_63_48_WORD_LEN) - 1) // corresponding mask + +#define FP_84_76_SCALE (76) +#define FP_84_76_DIGIT_SIZE (28) // bit-length of the digits +#define FP_84_76_DIGIT_MASK ((1 << FP_84_76_DIGIT_SIZE) - 1) // bit-length of the digits +#define FP_84_76_WORD_LEN (32) // bit-length of the word the digit is embedded in + +#define FP_112_76_SCALE (76) +#define FP_112_76_DIGIT_SIZE (28) // bit-length of the digits +#define FP_112_76_DIGIT_MASK ((1 << FP_112_76_DIGIT_SIZE) - 1) // bit-length of the digits +#define FP_112_76_WORD_LEN (32) // bit-length of the word the digit is embedded in + +#define FP_96_76_SCALE (76) +#define FP_96_76_DIGIT_SIZE (48) // bit-length of the digits +#define FP_96_76_WORD_LEN (64) // bit-length of the word the digit is embedded in + + +typedef int32_t digit24; // digit with 24 bits +typedef int32_t digit28; // digit with 30 bits + +typedef int64_t fp63_48; // does not use digits +typedef uint64_t fp63_48_digits; // digits storage container + +typedef int32_t fp8_4; + +typedef struct { + digit28 digit[3]; +} fp84_76; + +typedef struct { + uint64_t limb48[2]; +} fp96_76; + +typedef struct { + digit28 digit[4]; +} fp112_76; + + +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/header_macros.i b/crypto_sign/haetae2/m4f/header_macros.i new file mode 100644 index 00000000..d9eca239 --- /dev/null +++ b/crypto_sign/haetae2/m4f/header_macros.i @@ -0,0 +1,59 @@ +.macro GLOBFUNC name:req,names:vararg +.global \name +.type \name,%function +.ifnb \names +GLOBFUNC \names +.endif +.endm + + + +.macro FUNCTION name:req,names:vararg +GLOBFUNC \name,\names +.func \name,\name +.thumb_func +\name\(): +.endm + + + +.macro ENDFUNC name:req +.pool +.size \name,.-\name +.endfunc +.endm + + + +.macro GLOBOBJ name:req,names:vararg +.global \name +.type \name,%object +.ifnb \names +GLOBOBJ \names +.endif +.endm + + + +.macro OBJECT name:req,names:vararg +GLOBOBJ \name,\names +\name\(): +.endm + + + +.macro ENDOBJ name:req +.size \name,.-\name +.endm + + + +.macro SECTION name:req +.section \name,"ax",%progbits +.endm + + + +.macro .rodata +.section .rodata +.endm diff --git a/crypto_sign/haetae2/m4f/ntt332.S b/crypto_sign/haetae2/m4f/ntt332.S new file mode 100644 index 00000000..22b10166 --- /dev/null +++ b/crypto_sign/haetae2/m4f/ntt332.S @@ -0,0 +1,659 @@ +// based on code by: Markus Krausz (18.03.18) +// date 23.07.21: Now licensed under CC0 with permission of the authors. +/* from Dilithium2 with cosmetic changes */ + +.syntax unified +#include "header_macros.i" +#include "ntt332_macros.i" + +// This code uses UMULL - which is constant time on the M4, but not on the M3 +// Make sure that this code is never used on an M3 +smlad r0,r0,r0,r0 + + +// ################################################################ +// ############ CONFIGURATION ################### +// ################################################################ + +#define CHOICE_OF_PRIME 2 + +#if CHOICE_OF_PRIME == 1 +// Dilithium: + #define FORWARD_NTT_TWIDDLE_TABLE zetas_new332 + #define INVERSE_NTT_TWIDDLE_TABLE zetas_new332inv + #define Q_VALUE 8380417 + #define INVERSE_NEG_Q_VALUE 0xfc7fdfff +#endif /* CHOICE_OF_PRIME == 1 */ + +#if CHOICE_OF_PRIME == 2 +// HAETAE with Q = 64513 = 0xFC01 + #define FORWARD_NTT_TWIDDLE_TABLE twiddles_332_0xFC01 + #define INVERSE_NTT_TWIDDLE_TABLE twiddles_inv332_0xFC01 + #define Q_VALUE 64513 + #define INVERSE_NEG_Q_VALUE 0xC7F0FBFF +#endif /* CHOICE_OF_PRIME == 2 */ + +// ################################################################ +// ############ END CONFIGURATION ################### +// ################################################################ + + +// ############################## +// ########## NTT ########## +// ############################## + +//void haetae_ntt332(int32_t p[N]); +.global haetae_ntt332 +.type haetae_ntt332,%function +.align 2 +haetae_ntt332: + //bind aliases + ptr_p .req R0 + ptr_zeta .req R1 + zeta .req R1 + qinv .req R2 + q .req R3 + cntr .req R4 + pol4 .req R4 + pol0 .req R5 + pol1 .req R6 + pol2 .req R7 + pol3 .req R8 + temp_h .req R9 + temp_l .req R10 + zeta0 .req R11 + zeta1 .req R12 + zeta2 .req R14 + pol5 .req R11 + pol6 .req R12 + pol7 .req R14 + + //preserve registers + push {R4-R11, R14} + + //load constants, ptr + ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed + ldr.w q, inv_ntt_asm_smull_q + + //stage 1 - 3 + .equ distance, 512 + .equ strincr, 4 + + ldr ptr_zeta, =#FORWARD_NTT_TWIDDLE_TABLE + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + add.w temp_l, ptr_p, #32*strincr // 32 iterations + vmov s9, temp_l + 1: + .rept 2 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #strincr + .endr + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne 1b + + sub ptr_p, #32*4 + + // stage 4 - 6 + .equ distance, 64 + add.w temp_l, ptr_p, #8*112+8*4*4 // 8 iterations + vmov s9, temp_l + 1: + add.w temp_l, ptr_p, #4*strincr // 4 iterations + vmov s10, temp_l + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + 2: + .rept 2 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #4 + .endr + vmov temp_l, s10 + cmp.w ptr_p, temp_l + bne 2b + + add.w ptr_p, #112 + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne 1b + + sub ptr_p, #4*4*8+112*8 + vmov ptr_zeta, s0 + //stage 7 and 8 + add cntr, ptr_p, #1024 // 64 iterations + 1: + ldr.w zeta1, [ptr_zeta, #4] //z128,..., z254 + ldr.w zeta2, [ptr_zeta, #8] //z129,..., z255 + ldr zeta0, [ptr_zeta], #12 //z64, ..., z127 + ldr.w pol0, [ptr_p] //1*4 + ldr.w pol1, [ptr_p, #4] + ldr.w pol2, [ptr_p, #8] + ldr.w pol3, [ptr_p, #12] + + _2_layer_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #4] + str.w pol2, [ptr_p, #8] + str.w pol3, [ptr_p, #12] + str pol0, [ptr_p], #16 + + cmp.w cntr, ptr_p + bne.w 1b + + //restore registers + pop {R4-R11, PC} + + //unbind aliases + .unreq ptr_p + .unreq ptr_zeta + .unreq qinv + .unreq q + .unreq cntr + .unreq pol0 + .unreq pol1 + .unreq pol2 + .unreq pol3 + .unreq temp_h + .unreq temp_l + .unreq zeta0 + .unreq zeta1 + .unreq zeta2 + +.ltorg +// ############################## +// ########## NTT^-1 ########## +// ############################## + +//void haetae_invntt332_tomont(int32_t p[N]); +.global haetae_invntt332_tomont +.type haetae_invntt332_tomont,%function +.align 2 +haetae_invntt332_tomont: + //bind aliases + ptr_p .req R0 + ptr_zeta .req R1 + zeta .req R1 + qinv .req R2 + q .req R3 + cntr .req R4 + pol4 .req R4 + pol0 .req R5 + pol1 .req R6 + pol2 .req R7 + pol3 .req R8 + temp_h .req R9 + temp_l .req R10 + zeta0 .req R11 + zeta1 .req R12 + zeta2 .req R14 + pol5 .req R11 + pol6 .req R12 + pol7 .req R14 + + //preserve registers + push {R4-R11, R14} + + //load constants, ptr + ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed + ldr.w q, inv_ntt_asm_smull_q + + //stage 1 - 3 + .equ distance, 16 + .equ strincr, 32 + + ldr ptr_zeta, =#INVERSE_NTT_TWIDDLE_TABLE + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + add.w temp_l, ptr_p, #32*strincr // 32 iterations + vmov s9, temp_l + 1: + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol1, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol3, [ptr_p, #7*distance/4] + _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #strincr + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne.w 1b + + sub ptr_p, #32*strincr + + // stage 4 - 6 + .equ distance, 128 + .equ strincr, 256 + + // iteration 0 + movw temp_l, #4 + add.w temp_l, ptr_p, #4*256 // 4 iterations + vmov s10, temp_l + + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + 2: + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol1, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol3, [ptr_p, #7*distance/4] + _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p] + add.w ptr_p, #strincr + + vmov temp_l, s10 + cmp.w temp_l, ptr_p + bne.w 2b + + sub.w ptr_p, #4*256-4 + + // iteration 1-7 + add.w temp_l, ptr_p, #7*4 // 7 iterations + vmov s9, temp_l + 1: + add.w temp_l, ptr_p, #4*strincr // 4 iterations + vmov s10, temp_l + + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + 2: + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_inv_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p] + add.w ptr_p, #strincr + + vmov temp_l, s10 + cmp.w ptr_p, temp_l + bne 2b + sub.w ptr_p, #4*strincr-4 + + vmov temp_l, s9 + cmp.w temp_l, ptr_p + bne 1b + + sub ptr_p, #8*4 + vmov ptr_zeta, s0 + + //stage 7 and 8 + .equ strincr, 4 + + add.w cntr, ptr_p, #64*strincr // 64 iterations + vmov s9, cntr + 1: + ldr.w zeta1, [ptr_zeta, #4] + ldr.w zeta2, [ptr_zeta, #8] + ldr zeta0, [ptr_zeta], #12 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #256] + ldr.w pol2, [ptr_p, #512] + ldr.w pol3, [ptr_p, #768] + + _2_layer_inv_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l + + ldr.w zeta1, [ptr_zeta, #4] + ldr.w zeta2, [ptr_zeta, #8] + ldr.w zeta0, [ptr_zeta, #12] + ldr.w cntr, [ptr_zeta], #16 + montgomery_mul_32 pol0, cntr, qinv, q, temp_h, temp_l + montgomery_mul_32 pol1, zeta1, qinv, q, temp_h, temp_l + montgomery_mul_32 pol2, zeta2, qinv, q, temp_h, temp_l + montgomery_mul_32 pol3, zeta0, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #256] + str.w pol2, [ptr_p, #512] + str.w pol3, [ptr_p, #768] + str pol0, [ptr_p], #strincr + + vmov cntr, s9 + cmp.w cntr, ptr_p + bne.w 1b + + //restore registers + pop {R4-R11, PC} + + //unbind aliases + .unreq ptr_p + .unreq ptr_zeta + .unreq qinv + .unreq q + .unreq cntr + .unreq pol0 + .unreq pol1 + .unreq pol2 + .unreq pol3 + .unreq temp_h + .unreq temp_l + .unreq zeta0 + .unreq zeta1 + .unreq zeta2 + +.align 2 +inv_ntt_asm_smull_qinv: +.word INVERSE_NEG_Q_VALUE +.align 2 +inv_ntt_asm_smull_q: +.word Q_VALUE + +.section .rodata + + +/********************************************************************** + * zetas in Montgomery domain, reordered for NTT 3+3+2 layers: + * twiddles = reorder332([(R * pow(root,brv(i),q) mod_pm q for i in range(L)]) + * q=64513, root=426, R=2**32, L=256, signed + *********************************************************************/ +.align 2 +OBJECT twiddles_332_0xFC01 +.4byte 26964, -16505, 22229, 30746, 20243, 19064, -31218, 9395 +.4byte -16039, -22946, -22562, -6789, -10049, 9383, -30985, 6241 +.4byte -19553, 16304, -12296, 16446, 18239, 22859, 10681, 22935 +.4byte -1296, -19725, -32076, 11782, -8851, 22431, -29104, -17941 +.4byte 29643, -8577, 7893, 32144, 28147, -27527, -21464, -19646 +.4byte -15130, -2391, 13744, -29133, -20035, 30608, -23970, -16608 +.4byte 19616, 21408, 20143, -11361, -7941, 26533, -19129, 27690 +.4byte 17599, 30820, 25252, 7597, -11459, 10615, -9430, 11591 +.4byte -27989, 3350, 7814, 787, -13857, 12697, 1657, -21224 +.4byte 32114, -7374, -9190, -3761, 2464, 25555, -9604, -3529 +.4byte -28772, 19813, 16588, -15739, 20353, 23475, 13666, 17456 +.4byte 5764, 30980, -16267, 13633, -7401, -19555, -30317, 28847 +.4byte 598, 7682, -11808, -29942, -8796, 14864, 4538, -24162 +.4byte -19194, 835, 689, -1311, 15546, -31332, -16319, 3970 +.4byte 1025, 10971, -27685, -23016, -2648, 1488, -21900, -12543 +.4byte 8311, -25921, 28254, -12442, 28521, -16160, 31352, 12380 +.4byte -12882, -17631, -30332, -16630, 1806, 23439, 7742, -5342 +.4byte 17182, 17494, 9790, 5920, 13642, 29068, 7382, -18166 +.4byte 16507, 21422, -30274, -29051, -28190, 13283, 22131, -20316 +.4byte -9939, 6759, 10672, 21454, 15510, 6080, -17374, -14941 +.4byte -29735, -25912, 28710, -10170, 3808, 1160, 10639, -26985 +.4byte -31327, -10865, 25636, 24985, 17261, -26851, 11261, -8253 +.4byte -3304, -10623, 18282, -2202, -27727, -31368, -22243, 21502 +.4byte 13882, 12069, 18731, -11242, -7729, -16186, -10226, 1761 +.4byte -4127, -27298, -4800, -18832, -17737, -22805, 12050, -3528 +.4byte 65, -14501, 10770, 8908, 7929, -23751, 26934, 29563 +.4byte 21921, -27010, -31064, -21944, 8889, 5913, -1035, 23224 +.4byte 5322, -9488, -5823, -16405, -994, -20206, 2844, 7655 +.4byte -16251, 29439, -22820, -27740, 5876, 15822, 23078, -9522 +.4byte 13803, -8099, -18586, 2931, 9217, -9874, -21126, -14203 +.4byte 23844, 25492, -12831, 30362, 7947, 17463, -21442, -12979 +.4byte 29003, 9560, 31612, 26554, 17671, 8241, -20175 +ENDOBJ twiddles_332_0xFC01 + +/********************************************************************** + * zetas in Montgomery domain, reordered for inverse NTT 3+3+2 layers: + * q=64513, root=426, R=2**32, L=256, signed + *********************************************************************/ +.align 2 +OBJECT twiddles_inv332_0xFC01 +.4byte 14321, 14321, -26964, 14321, -22229, -26964, 16505 +.4byte 14321, 14321, -26964, 14321, -22229, -26964, 16505 +.4byte 31218, -17599, -21408, -25252, 11361, -30820, -20143 +.4byte -22229, 31218, -19064, -17599, -13744, -21408, -32144 +.4byte -20243, 8851, -22859, 29104, -22935, -22431, -10681 +.4byte -26964, -22229, 16505, 31218, -20243, -19064, -30746 +.4byte -19064, -13744, -32144, 20035, 27527, 29133, -28147 +.4byte 16505, -20243, -30746, 8851, 30985, -22859, -9395 +.4byte -30746, 30985, -9395, 19553, 22946, -6241, 16039 +.4byte 14321, 14321, -26964, -29720, 15742, -19565, 25927 +.4byte 9430, -17671, -9560, -24300, 4883, -1106, 20808 +.4byte -25252, 9430, -10615, 17207, -2563, -28776, -22667 +.4byte -7893, -15510, -6759, 4735, 21044, 30826, 27963 +.4byte -17599, -25252, -30820, -18313, 23371, -11437, 17784 +.4byte -19616, -7929, 14501, 31002, 20802, 16480, -25400 +.4byte 29104, -7893, 8577, -15374, 4592, 6702, 25685 +.4byte -18239, -15546, -835, 22074, -3018, 1833, 2029 +.4byte 31218, -17599, -21408, 31854, -29992, 26809, 18026 +.4byte -27690, -5876, -29439, -15372, 28703, 13541, -6621 +.4byte 20035, -19616, 16608, -30021, 32021, 15630, -15008 +.4byte -11782, -1806, 17631, -22332, -10677, 19118, -27900 +.4byte 8851, 29104, -22431, -20951, 25871, -258, -13695 +.4byte 2391, 27727, 10623, -26551, -4331, 10903, -4121 +.4byte 19553, -18239, -16446, -24444, 10742, 22590, 24372 +.4byte -9383, -20353, -19813, 26293, -9364, 10048, -21750 +.4byte -22229, 31218, -19064, -29166, -14863, 3961, -20041 +.4byte 11459, -23844, 9874, -3703, -30777, 14396, 11008 +.4byte 11361, -27690, 19129, -25299, -6887, -30254, 29405 +.4byte -29643, -16507, -29068, 7664, 10736, 14770, 3855 +.4byte -13744, 20035, 29133, -24818, 17895, -30556, 1372 +.4byte 23970, 4127, 16186, 26595, 18669, 10529, 3032 +.4byte -22935, -11782, 32076, -24925, -14040, 22892, -12108 +.4byte 12296, -598, 19555, 7362, -17297, 14289, -20927 +.4byte -20243, 8851, -22859, -29059, 17072, 15026, -6561 +.4byte -26533, -5322, -5913, 15530, 5189, 10636, -29546 +.4byte 27527, 2391, 15130, -21165, 26514, -22388, 23858 +.4byte 19725, -8311, -1488, -504, -11750, 18423, 12474 +.4byte 30985, 19553, -6241, 31801, 8453, 6858, -29047 +.4byte 19646, 31327, -1160, -21884, -28905, 2742, 25525 +.4byte 22946, -9383, 10049, -13378, 4021, -6354, -23716 +.4byte 6789, -32114, -12697, 28742, -142, 29970, 30535 +.4byte -26964, -22229, 16505, 16120, 21504, 28238, -11892 +.4byte -10615, 21442, -30362, 29417, -23574, -16592, 29957 +.4byte -30820, 11459, -7597, 13850, 9031, 7533, 12034 +.4byte 8577, -22131, 29051, -1179, 11682, 472, 13052 +.4byte -21408, 11361, -20143, -30442, 20926, 27563, 11540 +.4byte 16608, -12050, 18832, 8712, 352, -14322, -22083 +.4byte -22431, -29643, 17941, 30914, -7874, -26384, -23222 +.4byte -16446, -4538, 29942, 18851, 11188, -19749, 1157 +.4byte -19064, -13744, -32144, 19277, -14209, 17672, 22870 +.4byte 19129, -2844, 16405, 19278, 30103, -11165, 6717 +.4byte 29133, 23970, -30608, 25487, 15366, 27990, 30455 +.4byte 32076, -31352, 12442, -1606, -7233, -8112, 7492 +.4byte -22859, -22935, -10681, 27861, -8649, 17245, 3955 +.4byte 15130, -11261, -24985, 29596, -26825, -17375, -22858 +.4byte -6241, 12296, -16304, 28540, 16141, -15639, 3278 +.4byte 10049, 9604, 3761, -12351, 30780, -10486, 31507 +.4byte 16505, -20243, -30746, 18598, 25514, -13957, 23547 +.4byte -7597, 18586, 9522, -3288, -27502, -18054, 16865 +.4byte -20143, -26533, 7941, -29084, 5993, 26308, 10186 +.4byte 17941, -9790, 5342, -10669, -13464, -544, 22134 +.4byte -32144, 27527, -28147, 11030, 10872, -23020, 17316 +.4byte -30608, -18731, -21502, -27536, 23650, 29628, -28127 +.4byte -10681, 19725, 1296, -11574, 11262, -30824, -3852 +.4byte -16304, 16267, -17456, 4516, -6334, 23855, 17255 +.4byte -30746, 30985, -9395, -23311, 25124, -6153, -19798 +.4byte 7941, 31064, -29563, 29173, 2482, -12281, -28517 +.4byte -28147, 19646, 21464, -17347, -7869, 1637, 26132 +.4byte 1296, 27685, -3970, 29187, -22280, -28921, 3393 +.4byte -9395, 22946, 16039, 5066, -20648, -30810, -28614 +.4byte 21464, -28710, 14941, -27550, -16101, -18245, 4476 +.4byte 16039, 6789, 22562, 30526, 24041, 1623, -13619 +.4byte 22562, -7814, -11591, -3260, -12513, 13179, 16172 +ENDOBJ twiddles_inv332_0xFC01 + + +.type zetas_new332, %object +.align 2 +zetas_new332: +.word 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347 +.word 2725464, 1024112, 2706023, 95776, 3077325, 3530437, 2353451, -1079900 +.word 3585928, -1661693, -3592148, -2537516, 3915439, -359251, -549488, -1119584 +.word -3861115, -3043716, 3574422, -2867647, -2091905, 2619752, -2108549, 3539968 +.word -300467, 2348700, -539299, 3119733, -2118186, -3859737, -1699267, -1643818 +.word 3505694, -3821735, -2884855, -1399561, -3277672, 3507263, -2140649, -1600420 +.word 3699596, 3111497, 1757237, -19422, 811944, 531354, 954230, 3881043 +.word 2680103, 4010497, 280005, 3900724, -2556880, 2071892, -2797779, -3930395 +.word 2091667, 3407706, -1528703, 2316500, 3817976, -3677745, -3342478, 2244091 +.word -3041255, -2446433, -3562462, -1452451, 266997, 2434439, 3475950, -1235728 +.word 3513181, 2176455, -3520352, -3759364, -1585221, -1197226, -3193378, -1257611 +.word 900702, 1859098, 1939314, 909542, 819034, -4083598, 495491, -1613174 +.word -1000202, -43260, -522500, -3190144, -655327, -3122442, -3157330, 2031748 +.word 3207046, -3632928, -3556995, -525098, 126922, -768622, -3595838, 3412210 +.word 342297, 286988, -983419, -2437823, 4108315, 2147896, 3437287, -3342277 +.word 2715295, 1735879, 203044, -2967645, 2842341, 2691481, -3693493, -2590150 +.word 1265009, -411027, 4055324, 1247620, -2477047, 2486353, 1595974, -671102 +.word -3767016, 1250494, -1228525, 2635921, -3548272, -22981, -2994039, 1869119 +.word -1308169, 1903435, -1050970, -381987, -1333058, 1237275, 1349076, -3318210 +.word -1430225, 1852771, -451100, 1312455, -1430430, 3306115, -1962642, -3343383 +.word -1279661, 1917081, 264944, -2546312, -1374803, 508951, 1500165, 777191 +.word 3097992, 2235880, 3406031, 44288, -542412, -2831860, -1100098, -1671176 +.word -1846953, 904516, -2584293, -3724270, 3958618, 594136, -3776993, -3724342 +.word -2013608, 2432395, -8578, 2454455, -164721, 1653064, 1957272, 3369112 +.word -3249728, 185531, -1207385, 2389356, -3183426, 162844, -210977, 1616392 +.word 3014001, 759969, 810149, 1652634, -1316856, -3694233, -1799107, 189548 +.word -3038916, 3523897, -3553272, 3866901, 269760, 3159746, 2213111, -975884 +.word -1851402, 1717735, 472078, -2409325, -426683, 1723600, -177440, -1803090 +.word 1910376, 1315589, -1667432, -1104333, 1341330, -260646, -3833893, 1285669 +.word -2939036, -2235985, -1584928, -420899, -2286327, -812732, 183443, -976891 +.word -1439742, 1612842, -3545687, -3019102, -554416, 3919660, -3881060, -48306 +.word -1362209, -3628969, 3937738, 1400424, 3839961, -846154, 1976782 +.size zetas_new332,.-zetas_new332 + +.type zetas_new332inv, %object +.align 2 +zetas_new332inv: +.word 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894 +.word 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894 +.word -466468, -2680103, -3111497, -280005, 19422, -4010497, -1757237 +.word 518909, -466468, 876248, -2680103, 2884855, -3111497, -3119733 +.word 777960, 2091905, 359251, 2108549, 1119584, -2619752, 549488 +.word -25847, 518909, 2608894, -466468, 777960, 876248, -237124, 876248 +.word 2884855, -3119733, 3277672, 3859737, 1399561, 2118186, 2608894 +.word 777960, -237124, 2091905, -2353451, 359251, -1826347, -237124 +.word -2353451, -1826347, -3585928, -1024112, 1079900, -2725464, 4193792 +.word 4193792, -25847, 41978, 3024400, 3975713, -1225192, 2797779 +.word -3839961, 3628969, -1711436, 3835778, 485110, -3954267, -280005 +.word 2797779, -2071892, -2831100, -2698859, -908040, -2292170, 539299 +.word 1430430, -1852771, -3658785, 3512212, 1859141, -1607594, -2680103 +.word -280005, -4010497, 715005, 1483994, -1045894, -980943, -3699596 +.word 1316856, -759969, -955715, 3677139, 3933849, 2719610, 2108549 +.word 539299, -2348700, 1658328, -1403403, 1775852, -2460465, -3915439 +.word -126922, 3632928, 1067023, 3847594, 4179270, 1652689, -466468 +.word -2680103, -3111497, -2953811, -284642, 2507426, -324139, -3881043 +.word -1341330, -1315589, 3990128, -2137097, -4109898, 4092021, 3277672 +.word -3699596, 1600420, 1541634, 3493410, 3487504, 2497815, 2867647 +.word 2477047, 411027, 1654972, 1326223, -2608226, -2752209, 2091905 +.word 2108549, -2619752, 1836700, 2945615, -1908953, 729864, 3821735 +.word -3958618, -904516, 2080615, 1555380, -3471815, -1978758, -3585928 +.word -3915439, 2537516, -892788, -553664, -3095038, 658596, -3530437 +.word 1585221, -2176455, 3355482, -1783485, 2780552, -3623330, 518909 +.word -466468, 876248, -442683, 2523147, -2847660, -3683140, 2556880 +.word 1439742, 812732, 774207, -3168108, 1877157, 3406477, 19422, -3881043 +.word -954230, -214686, -1182619, 2453526, -2201920, 300467, 1308169 +.word 22981, 3614022, 2136260, 1459487, -2233803, 2884855, 3277672 +.word 1399561, 394072, -3933227, 4136064, 156486, 2140649, 3249728 +.word -1653064, 1596950, 633578, 2722529, -554462, 1119584, 2867647 +.word -3574422, 1004840, 191586, 3969463, 1161373, 3592148, 1000202 +.word 4083598, 3189243, 3561667, -3650125, 3490511, 777960, 2091905 +.word 359251, -1829156, -3707725, -661807, 1144558, -531354, 1851402 +.word -3159746, 1543095, -2903948, 1505516, -1500460, 3859737, 3821735 +.word -3505694, -2413330, 3908886, -1203856, 3570263, 3043716, -2715295 +.word -2147896, 758741, 3917553, -2414897, -1613811, -2353451, -3585928 +.word 1079900, 990020, -719638, 2718792, 2260310, 1643818, -3097992 +.word -508951, -783456, -2089539, 2616547, 4060031, -1024112, -3530437 +.word -3077325, -1821861, 1920615, 3988525, 2048419, -95776, 3041255 +.word 3677745, -971504, 2190617, 2311312, -1170082, -25847, 518909 +.word 2608894, 1261528, -2073537, -959585, 3948120, -2071892, 3881060 +.word 3019102, -1342633, -1115066, 3589694, -1929116, -4010497, 2556880 +.word -3900724, 3360006, 1758630, -2306989, -1841637, -2348700, -1349076 +.word 381987, -1699982, 3189673, 3531558, -1210546, -3111497, 19422 +.word -1757237, 2977353, 2612035, -2718155, -1544829, 1600420, 210977 +.word -2389356, 2052582, -2737802, 2383976, -450259, -2619752, 300467 +.word -3539968, 1698289, -4065084, -644023, -1114140, 2537516, 3157330 +.word 3190144, -993399, -2220524, 2920588, 252737, 876248, 2884855 +.word -3119733, 1490985, -34731, -1212610, -3183745, -954230, 177440 +.word 2409325, -3302554, -2390327, -2749545, 653128, 1399561, 2140649 +.word -3507263, -3745105, -1942293, -3367121, 2734884, -3574422, 3693493 +.word 2967645, 1393803, -2467905, 1786029, -1633410, 359251, 1119584 +.word 549488, -2824548, -1325638, -2207625, -2601586, -3505694, 1100098 +.word -44288, 3478676, -2457992, -1617107, 2551364, 1079900, 3592148 +.word 1661693, 1593929, 318899, -3366475, 3118416, -3077325, -3475950 +.word 1452451, 3772814, 1424805, -3391376, 632820, 2608894, 777960 +.word -237124, 2062597, 4064335, 2197148, -1127864, -3900724, 1584928 +.word -1285669, 2525341, -896437, -1915773, 1792087, -1757237, -531354, -811944 +.word 938441, -674578, 2876837, 3959371, -3539968, 1228525, 671102 +.word 1219592, -3853560, 2630979, -2134676, -3119733, 3859737, 2118186 +.word -2432637, 2746655, 718593, -2353280, -3507263, 8578, 3724342 +.word -34852, 1387945, 358956, 1604944, 549488, 3043716, 3861115 +.word 1290746, 3208584, 2538711, -1442830, 1661693, -1939314, 1257611 +.word -367371, -1308058, 264382, 2614173, -237124, -2353451, -1826347, 2050674 +.word 592050, -138487, 2310528, -811944, 3553272, -189548, -2728561 +.word -4168358, -79, 3844932, 2118186, 1643818, 1699267, 500408 +.word 743398, 879633, -3105206, 3861115, 983419, -3412210, 712597 +.word -23479, 3729381, -1010481, -1826347, -1024112, -2725464, -2361217 +.word -1864453, 3850522, 2337144, 1699267, -264944, 3343383, 3842267 +.word 4181974, -4032642, 3983585, -2725464, -95776, -2706023, 260345 +.word 2526550, 2000777, 987079, -2706023, 1528703, 3930395, -3030761 +.word -3082055, -2374824, 1836319 +.size zetas_new332inv,.-zetas_new332inv diff --git a/crypto_sign/haetae2/m4f/ntt332.h b/crypto_sign/haetae2/m4f/ntt332.h new file mode 100644 index 00000000..dd88cb56 --- /dev/null +++ b/crypto_sign/haetae2/m4f/ntt332.h @@ -0,0 +1,14 @@ +#ifndef NTT332_H +#define NTT332_H + +#include "params.h" +#include + +#if N != 256 +#error "NTT332: Only N==256 is supported." +#endif + +void haetae_ntt332(int32_t poly[N]); +void haetae_invntt332_tomont(int32_t poly[N]); + +#endif /* NTT332_H */ \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/ntt332_macros.i b/crypto_sign/haetae2/m4f/ntt332_macros.i new file mode 100644 index 00000000..1c8b9512 --- /dev/null +++ b/crypto_sign/haetae2/m4f/ntt332_macros.i @@ -0,0 +1,193 @@ +/* from Dilithium2 */ + +#ifndef MACROS_I +#define MACROS_I +// 3 +.macro montgomery_mul_32 a, b, Qprime, Q, tmp, tmp2 + smull \tmp, \a, \a, \b + mul \tmp2, \tmp, \Qprime + smlal \tmp, \a, \tmp2, \Q +.endm + +// 2 +.macro addSub1 c0, c1 + add.w \c0, \c1 + sub.w \c1, \c0, \c1, lsl #1 +.endm + +// 3 +.macro addSub2 c0, c1, c2, c3 + add \c0, \c1 + add \c2, \c3 + sub.w \c1, \c0, \c1, lsl #1 + sub.w \c3, \c2, \c3, lsl #1 +.endm + +// 6 +.macro addSub4 c0, c1, c2, c3, c4, c5, c6, c7 + add \c0, \c1 + add \c2, \c3 + add \c4, \c5 + add \c6, \c7 + sub.w \c1, \c0, \c1, lsl #1 + sub.w \c3, \c2, \c3, lsl #1 + sub.w \c5, \c4, \c5, lsl #1 + sub.w \c7, \c6, \c7, lsl #1 +.endm + +.macro _2_layer_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 + montgomery_mul_32 \c2, \zeta0, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 + + montgomery_mul_32 \c1, \zeta1, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c1, \c2, \c3 +.endm + +.macro _2_layer_inv_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 + montgomery_mul_32 \c1, \zeta0, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c1, \c2, \c3 + + montgomery_mul_32 \c2, \zeta1, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 +.endm + +.macro _3_layer_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + vmov.w \twiddle, \xi0 + montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 + + vmov.w \twiddle, \xi1 + montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 + + vmov.w \twiddle, \xi3 + montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi4 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi5 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi6 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 +.endm + +.macro _3_layer_inv_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + vmov.w \twiddle, \xi0 + montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 + + vmov.w \twiddle, \xi1 + montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 + + vmov.w \twiddle, \xi3 + montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi4 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi5 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi6 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 +.endm + +/************************************************************ +* Name: _3_layer_inv_butterfly_light_fast_first +* +* Description: upper half of 3-layer inverse butterfly +* defined over X^8 - 1 +* +* Input: (c4, c1, c6, c3) = coefficients on the upper half; +* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = +* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in +* Montgomery domain +* +* Symbols: R = 2^32 +* +* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD +* +* Output: +* c4 = c4 + c1 + (c6 + c3) +* c5 = (c4 - c1) w_4 + (c6 + c3) w_8^3 +* c6 = c4 + c1 - (c6 + c3) +* c7 = (c4 - c1) w_8^3 + (c6 + c3) w_4 +************************************************************/ +// 15 +.macro _3_layer_inv_butterfly_light_fast_first c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + addSub2 \c4, \c1, \c6, \c3 + addSub1 \c4, \c6 + + vmov.w \tmp, \xi4 + vmov.w \tmp2, \xi6 + + smull.w \c0, \c5, \c1, \tmp + smlal.w \c0, \c5, \c3, \tmp2 + mul.w \twiddle, \c0, \Qprime + smlal.w \c0, \c5, \twiddle, \Q + + smull.w \c2, \c7, \c1, \tmp2 + smlal.w \c2, \c7, \c3, \tmp + mul.w \twiddle, \c2, \Qprime + smlal.w \c2, \c7, \twiddle, \Q +.endm + +/************************************************************ +* Name: _3_layer_inv_butterfly_light_fast_second +* +* Description: lower half of 3-layer inverse butterfly +* defined over X^8 - 1, and the 2nd +* layer of butterflies +* +* Input: +* (c4, c5, c6, c7) = results of the upper half; +* (c0, c1, c2, c3) = coefficients on the lower half; +* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = +* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in +* Montgomery domain +* +* Symbols: R = 2^32 +* +* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD +* +* Output: (normal order) +* c0 = c0 + c1 + (c2 + c3) + ( c4 + c5 + (c6 + c7) ) +* c1 = (c0 - c1) w3 + (c2 - c3) w4 + ( (c4 - c5) w5 + (c6 - c7) w6 ) +* c2 = ( c0 + c1 - (c2 + c3)) w1 + (( c4 + c5 - (c6 + c7) ) w2) +* c3 = ((c0 - c1) w3 - (c2 - c3) w4) w1 + (((c4 - c5) w5 - (c6 - c7) w6) w2) +* c4 = c0 + c1 - (c2 + c3) - ( c4 + c5 + (c6 + c7) ) w0 +* c5 = (c0 - c1) w3 + (c2 - c3) w4 - ( (c4 - c5) w5 + (c6 - c7) w6 ) w0 +* c6 = ( c0 + c1 - (c2 + c3)) w1 - (( c4 + c5 - (c6 + c7) ) w2) w0 +* c7 = ((c0 - c1) w3 - (c2 - c3) w4) w1 - (((c4 - c5) w5 - (c6 - c7) w6) w2) w0 +************************************************************/ +// 19 +.macro _3_layer_inv_butterfly_light_fast_second c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + addSub2 \c0, \c1, \c2, \c3 + + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 + + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 +.endm + +#endif /* MACROS_I */ diff --git a/crypto_sign/haetae2/m4f/packing.c b/crypto_sign/haetae2/m4f/packing.c new file mode 100644 index 00000000..e88ce939 --- /dev/null +++ b/crypto_sign/haetae2/m4f/packing.c @@ -0,0 +1,266 @@ +#include "packing.h" +#include "encoding.h" +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: pack_pk + * + * Description: Bit-pack public key pk = (seed, b). + * + * Arguments: - uint8_t pk[]: output byte array + * - const polyveck *b: polynomial vector of length K containg b + * - const uint8_t seed[]: seed for A' + **************************************************/ +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, + const uint8_t seed[SEEDBYTES]) { + unsigned int i; + + memcpy(pk, seed, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_pack(pk + i * POLYQ_PACKEDBYTES, &b->vec[i]); + } +} + +/************************************************* + * Name: unpack_pk + * + * Description: Unpack public key pk = (seed, b). + * + * Arguments: - uint8_t seed[]: seed for A' + * - polyveck *b: polynomial vector of length K containg b + * - const uint8_t pk[]: output byte array + **************************************************/ +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) { + unsigned int i; + + memcpy(seed, pk, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_unpack(&b->vec[i], pk + i * POLYQ_PACKEDBYTES); + } +} + +/************************************************* + * Name: pack_sk + * + * Description: Bit-pack secret key sk = (pk, s). + * + * Arguments: - uint8_t sk[]: output byte array + * - const uint8_t pk[PUBLICKEYBYTES]: packed pk + * - const polyvecl *s0: polyvecl pointer containing s0 (encoding + *starting at offset 1) + * - const polyveck *s1: polyveck pointer containing s1 + **************************************************/ +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, + const polyveck *s1, const uint8_t key[SEEDBYTES]) { + unsigned int i; + memcpy(sk, pk, CRYPTO_PUBLICKEYBYTES); + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s0->vec[i]); + + sk += (L - 1) * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_pack(sk + i * POLY2ETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(sk, key, SEEDBYTES); +} + +/************************************************* + * Name: unpack_sk + * + * Description: Unpack secret key sk = (A, s). + * + * Arguments: - polyvecl A[K]: output polyvecl array for A + * - polyvecl s0: output polyvecl pointer for s0 + * - polyveck s1: output polyveck pointer for s1 + * - const uint8_t sk[]: byte array containing bit-packed sk + **************************************************/ +void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { + unsigned int i; + + +#ifdef ENABLE_SIGNATURE_MATRIX_BUFFER + // Expand matrix A, if buffer is enabled. Otherwise + // the matrix elements will be computed (repeatedly) + // on demand. + for (size_t row = 0; row < K; row++) + for (size_t column = 0; column < L; column++) + expand_pk_matrix_elem_frozen(&A[row].vec[column], row, column, sk); +#else + // TODO: Remove A[K] from the unpack_sk() signature, if A[K] is not bufferd + { + // This block is introduced only to avoid the compiler warning + // that A[K] is not being used if ENABLE_SIGNATURE_MATRIX_BUFFER + // is not defined. Beware, in this case A[0] points to + // the start of the secret key. See initialization in + // crypto_sign_signature() + int32_t dummy; + dummy = A[K].vec[0].coeffs[0]; + A[K].vec[0].coeffs[0] = dummy; + } +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_unpack(&s0->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += M * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_unpack(&s1->vec[i], sk + i * POLY2ETA_PACKEDBYTES); + + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_unpack(&s1->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(key, sk, SEEDBYTES); + +} + +/************************************************* + * Name: pack_sig + * + * Description: Bit-pack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - uint8_t sig[]: output byte array + * - const uint8_t c_seed[]: pointer to seed of challenge + * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of + *length L + * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of + *length L + * - const polyveck *h: pointer t vector h of length K + * Returns 1 in case the signature size is above the threshold; otherwise 0. + **************************************************/ +int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], + const polyvecl *lowbits_z1, const polyvecl *highbits_z1, + const polyveck *h) { + + uint8_t encoded_h[N * K]; + uint8_t encoded_hb_z1[N * L]; + uint16_t size_enc_h, size_enc_hb_z1; + uint8_t offset_enc_h, offset_enc_hb_z1; + + // init/padding with zeros: + memset(sig, 0, CRYPTO_BYTES); + + memcpy(sig, c_seed, SEEDBYTES); + sig += SEEDBYTES; + + for (int i = 0; i < L; ++i) + poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); + sig += L * N; + + size_enc_hb_z1 = + encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]); + size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]); + + if(size_enc_h == 0 || size_enc_hb_z1 == 0) { + return 1; // encoding failed + } + + // The size of the encoded h and HB(z1) does not always fit in one byte, + // thus we output a one byte offset to a fixed baseline + if(size_enc_h < BASE_ENC_H || size_enc_hb_z1 < BASE_ENC_HB_Z1 || + size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { + return 1; // encoding size offset out of range + } + + offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; + offset_enc_h = size_enc_h - BASE_ENC_H; + + if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > + CRYPTO_BYTES) { + return 1; // signature too big + } + + sig[0] = offset_enc_hb_z1; + sig[1] = offset_enc_h; + sig += 2; + + memcpy(sig, encoded_hb_z1, size_enc_hb_z1); + sig += size_enc_hb_z1; + + memcpy(sig, encoded_h, size_enc_h); + sig += size_enc_h; + + return 0; +} + +/************************************************* + * Name: unpack_sig + * + * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - uint8_t c_seed[]: pointer to output seed of challenge + * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) + * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) + * - polyveck *h: pointer to output vector h + * - const uint8_t sig[]: byte array containing + * bit-packed signature + * + * Returns 1 in case of malformed signature; otherwise 0. + **************************************************/ +int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, + polyvecl *highbits_z1, polyveck *h, + const uint8_t sig[CRYPTO_BYTES]) { + + uint16_t size_enc_hb_z1, size_enc_h; + + memcpy(c_seed, sig, SEEDBYTES); + sig += SEEDBYTES; + + for (unsigned int i = 0; i < L; ++i) + poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); + sig += L * N; + + size_enc_hb_z1 = (uint16_t)sig[0] + BASE_ENC_HB_Z1; + size_enc_h = (uint16_t)sig[1] + BASE_ENC_H; + sig += 2; + + if(CRYPTO_BYTES < (2 + L*N + SEEDBYTES + size_enc_h + size_enc_hb_z1)) + return 1; // invalid size_enc_h and/or size_enc_hb_z1 + + if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { + return 1; // decoding failed + } + + sig += size_enc_hb_z1; + + if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { + return 1; // decoding failed + } + + sig += size_enc_h; + + for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) + if(sig[i] != 0) return 1; // verify zero padding + + return 0; +} diff --git a/crypto_sign/haetae2/m4f/packing.h b/crypto_sign/haetae2/m4f/packing.h new file mode 100644 index 00000000..b000218e --- /dev/null +++ b/crypto_sign/haetae2/m4f/packing.h @@ -0,0 +1,26 @@ +// clang-format off +#ifndef HAETAE_PACKING_H +#define HAETAE_PACKING_H + +#include "params.h" +#include "polyvec.h" +#include + +#define pack_pk HAETAE_NAMESPACE(pack_pk) +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, const uint8_t seed[SEEDBYTES]); +#define unpack_pk HAETAE_NAMESPACE(unpack_pk) +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define pack_sk HAETAE_NAMESPACE(pack_sk) +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); +#define unpack_sk HAETAE_NAMESPACE(unpack_sk) +void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +#define pack_sig HAETAE_NAMESPACE(pack_sig) +int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); +#define unpack_sig HAETAE_NAMESPACE(unpack_sig) +int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + + +#endif //HAETAE_PACKING_H +// clang-format on diff --git a/crypto_sign/haetae2/m4f/params.h b/crypto_sign/haetae2/m4f/params.h new file mode 100644 index 00000000..7fac531b --- /dev/null +++ b/crypto_sign/haetae2/m4f/params.h @@ -0,0 +1,140 @@ +// clang-format off +#ifndef HAETAE_PARAMS_H +#define HAETAE_PARAMS_H + +#include "config.h" + +/*************************************************************** + * Settings for Stack Management + * ENABLE_TWO_PASS_SAMPLING: + * - Default: not defined + * - relates to polyfixveclk_sample_hyperball() + * - use about (L + K - 1) * 2kB less stack memory + * - roughly double the execution time + * ENABLE_SIGNATURE_MATRIX_BUFFER: + * - Default: defined + * - Enables the use of large matrices to + * store the public key matrix + * - Uses about L * K * 2kB stack memory + * - increases runtime, as the matrix needs + * - to be recomputed for each rejection cycle + * Execute "make clean" to ensure the switches take effect. + ***************************************************************/ +#define ENABLE_TWO_PASS_SAMPLING +//#define ENABLE_SIGNATURE_MATRIX_BUFFER +//#define ENABLE_KEYPAIR_MATRIX_BUFFER + + +#define SEEDBYTES 32 +#define CRHBYTES 64 +#define N 256 +#define ROOT_OF_UNITY 3 + +#define Q 64513 +#define DQ (Q << 1)// 2Q + +#if HAETAE_MODE == 2 +#define K 2 +#define L 4 +#define ETA 1 +#define TAU 58 +#define B0 9846.02 +#define B0SQ_FP112_76 {.digit = {0x04D6A161, 0x04538EF3, 0x0EE57247, 0x05C73F}} // == round(9846.02**2 * 2^76) +#define B1 9838.99 +#define B2 12777.52 +#define GAMMA 48.858 +#define LN 8192 // Large N +#define SQNM 39.191835884530846 // \sqrt(n * m) +#define D 1 +#define CRYPTO_BYTES 1474 + +#define BASE_ENC_HB_Z1 132 +#define BASE_ENC_H 7 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 3 +#define K 3 +#define L 6 +#define ETA 1 +#define TAU 80 +#define B0 18314.98 +#define B0SQ_FP112_76 {.digit = {0x0A9930BE, 0x0D495182, 0x09CE6809, 0x013FE62}} // == round(18314.98**2 * 2^76) +#define B1 18307.70 +#define B2 21906.65 +#define GAMMA 57.707 +#define LN 8192 // Large N +#define SQNM 48.0 +#define D 1 +#define CRYPTO_BYTES 2349 + +#define BASE_ENC_HB_Z1 376 +#define BASE_ENC_H 127 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 5 +#define K 4 +#define L 7 +#define ETA 1 +#define TAU 128 +#define B0 22343.66 +#define B0SQ_FP112_76 {.digit = {0x0504816F, 0x077318FC, 0x0E6B212D, 0x01DC1C8}} // == round(22343.66**2 * 2^76) +#define B1 22334.95 +#define B2 24441.49 +#define GAMMA 55.13 +#define LN 8192 // Large N +#define SQNM 53.0659966456864 +#define D 0 +#define CRYPTO_BYTES 2948 + +#define BASE_ENC_HB_Z1 501 +#define BASE_ENC_H 358 + +#define ALPHA_HINT 256 +#define LOG_ALPHA_HINT 8 + +#define POLYB1_PACKEDBYTES 512 // 16bits * N / 8bits +#define POLYQ_PACKEDBYTES 512 // 16bits * N / 8bits + +#endif // HAETAE_MODE + +#define HALF_ALPHA_HINT (ALPHA_HINT >> 1) // ALPHA / 2 + +#define B0SQ ((uint64_t)(B0*B0)) +#define B1SQ ((uint64_t)(B1*B1)) +#define B2SQ ((uint64_t)(B2*B2)) + +#define M (L-1) + +#if ETA == 1 +#define POLYETA_PACKEDBYTES 64 +#define POLY2ETA_PACKEDBYTES 96 +#elif ETA == 2 +#define POLYETA_PACKEDBYTES 96 +#endif + +#define POLYC_PACKEDBYTES 32 // 1bit * N / 8bits +#define POLY_HIGHBITS_PACKEDBYTES (N * 9 / 8) +#define POLYVECK_HIGHBITS_PACKEDBYTES (POLY_HIGHBITS_PACKEDBYTES * K) +#define POLYVECK_BYTES (K * N * sizeof(int32_t)) +#define POLYVECL_BYTES (L * N * sizeof(int32_t)) + +#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLYQ_PACKEDBYTES) // seed + b +#if D == 1 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + M * POLYETA_PACKEDBYTES + K * POLY2ETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#elif D == 0 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + (M + K) * POLYETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#else +#error +#endif +#endif +// clang-format on diff --git a/crypto_sign/haetae2/m4f/poly.c b/crypto_sign/haetae2/m4f/poly.c new file mode 100644 index 00000000..8c9181ee --- /dev/null +++ b/crypto_sign/haetae2/m4f/poly.c @@ -0,0 +1,825 @@ +#include "poly.h" +#include "decompose.h" +#include "ntt332.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include "arm_simd.h" +#include + + +void poly_decompose_vk(poly *v0, poly *v) { + for (int j = 0; j < N; j++) { + v->coeffs[j] = decompose_vk(&v0->coeffs[j], v->coeffs[j]); + } +} + +void poly_frommont(poly *v) { + unsigned int j; + + for (j = 0; j < N; j++) + v->coeffs[j] = montgomery_reduce((int64_t)v->coeffs[j] * MONTSQ); +} + +void poly_double_negate(poly *v) { + unsigned int j; + + for (j = 0; j < N; j++) + v->coeffs[j] = montgomery_reduce((int64_t)v->coeffs[j] * MONT * (-2)); +} + +void poly_caddq(poly *v) { + unsigned j; + + for (j = 0; j < N; ++j) + v->coeffs[j] = caddq(v->coeffs[j]); +} + + + + +/************************************************* + * Name: poly_clone + * + * Description: Clones the contents of one poly to another. + * + * Arguments: - poly src: polynomial to be cloned + * - poly dest: polynomial to clone to + **************************************************/ +void poly_clone(poly *dest, const poly *src){ + for (size_t i=0; icoeffs[i] = src->coeffs[i]; +} + +/************************************************* + * Name: poly_add + * + * Description: Add polynomials. No modular reduction is performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +/************************************************* + * Name: poly_sub + * + * Description: Subtract polynomials. No modular reduction is + * performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial to be + * subtraced from first input polynomial + **************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +/************************************************* + * Name: poly_cneg + * + * Description: Conditionally negate polynomial. No modular reduction is + * performed. + * + * Arguments: - poly *c: pointer to input/output polynomial + * - const uint8_t b: bit in [0,1]. If zero keep, + * else negate. + **************************************************/ +void poly_cneg(poly *c, const uint8_t b) { + unsigned int j; + for (j = 0; j < N; j++) { + c->coeffs[j] *= 1 - 2 * b; + } +} + + +/************************************************* + * Name: polyq_shl + * + * Description: Shift every coefficient left by shmnt. + * No overflow checking is done. + * + * Arguments: - poly *r: pointer to polynomial to work on + * - const uint8_t shmnt: shift amount + **************************************************/ +void poly_shl(poly *r, const uint8_t shmnt){ + for (size_t k = 0; k < N; ++k) + r->coeffs[k] <<= shmnt; +} + +/************************************************* + * Name: poly_double + * + * Description: Double vector of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + **************************************************/ +void poly_double(poly *b) { + unsigned int j; + + for (j = 0; j < N; ++j) + b->coeffs[j] *= 2; +} + +/************************************************* + * Name: poly_pointwise_montgomery + * + * Description: Pointwise multiplication of polynomials in NTT domain + * representation and multiplication of resulting polynomial + * by 2^{-32}. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial + **************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); +} + +/************************************************* + * Name: poly_pointwise_montgomery_mixed + * + * Description: Pointwise multiplication of polynomials in NTT domain + * representation and multiplication of resulting polynomial + * by 2^{-32}. One of the input polynomials is frozen. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly_frozen *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial + **************************************************/ +void poly_pointwise_montgomery_mixed(poly *c, const poly_frozen *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = _montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); +} + +void poly_pointwise_montgomery_mixed_2(poly *c, const poly_frozen *a, const poly *b) { + uint16x2_t t; + // TODO: According to benchmarks_2023-06-28_pmm* data this is a bit + // slower than the above, but saves about 5kB stack usage. + + for (size_t i = 0; i < (N >> 1); ++i){ + t = load_uint16x2_t(&a->coeffs[0], i); + size_t j = i << 1; + c->coeffs[j] = _montgomery_reduce((int64_t)(t & 0xFFFF) * b->coeffs[j]); + j++; + c->coeffs[j] = _montgomery_reduce((int64_t)((t >> 16)) * b->coeffs[j]); + } +} + +/************************************************* + * Name: poly_reduce2q + * + * Description: Inplace reduction of all coefficients of polynomial to 2q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_reduce2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = reduce32_2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze2q + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ 2Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze(a->coeffs[i]); +} + +/************************************************* + * Name: poly_highbits + * + * Description: Compute HighBits of polynomial + * + * Arguments: - poly *a2: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_highbits(poly *a2, const poly *a) { + unsigned int i; + int32_t a1tmp; + + for (i = 0; i < N; ++i) + decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]); +} + +/************************************************* + * Name: poly_lowbits + * + * Description: Compute LowBits of polynomial + * + * Arguments: - poly *a1: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lowbits(poly *a1, const poly *a) { + unsigned int i = 0; + int32_t a2tmp = 0; + + for (i = 0; i < N; ++i) + decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]); +} + +/************************************************* + * Name: poly_compose + * + * Description: Compose HighBits and LowBits to recreate the polynomial + * + * Arguments: - poly *a3: pointer to output polynomial + * - const poly *ha: pointer to HighBits polynomial + * - const poly *la: pointer to HighBits polynomial + **************************************************/ +void poly_compose(poly *a, const poly *ha, const poly *la) { + unsigned int i = 0; + + for (i = 0; i < N; ++i) + a->coeffs[i] = (ha->coeffs[i] << 8) + la->coeffs[i]; +} + +/************************************************* + * Name: poly_lsb + * + * Description: Compute least significant bits of polynomial + * + * Arguments: - poly *a0: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lsb(poly *a0, const poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a0->coeffs[i] = a->coeffs[i] & 1; +} + +/************************************************* + * Name: poly_uniform + * + * Description: Sample polynomial with uniformly random coefficients + * in [0,Q-1] by performing rejection sampling on the + * output stream of SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#define POLY_UNIFORM_NBLOCKS \ + ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES) +// N * 2(random bytes for [0, Q - 1]) + +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform(a->coeffs, N, buf, buflen); + + while (ctr < N) { + off = buflen % 2; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* + * Name: poly_uniform_frozen + * + * Description: Sample polynomial with uniformly random coefficients + * in [0,Q-1] by performing rejection sampling on the + * output stream of SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform_frozen(a->coeffs, N, buf, buflen); + + while (ctr < N) { + off = buflen % 2; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform_frozen(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* + * Name: poly_uniform_eta + * + * Description: Sample polynomial with uniformly random coefficients + * in [-ETA,ETA] by performing rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#if ETA == 1 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#elif ETA == 2 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#endif + +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int ctr; + unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); + + ctr = rej_eta(a->coeffs, N, buf, buflen); + + while (ctr < N) { + stream256_squeezeblocks(buf, 1, &state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); + } +} + +uint8_t hammingWeight_8(uint8_t x) { + x = (x & 0x55) + (x >> 1 & 0x55); + x = (x & 0x33) + (x >> 2 & 0x33); + x = (x & 0x0F) + (x >> 4 & 0x0F); + + return x; +} + +/************************************************* + * Name: poly_challenge + * + * Description: Implementation of challenge. Samples polynomial with TAU 1 + * coefficients using the output stream of SHAKE256(seed). + * + * Arguments: - poly *c: pointer to output polynomial + * - const uint8_t seed[]: byte array containing seed of length + * SEEDBYTES + **************************************************/ +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { +#if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) + unsigned int i, b, pos = 0; + uint8_t buf[XOF256_BLOCKBYTES]; + xof256_state state; + + xof256_absorb_once(&state, seed, SEEDBYTES); + xof256_squeezeblocks(buf, 1, &state); + + for (i = 0; i < N; ++i) + c->coeffs[i] = 0; + for (i = N - TAU; i < N; ++i) { + do { + if (pos >= XOF256_BLOCKBYTES) { + xof256_squeezeblocks(buf, 1, &state); + pos = 0; + } + + b = buf[pos++]; + } while (b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1; + } +#elif HAETAE_MODE == 5 + unsigned int i, hwt = 0, cond = 0; + uint8_t mask = 0, w0 = 0; + uint8_t buf[32] = {0}; + xof256_state state; + + xof256_absorb_once(&state, seed, SEEDBYTES); + xof256_squeeze(buf, 32, &state); + + for (i = 0; i < 32; ++i) + hwt += hammingWeight_8(buf[i]); + + cond = (128 - hwt); + mask = 0xff & (cond >> 8); + w0 = -(buf[0] & 1); + mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0 + for (i = 0; i < 32; ++i) { + buf[i] ^= mask; + c->coeffs[8 * i] = buf[i] & 1; + c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1; + c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1; + c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1; + c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1; + c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1; + c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1; + c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1; + } +#endif +} + +void poly_decomposed_pack(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + buf[i] = a->coeffs[i]; + } +} + +void poly_decomposed_unpack(poly *a, const uint8_t *buf) { + unsigned int i; + for (i = 0; i < N; i++) { + a->coeffs[i] = (int8_t)buf[i]; + } +} + +void poly_caddDQ2ALPHA(poly *h) { + unsigned int j; + for (j = 0; j < N; j++) { + h->coeffs[j] += + (h->coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); + } +} + +void poly_highbits_hint(poly *w, const poly *v) { + unsigned int j; + for (j = 0; j < N; j++) { + decompose_hint(&w->coeffs[j], v->coeffs[j]); + } +} + +void poly_pack_highbits(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N / 8; i++) { + buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff; + + buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01; + buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff; + + buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03; + buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff; + + buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07; + buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff; + + buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f; + buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff; + + buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f; + buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff; + + buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f; + buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff; + + buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f; + buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff; + + buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff; + } +} + +void poly_pack_lsb(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + if ((i % 8) == 0) { + buf[i / 8] = 0; + } + buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8); + } +} + +/************************************************* + * Name: polyq_pack + * + * Description: Bit-pack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYQ_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyq_pack(uint8_t *r, const poly *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r[b_idx] = (a->coeffs[d_idx] & 0xff); + r[b_idx + 1] = ((a->coeffs[d_idx] >> 8) & 0x7f) | + ((a->coeffs[d_idx + 1] & 0x1) << 7); + r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff); + r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) | + ((a->coeffs[d_idx + 2] & 0x3) << 6); + r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff); + r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) | + ((a->coeffs[d_idx + 3] & 0x7) << 5); + r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff); + r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) | + ((a->coeffs[d_idx + 4] & 0xf) << 4); + r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff); + r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) | + ((a->coeffs[d_idx + 5] & 0x1f) << 3); + r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff); + r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) | + ((a->coeffs[d_idx + 6] & 0x3f) << 2); + r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff); + r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) | + (a->coeffs[d_idx + 7] & 0x7f) << 1; + r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff); + } +#else + for (i = 0; i < N / 1; ++i) { + r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0; + r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8; + } +#endif +} + +/************************************************* + * Name: polyq_unpack + * + * Description: Unpack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyq_unpack(poly *r, const uint8_t *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8); + r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) | + ((a[b_idx + 2] & 0xff) << 1) | + ((a[b_idx + 3] & 0x3f) << 9); + r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) | + ((a[b_idx + 4] & 0xff) << 2) | + ((a[b_idx + 5] & 0x1f) << 10); + r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) | + ((a[b_idx + 6] & 0xff) << 3) | + ((a[b_idx + 7] & 0xf) << 11); + r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) | + ((a[b_idx + 8] & 0xff) << 4) | + ((a[b_idx + 9] & 0x7) << 12); + r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) | + ((a[b_idx + 10] & 0xff) << 5) | + ((a[b_idx + 11] & 0x3) << 13); + r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) | + ((a[b_idx + 12] & 0xff) << 6) | + ((a[b_idx + 13] & 0x1) << 14); + r->coeffs[d_idx + 7] = + ((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7); + } + +#else + for (i = 0; i < N / 1; ++i) { + r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0; + r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8; + r->coeffs[1 * i + 0] &= 0xffff; + } +#endif +} + +/************************************************* + * Name: polyeta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyeta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + t[0] = ETA - a->coeffs[4 * i + 0]; + t[1] = ETA - a->coeffs[4 * i + 1]; + t[2] = ETA - a->coeffs[4 * i + 2]; + t[3] = ETA - a->coeffs[4 * i + 3]; + r[i] = t[0] >> 0; + r[i] |= t[1] << 2; + r[i] |= t[2] << 4; + r[i] |= t[3] << 6; + } +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + t[0] = ETA - a->coeffs[8 * i + 0]; + t[1] = ETA - a->coeffs[8 * i + 1]; + t[2] = ETA - a->coeffs[8 * i + 2]; + t[3] = ETA - a->coeffs[8 * i + 3]; + t[4] = ETA - a->coeffs[8 * i + 4]; + t[5] = ETA - a->coeffs[8 * i + 5]; + t[6] = ETA - a->coeffs[8 * i + 6]; + t[7] = ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#endif +} + +/************************************************* + * Name: polyeta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyeta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + r->coeffs[4 * i + 0] = a[i] >> 0; + r->coeffs[4 * i + 0] &= 0x3; + + r->coeffs[4 * i + 1] = a[i] >> 2; + r->coeffs[4 * i + 1] &= 0x3; + + r->coeffs[4 * i + 2] = a[i] >> 4; + r->coeffs[4 * i + 2] &= 0x3; + + r->coeffs[4 * i + 3] = a[i] >> 6; + r->coeffs[4 * i + 3] &= 0x3; + + r->coeffs[4 * i + 0] = ETA - r->coeffs[4 * i + 0]; + r->coeffs[4 * i + 1] = ETA - r->coeffs[4 * i + 1]; + r->coeffs[4 * i + 2] = ETA - r->coeffs[4 * i + 2]; + r->coeffs[4 * i + 3] = ETA - r->coeffs[4 * i + 3]; + } + +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7]; + } +#endif +} + +/************************************************* + * Name: poly2eta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly2eta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + t[0] = 2 * ETA - a->coeffs[8 * i + 0]; + t[1] = 2 * ETA - a->coeffs[8 * i + 1]; + t[2] = 2 * ETA - a->coeffs[8 * i + 2]; + t[3] = 2 * ETA - a->coeffs[8 * i + 3]; + t[4] = 2 * ETA - a->coeffs[8 * i + 4]; + t[5] = 2 * ETA - a->coeffs[8 * i + 5]; + t[6] = 2 * ETA - a->coeffs[8 * i + 6]; + t[7] = 2 * ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +/************************************************* + * Name: poly2eta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void poly2eta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = 2 * ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = 2 * ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = 2 * ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = 2 * ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = 2 * ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = 2 * ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = 2 * ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = 2 * ETA - r->coeffs[8 * i + 7]; + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +void poly_fromcrt(poly *w, const poly *u, const poly *v) { + unsigned int i; + int32_t xq, x2; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + x2 = v->coeffs[i]; + w->coeffs[i] = xq + (Q & -((xq ^ x2) & 1)); + } +} + +void poly_fromcrt0(poly *w, const poly *u) { + unsigned int i; + int32_t xq; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + w->coeffs[i] = xq + (Q & -(xq & 1)); + } +} + +void poly_ntt(poly *a) { haetae_ntt332(&a->coeffs[0]); } + +void poly_invntt_tomont(poly *a) { haetae_invntt332_tomont(&a->coeffs[0]); } diff --git a/crypto_sign/haetae2/m4f/poly.h b/crypto_sign/haetae2/m4f/poly.h new file mode 100644 index 00000000..192c9033 --- /dev/null +++ b/crypto_sign/haetae2/m4f/poly.h @@ -0,0 +1,116 @@ +// clang-format off +#ifndef HAETAE_POLY_H +#define HAETAE_POLY_H + +#include "params.h" +#include "reduce.h" +#include "sampler.h" +#include + +// General polynomial +typedef struct { + int32_t coeffs[N]; +} poly; + +// Polynomial with values in [0,q-1] for use in matrices. +// These are typically read-only after initial computation. +typedef struct { + uint16_t coeffs[N]; +} poly_frozen; + + + +#define poly_decompose_vk HAETAE_NAMESPACE(poly_decompose_vk) +void poly_decompose_vk(poly *v0, poly *v); +#define poly_frommont HAETAE_NAMESPACE(poly_frommont) +void poly_frommont(poly *v); +#define poly_double_negate HAETAE_NAMESPACE(poly_double_negate) +void poly_double_negate(poly *v); +#define poly_caddq HAETAE_NAMESPACE(poly_caddq) +void poly_caddq(poly *v); + + + +#define poly_clone HAETAE_NAMESPACE(poly_clone) +void poly_clone(poly *dest, const poly *src); +#define poly_add HAETAE_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub HAETAE_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_cneg HAETAE_NAMESPACE(poly_cneg) +void poly_cneg(poly *c, const uint8_t b); +#define poly_shl HAETAE_NAMESPACE(poly_shl) +void poly_shl(poly *r, const uint8_t shmnt); +#define poly_double HAETAE_NAMESPACE(poly_double) +void poly_double(poly *b); +#define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); +#define poly_pointwise_montgomery_mixed HAETAE_NAMESPACE(poly_pointwise_montgomery_mixed) +void poly_pointwise_montgomery_mixed(poly *c, const poly_frozen *a, const poly *b); + +#define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) +void poly_reduce2q(poly *a); +#define poly_freeze2q HAETAE_NAMESPACE(poly_freeze2q) +void poly_freeze2q(poly *a); +#define poly_freeze HAETAE_NAMESPACE(poly_freeze) +void poly_freeze(poly *a); + +#define poly_highbits HAETAE_NAMESPACE(poly_highbits) +void poly_highbits(poly *a2, const poly *a); +#define poly_lowbits HAETAE_NAMESPACE(poly_lowbits) +void poly_lowbits(poly *a1, const poly *a); +#define poly_compose HAETAE_NAMESPACE(poly_compose) +void poly_compose(poly *a, const poly *ha, const poly *la); +#define poly_lsb HAETAE_NAMESPACE(poly_lsb) +void poly_lsb(poly *a0, const poly *a); + +#define poly_uniform HAETAE_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_frozen HAETAE_NAMESPACE(poly_uniform_frozen) +void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define poly_challenge HAETAE_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); + +#define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) +void poly_decomposed_pack(uint8_t *buf, const poly *a); +#define poly_decomposed_unpack HAETAE_NAMESPACE(poly_decomposed_unpack) +void poly_decomposed_unpack(poly *a, const uint8_t *buf); + +#define poly_caddDQ2ALPHA HAETAE_NAMESPACE(poly_caddDQ2ALPHA) +void poly_caddDQ2ALPHA(poly *h); +#define poly_highbits_hint HAETAE_NAMESPACE(poly_highbits_hint) +void poly_highbits_hint(poly *w, const poly *v); +#define poly_pack_highbits HAETAE_NAMESPACE(poly_pack_highbits) +void poly_pack_highbits(uint8_t *buf, const poly *a); + +#define poly_pack_lsb HAETAE_NAMESPACE(poly_pack_lsb) +void poly_pack_lsb(uint8_t *buf, const poly *a); + +#define polyq_pack HAETAE_NAMESPACE(polyq_pack) +void polyq_pack(uint8_t *r, const poly *a); +#define polyq_unpack HAETAE_NAMESPACE(polyq_unpack) +void polyq_unpack(poly *r, const uint8_t *a); + +#define polyeta_pack HAETAE_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t *r, const poly *a); +#define polyeta_unpack HAETAE_NAMESPACE(polyeta_unpack) +void polyeta_unpack(poly *r, const uint8_t *a); +#define poly2eta_pack HAETAE_NAMESPACE(poly2eta_pack) +void poly2eta_pack(uint8_t *r, const poly *a); +#define poly2eta_unpack HAETAE_NAMESPACE(poly2eta_unpack) +void poly2eta_unpack(poly *r, const uint8_t *a); + +#define poly_fromcrt HAETAE_NAMESPACE(poly_fromcrt) +void poly_fromcrt(poly *w, const poly *u, const poly *v); +#define poly_fromcrt0 HAETAE_NAMESPACE(poly_fromcrt0) +void poly_fromcrt0(poly *w, const poly *u); + +#define poly_ntt HAETAE_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); +#define poly_invntt_tomont HAETAE_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/m4f/polyfix.c b/crypto_sign/haetae2/m4f/polyfix.c new file mode 100644 index 00000000..d7d36e8b --- /dev/null +++ b/crypto_sign/haetae2/m4f/polyfix.c @@ -0,0 +1,382 @@ +#include "polyfix.h" +#include "decompose.h" +#include "math.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include "fp84_76.h" +#include "sampler.h" +#include + +const fp112_76 B0_squared_112 = B0SQ_FP112_76; + +/************************************************* + * Name: polyfix_add + * + * Description: Add double polynomial and integer polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output double polynomial + * - const polyfix *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void polyfix_add(polyfix *c, const polyfix *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + LN * b->coeffs[i]; +} + +/************************************************* + * Name: polyfix_sub + * + * Description: Subtract fixed polynomial and fixed polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output fixed polynomial + * - const polyfix *a: pointer to first summand + * - const polyfix *b: pointer to second summand + **************************************************/ +void polyfix_sub(polyfix *c, const polyfix *a, const polyfix *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +int32_t fix_round(int32_t num) { + num += (num >> 31) & (-LN + 1); + num += + LN / + 2; // total \floor(LN / 2) if positive, -\floor(LN / 2) + 1 if negative + return num / LN; +} + +/************************************************* + * Name: polyfix_round + * + * Description: rounds a fixed polynomial to integer polynomial + * + * Arguments: - poly *a: output integer polynomial + * - poly *b: input fixed polynomial + **************************************************/ +void polyfix_round(poly *a, const polyfix *b) { + unsigned i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = fix_round(b->coeffs[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length K **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixveck_add + * + * Description: Add vector to a vector of double polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixveck_sub + * + * Description: subtract vector to a vector of fixed polynomials of length k. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyfixveck *u: pointer to first summand + * - const polyfixveck *v: pointer to second summand + **************************************************/ +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixveck_double + * + * Description: Double vector of polynomials of length K. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixveck_double(polyfixveck *b, const polyfixveck *a) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; +} + +/************************************************* + * Name: polyfixveck_round + * + * Description: rounds a fixed polynomial vector of length K + * + * Arguments: - polyveck *a: output integer polynomial vector + * - polyfixveck *b: input fixed polynomial vector + **************************************************/ +void polyfixveck_round(polyveck *a, const polyfixveck *b) { + unsigned i; + + for (i = 0; i < K; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length L **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixvecl_add + * + * Description: Add vector to a vector of double polynomials of length L. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyvecl *v: pointer to second summand + **************************************************/ +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixvecl_sub + * + * Description: subtract vector to a vector of fixed polynomials of length l. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyfixvecl *v: pointer to second summand + **************************************************/ +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfix_double + * + * Description: Double contents of polynomial. + * + * Arguments: - polyveck *b: pointer to output polynomial + * - polyveck *a: pointer to input polynomial + **************************************************/ +void polyfix_double(polyfix *b, const polyfix *a) { + unsigned int j; + + for (j = 0; j < N; ++j) + b->coeffs[j] = 2 * a->coeffs[j]; +} + +/************************************************* + * Name: polyfixvecl_double + * + * Description: Double vector of polynomials of length L. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfix_double(&b->vec[i], &a->vec[i]); +} + +/************************************************* + * Name: polyfixvecl_round + * + * Description: rounds a fixed polynomial vector of length L + * + * Arguments: - polyvecl *a: output integer polynomial vector + * - polyfixvecl *b: input fixed polynomial vector + **************************************************/ +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) { + unsigned i; + + for (i = 0; i < L; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + + +/************************************************* + * Name: polyfix_norm2 + * + * Description: Calculates L2 norm of a fixed point polynomial + * + * Arguments: - polyfix *a: polynomial to calculate norm + **************************************************/ +uint64_t polyfix_sqnorm2(const polyfix *a) { + unsigned int j; + uint64_t ret = 0; + + for (j = 0; j < N; ++j) + ret += (int64_t)a->coeffs[j] * a->coeffs[j]; + + return ret; +} + +/************************************************* + * Name: polyfixveclk_norm2 + * + * Description: Calculates L2 norm of a fixed point polynomial vector with + *length L + K The result is L2 norm * LN similar to the way polynomial is + *usually stored + * + * Arguments: - polyfixvecl *a: polynomial vector with length L to calculate + * norm + * - polyfixveck *a: polynomial vector with length K to calculate + * norm + **************************************************/ +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { + unsigned int i; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + ret += polyfix_sqnorm2(&a->vec[i]); + } + + for (i = 0; i < K; ++i) { + ret += polyfix_sqnorm2(&b->vec[i]); + } + + return ret; +} + +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, + const uint8_t seed[CRHBYTES], + const uint16_t nonce) { + uint16_t ni = nonce; + uint64_t samples[N * (L + K)]; + fp112_76 sqsum112 = {{0}}; + fp96_76 sqsum, invsqrt; + uint64_t sqnorm2; + unsigned int i, j; + uint8_t signs[N * (L + K) / 8]; + + do { + set_to_zero_112(&sqsum112); + sample_gauss_N(&samples[0], &signs[0], &sqsum112, seed, ni++, N + 1); + sample_gauss_N(&samples[N], &signs[N / 8], &sqsum112, seed, ni++, N + 1); + + for (i = 2; i < L + K; i++) + sample_gauss_N(&samples[N * i], &signs[N / 8 * i], &sqsum112, seed, + ni++, N); + + convert_fp112_76_to_fp96_76(&sqsum, &sqsum112); + + // divide sqsum by 2 and approximate inverse square root + sqsum.limb48[0] += 1; // rounding + sqsum.limb48[0] >>= 1; + sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; + sqsum.limb48[1] >>= 1; + sqsum.limb48[1] += sqsum.limb48[0] >> 48; + sqsum.limb48[0] &= (1ULL << 48) - 1; + fixpoint_newton_invsqrt(&invsqrt, &sqsum); + fixpoint_mul_high(&sqsum, &invsqrt, + (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); + + for (i = 0; i < L; i++) { + for (j = 0; j < N; j++) + y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + for (i = L; i < K + L; i++) { + for (j = 0; j < N; j++) + y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + sqnorm2 = polyfixveclk_sqnorm2(y1, y2); + } while (sqnorm2 > B0SQ * LN * LN); + return ni; +} + +uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, + const uint8_t seed[CRHBYTES], + const uint16_t nonce) { + uint16_t ni = nonce; + uint16_t ni_at_start_of_pass_1; + + uint64_t samples[N + 1]; + fp112_76 sqsum112 = {{0}}; + fp96_76 sqsum, invsqrt; + fp112_76 sqsum_2nd_pass__throw_away = {{0}}; + + unsigned int i, j; + uint8_t signs[N / 8]; + + do { + /* ------------- PASS ONE: compute sqsum and invsqrt ----------- */ + ni_at_start_of_pass_1 = ni; + + sample_gauss_N(&samples[0], &signs[0], &sqsum112, seed, ni++, N + 1); + sample_gauss_N(&samples[0], &signs[0], &sqsum112, seed, ni++, N + 1); + + for (i = 2; i < L + K; i++) + sample_gauss_N(&samples[0], &signs[0], &sqsum112, seed, ni++, N); + + convert_fp112_76_to_fp96_76(&sqsum, &sqsum112); + + // divide sqsum by 2 and approximate inverse square root + sqsum.limb48[0] += 1; // rounding + sqsum.limb48[0] >>= 1; + sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; + sqsum.limb48[1] >>= 1; + sqsum.limb48[1] += sqsum.limb48[0] >> 48; + sqsum.limb48[0] &= (1ULL << 48) - 1; + fixpoint_newton_invsqrt(&invsqrt, &sqsum); + fixpoint_mul_high(&sqsum, &invsqrt, + (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); + + /* ------------- PASS TWO: sample y1 and y2 ----------------- */ + ni = ni_at_start_of_pass_1; + for (i = 0; i < 2; i++) { + sample_gauss_N(&samples[0], &signs[0], &sqsum_2nd_pass__throw_away, seed, ni++, N + 1); + for (j = 0; j < N; j++) + y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( + samples[j], &sqsum, + (signs[j / 8] >> (j % 8)) & 1); + } + for (i = 2; i < L; i++) { + sample_gauss_N(&samples[0], &signs[0], &sqsum_2nd_pass__throw_away, seed, ni++, N); + for (j = 0; j < N; j++) + y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( + samples[j], &sqsum, + (signs[j / 8] >> (j % 8)) & 1); + } + for (i = L; i < K + L; i++) { + sample_gauss_N(&samples[0], &signs[0], &sqsum_2nd_pass__throw_away, seed, ni++, N); + for (j = 0; j < N; j++) + y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( + samples[j], &sqsum, + (signs[j / 8] >> (j % 8)) & 1); + } + } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); + + return ni; +} diff --git a/crypto_sign/haetae2/m4f/polyfix.h b/crypto_sign/haetae2/m4f/polyfix.h new file mode 100644 index 00000000..a77a2740 --- /dev/null +++ b/crypto_sign/haetae2/m4f/polyfix.h @@ -0,0 +1,71 @@ +// clang-format off +#ifndef HAETAE_POLYFIX_H +#define HAETAE_POLYFIX_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include "reduce.h" +#include + +typedef struct { + int32_t coeffs[N]; +} polyfix; + +#define polyfix_norm2 HAETAE_NAMESPACE(polyfix_norm2) +double polyfix_norm2(const polyfix *a); + +#define polyfix_round HAETAE_NAMESPACE(polyfix_round) +void polyfix_round(poly *a, const polyfix *b); + +#define polyfix_add HAETAE_NAMESPACE(polyfix_add) +void polyfix_add(polyfix *c, const polyfix *a, const poly *b); + +#define polyfix_sub HAETAE_NAMESPACE(polyfix_sub) +void polyfix_sub(polyfix *c, const polyfix *a, const polyfix *b); + +typedef struct { + polyfix vec[K]; +} polyfixveck; + +#define polyfixveck_add HAETAE_NAMESPACE(polyfixveck_add) +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v); +#define polyfixfixveck_sub HAETAE_NAMESPACE(polyfixfixveck_sub) +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v); +#define polyfixveck_double HAETAE_NAMESPACE(polyfixveck_double) +void polyfixveck_double(polyfixveck *b, const polyfixveck *a); + +#define polyfixveck_round HAETAE_NAMESPACE(polyfixveck_round) +void polyfixveck_round(polyveck *a, const polyfixveck *b); + +typedef struct { + polyfix vec[L]; +} polyfixvecl; + +#define polyfixvecl_add HAETAE_NAMESPACE(polyfixvecl_add) +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v); +#define polyfixfixvecl_sub HAETAE_NAMESPACE(polyfixfixvecl_sub) +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v); +#define polyfix_double HAETAE_NAMESPACE(polyfix_double) +void polyfix_double(polyfix *b, const polyfix *a); +#define polyfixvecl_double HAETAE_NAMESPACE(polyfixvecl_double) +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a); + +#define polyfixvecl_round HAETAE_NAMESPACE(polyfixvecl_round) +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); + +#define polyfix_sqnorm2 HAETAE_NAMESPACE(polyfix_sqnorm2) +uint64_t polyfix_sqnorm2(const polyfix *a); +#define polyfixveclk_sqnorm2 HAETAE_NAMESPACE(polyfixveclk_sqnorm2) +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); + +#define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); + +#define polyfixveclk_two_pass_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_two_pass_sample_hyperball) +uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/m4f/polymat.c b/crypto_sign/haetae2/m4f/polymat.c new file mode 100644 index 00000000..c9ac34a5 --- /dev/null +++ b/crypto_sign/haetae2/m4f/polymat.c @@ -0,0 +1,175 @@ +#include "polymat.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: expand_a_gen_mod_q_elem + * (internal use only) + * + * Description: Unpack polynomial of A_gen + * + * Arguments: - poly elem: output poly for the matrix element + * - const row: row of the matrix element 0 <= row < K + * - const column: column of the matrix element 0 <= column < L + * - const uint8_t pk[]: compressed public key + **************************************************/ +static void expand_a_gen_mod_q_elem(poly *elem, const size_t row, const size_t column, + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]){ + uint16_t nonce; + + nonce = (row << 8) + (column); + poly_uniform(elem, pk, nonce); + poly_shl(elem, 1); +} + +/************************************************* + * Name: expand_b_mod_q_elem + * (internal use only) + * + * Description: Unpack polynomial of b + * + * Arguments: - poly elem: output poly for the matrix element + * - const row: row of the matrix element 0 <= row < K + * - const column: column of the matrix element 0 <= column < L + * - const uint8_t pk[]: compressed public key + **************************************************/ +static void expand_b_mod_q_elem(poly *elem, const size_t row, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]){ +#if D == 0 + polyq_unpack(elem, pk + SEEDBYTES + row * POLYQ_PACKEDBYTES); +#else + poly a; + uint16_t nonce; + + polyq_unpack(elem, pk + SEEDBYTES + row * POLYQ_PACKEDBYTES); + + // first column of A = 2(a-b1*2^d) + + nonce = (K << 8) + M + row; + // dbg_send_msg_and_hexdump("b nonce: ", (uint8_t*) &nonce, sizeof(nonce)); + poly_uniform(&a, pk, nonce); + + poly_shl(elem, D); + + poly_sub(elem, &a, elem); + poly_shl(elem, 1); + poly_ntt(elem); +#endif +} + +#if 0 +/************************************************* + * Name: expand_pk_matrix_elem + * + * Description: Unpack public key polynomial A[row, column]. + * + * Arguments: - poly elem: output poly for the matrix element + * - const row: row of the matrix element 0 <= row < K + * - const column: column of the matrix element 0 <= column < L + * - const uint8_t pk[]: compressed public key + **************************************************/ +void expand_pk_matrix_elem(poly *elem, const size_t row, const size_t column, + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]){ + if (0 < column) { + expand_a_gen_mod_q_elem(elem, row, column - 1, pk); + } else { + expand_b_mod_q_elem(elem, row, pk); + } +} +#endif + +/************************************************* + * Name: expand_pk_matrix_elem_frozen + * + * Description: Unpack public key polynomial A[row, column]. + * + * Arguments: - poly elem: output poly for the matrix element + * - const row: row of the matrix element 0 <= row < K + * - const column: column of the matrix element 0 <= column < L + * - const uint8_t pk[]: compressed public key + **************************************************/ +void expand_pk_matrix_elem_frozen(poly_frozen *elem, const size_t row, const size_t column, + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]){ + poly p; + if (0 < column) { + expand_a_gen_mod_q_elem(&p, row, column - 1, pk); + } else { + expand_b_mod_q_elem(&p, row, pk); + } + for (size_t j = 0; j < N; j++) { + elem->coeffs[j] = (uint16_t) (freeze(p.coeffs[j]) & 0xFFFF); + } +} + + + + + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); +} + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); +} + +// doubles k * m sub-matrix of k * l mat +void polymatkl_double(polyvecl mat[K]) { + unsigned int i, j, k; + for (i = 0; i < K; ++i) { + for (j = 1; j < L; ++j) { + for (k = 0; k < N; ++k) { + mat[i].vec[j].coeffs[k] *= 2; + } + } + } +} + +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} + +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} diff --git a/crypto_sign/haetae2/m4f/polymat.h b/crypto_sign/haetae2/m4f/polymat.h new file mode 100644 index 00000000..064117af --- /dev/null +++ b/crypto_sign/haetae2/m4f/polymat.h @@ -0,0 +1,34 @@ +#ifndef HAETAE_POLYMAT_H +#define HAETAE_POLYMAT_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +#define expand_pk_matrix_elem HAETAE_NAMESPACE(expand_pk_matrix_elem) +void expand_pk_matrix_elem(poly *elem, const size_t row, const size_t column, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define expand_pk_matrix_elem_frozen HAETAE_NAMESPACE(expand_pk_matrix_elem_frozen) +void expand_pk_matrix_elem_frozen(poly_frozen *elem, const size_t row, const size_t column, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkm_pointwise_montgomery) +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v); + +#define polymatkl_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkl_pointwise_montgomery) +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v); + +#define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) +void polymatkl_double(polyvecl mat[K]); + +#endif diff --git a/crypto_sign/haetae2/m4f/polyvec.c b/crypto_sign/haetae2/m4f/polyvec.c new file mode 100644 index 00000000..467344be --- /dev/null +++ b/crypto_sign/haetae2/m4f/polyvec.c @@ -0,0 +1,547 @@ +#include + +#include "decompose.h" +#include "fft.h" +#include "math.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +/************************************************* + * Name: polyveck_add + * + * Description: Add vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_sub + * + * Description: Subtract vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first input vector + * - const polyveck *v: pointer to second input vector to be + * subtracted from first input vector + **************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_double + * + * Description: Double vector of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + **************************************************/ +void polyveck_double(polyveck *b) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_double(&b->vec[i]); +} + +/************************************************* + * Name: polyveck_reduce2q + * + * Description: Reduce coefficients to 2q + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_reduce2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_reduce2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze2q + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ 2Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_expand + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in Zq by rejection sampling on the + * output stream from SHAKE128(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + **************************************************/ +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]) { + unsigned int i, nonce = (K << 8) + M; + for (i = 0; i < K; ++i) + poly_uniform(&v->vec[i], seed, nonce++); +} + +/************************************************* + * Name: polyvecmk_uniform_eta + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in [-ETA,ETA] by rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i, n = nonce; + for (i = 0; i < M; i++) + poly_uniform_eta(&u->vec[i], seed, n++); + for (i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, n++); +} + +/************************************************* + * Name: polyveck_double_negate + * + * Description: multiply each coefficient with -2 + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_double_negate(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2); +} + +/************************************************* + * Name: polyveck_frommont + * + * Description: multiply each coefficient with MONT + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_frommont(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ); +} + +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, + const poly *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v); + } +} + +/************************************************* + * Name: polyveck_poly_fromcrt + * + * Description: recover polynomials from CRT domain, where all "mod q" + * polynomials are known and only the uppermost "mod 2" polynomial + * is non-zero + * + * Arguments: - polyveck *w: pointer to output vector of polynomials of + * length K + * - const polyveck *u: pointer to the input vector of polynomials + * of length K + * - const poly *v: pointer to the input polynomial ("mod 2") + **************************************************/ +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) { + unsigned int i; + + poly_fromcrt(&w->vec[0], &u->vec[0], v); + + for (i = 1; i < K; i++) { + poly_fromcrt0(&w->vec[i], &u->vec[i]); + } +} + +void polyveck_highbits_hint(polyveck *w, const polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pack_highbits(buf + i * POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]); + } +} + +void polyveck_cneg(polyveck *v, const uint8_t b) { + unsigned int row; + for (row = 0; row < K; row++) { + poly_cneg(&v->vec[row], b); + } +} + +void polyveck_caddDQ2ALPHA(polyveck *h) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + h->vec[i].coeffs[j] += + (h->vec[i].coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_csubDQ2ALPHA(polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] -= + ~((v->vec[i].coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & + ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_mul_alpha(polyveck *v, const polyveck *u) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * ALPHA_HINT; + } + } +} + +void polyveck_div2(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] >>= 1; +} + +void polyveck_caddq(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]); +} + +void polyveck_decompose_vk(polyveck *v0, polyveck *v) { + for (int i = 0; i < K; i++) { + for (int j = 0; j < N; j++) { + v->vec[i].coeffs[j] = + decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_ntt(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_ntt(&x->vec[i]); + } +} + +void polyveck_invntt_tomont(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_invntt_tomont(&x->vec[i]); + } +} + +/************************************************* + * Name: polyveck_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length k + * + * Arguments: - polyveck *b: polynomial vector with length k to calculate + *norm + **************************************************/ +uint64_t polyveck_sqnorm2(const polyveck *b) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < K; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; + } + } + return ret; +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecl_highbits + * + * Description: Compute HighBits of a vector of polynomials + * + * Arguments: - polyvecl *v2: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_highbits(polyvecl *v2, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_highbits(&v2->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyvecl_lowbits + * + * Description: Compute LowBits of a vector of polynomials + * + * Arguments: - polyvecl *v1: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_lowbits(&v1->vec[i], &v->vec[i]); +} + + +/************************************************* + * Name: polyvecl_cneg + * + * Description: Conditionally negate all polynomials of a vector + * + * Arguments: - polyvecl *v: pointer to output vector of polynomials of + * length L + * - const uint8_t b: Keep as is, if zero, else negate. + **************************************************/ +void polyvecl_cneg(polyvecl *v, const uint8_t b) { + for (size_t column = 0; column < L; column++) { + poly_cneg(&v->vec[column], b); + } +} + +/************************************************* + * Name: polyvecl_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length l + * + * Arguments: - polyvecl *a: polynomial vector with length l to calculate + *norm + **************************************************/ +uint64_t polyvecl_sqnorm2(const polyvecl *a) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; + } + } + + return ret; +} + +/************************************************* + * Name: polyvecl_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecl *u: pointer to first input vector + * - const polyvecl *v: pointer to second input vector + **************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, + const polyvecl *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecl_ntt(polyvecl *x) { + unsigned int i; + for (i = 0; i < L; i++) { + poly_ntt(&x->vec[i]); + } +} + +/**************************************************************/ +/************ Vectors of polynomials of length M **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecm_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecm *u: pointer to first input vector + * - const polyvecm *v: pointer to second input vector + **************************************************/ +void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u, + const polyvecm *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < M; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecm_ntt(polyvecm *x) { + unsigned int i; + for (i = 0; i < M; i++) { + poly_ntt(&x->vec[i]); + } +} + +static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort +{ + int32_t a = *x; + int32_t b = *y; + int32_t ab = b ^ a; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} +static inline void minmaxmask(int32_t *x, int32_t *y, + int32_t *mask) // adapted from djbsort +{ + // If mask is -1, we perform the operation, else we do basically nothing. + // mask truth table: + // mask = 0 -> mask = 0, no swap is performed + // mask = -1, swap performed -> mask = 0 + // mask = -1, swap not performed -> mask = -1 + int32_t a = *x; + int32_t b = *y; + int32_t ab = (b ^ a) & *mask; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + *mask &= ~c; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} + +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2) { + int32_t res = 0; + complex_fp32_16 input[FFT_N] = {0}; + int32_t sum[N] = {0}, bestm[N / TAU + 1] = {0}, min = 0; + + for (size_t i = 0; i < M; ++i) { + fft_bitrev(input, &s1->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + for (size_t i = 0; i < K; ++i) { + fft_bitrev(input, &s2->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + // compute max m + for (size_t i = 0; i < N / TAU + 1; ++i) { + bestm[i] = sum[i]; + } + for (size_t i = N / TAU + 1; i < N; i++) { + int32_t mask = -1; + for (size_t j = 0; j < N / TAU + 1; j++) { + minmaxmask(&sum[i], &bestm[j], &mask); + } + } + // find minimum in bestm + min = bestm[0]; + for (size_t i = 1; i < N / TAU + 1; i++) { + int32_t tmp = bestm[i]; + minmax(&min, &tmp); + } + // multiply all but the minimum by N mod TAU + for (size_t i = 0; i < N / TAU + 1; i++) { + int32_t fac = ((min - bestm[i]) >> 31); // all-ones if bestm[i] != min (TODO: impl specific behaviour) + fac = + (fac & (TAU)) ^ + ((~fac) & (N % TAU)); // fac = TAU for all != min and N%TAU for min + bestm[i] += + 0x10200; // add 1 for the "1 poly" in S, and prepare rounding + bestm[i] >>= 10; // round off 10 bits + bestm[i] *= fac; + res += bestm[i]; + } + + return (res + (1 << 5)) >> 6; // return rounded, squared value +} diff --git a/crypto_sign/haetae2/m4f/polyvec.h b/crypto_sign/haetae2/m4f/polyvec.h new file mode 100644 index 00000000..d6f98673 --- /dev/null +++ b/crypto_sign/haetae2/m4f/polyvec.h @@ -0,0 +1,141 @@ +// clang-format off +#ifndef HAETAE_POLYVEC_H +#define HAETAE_POLYVEC_H + +#include "params.h" +#include "poly.h" +#include + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +typedef struct { + poly_frozen vec[K]; +} polyveck_frozen; + +#define polyveck_add HAETAE_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub HAETAE_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_double HAETAE_NAMESPACE(polyveck_double) +void polyveck_double(polyveck *b); + +#define polyveck_reduce2q HAETAE_NAMESPACE(polyveck_reduce2q) +void polyveck_reduce2q(polyveck *v); +#define polyveck_freeze2q HAETAE_NAMESPACE(polyveck_freeze2q) +void polyveck_freeze2q(polyveck *v); +#define polyveck_freeze HAETAE_NAMESPACE(polyveck_freeze) +void polyveck_freeze(polyveck *v); + +#define polyveck_uniform_eta HAETAE_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define polyveck_expand HAETAE_NAMESPACE(polyveck_expand) +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]); + +#define polyveck_ntt HAETAE_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *x); + +#define polyveck_invntt_tomont HAETAE_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *x); + +#define polyveck_double_negate HAETAE_NAMESPACE(polyveck_double_negate) +void polyveck_double_negate(polyveck *x); + +#define polyveck_frommont HAETAE_NAMESPACE(polyveck_frommont) +void polyveck_frommont(polyveck *x); + +#define polyveck_poly_pointwise_montgomery HAETAE_NAMESPACE(polyveck_poly_pointwise_montgomery) +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_poly_fromcrt HAETAE_NAMESPACE(polyveck_poly_fromcrt) +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_highbits_hint HAETAE_NAMESPACE(polyveck_highbits_hint) +void polyveck_highbits_hint(polyveck *w, const polyveck *v); + +#define polyveck_pack_highbits HAETAE_NAMESPACE(polyveck_pack_highbits) +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v); + +#define polyveck_cneg HAETAE_NAMESPACE(polyveck_cneg) +void polyveck_cneg(polyveck *v, const uint8_t b); + +#define polyveck_caddDQ2ALPHA HAETAE_NAMESPACE(polyveck_caddDQ2ALPHA) +void polyveck_caddDQ2ALPHA(polyveck *h); + +#define polyveck_csubDQ2ALPHA HAETAE_NAMESPACE(polyveck_csubDQ2ALPHA) +void polyveck_csubDQ2ALPHA(polyveck *v); + +#define polyveck_mul_alpha HAETAE_NAMESPACE(polyveck_mul_alpha) +void polyveck_mul_alpha(polyveck *v, const polyveck *u); + +#define polyveck_div2 HAETAE_NAMESPACE(polyveck_div2) +void polyveck_div2(polyveck *v); + +#define polyveck_caddq HAETAE_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); + +#define polyveck_decompose_vk HAETAE_NAMESPACE(polyveck_decompose_vk) +void polyveck_decompose_vk(polyveck *v0, polyveck *v); + +#define polyveck_sqnorm2 HAETAE_NAMESPACE(polyveck_sqnorm2) +uint64_t polyveck_sqnorm2(const polyveck *b); + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +typedef struct { + poly_frozen vec[L]; +} polyvecl_frozen; + +#define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) +void polyvecl_cneg(polyvecl *v, const uint8_t b); + +#define polyvecl_sqnorm2 HAETAE_NAMESPACE(polyvecl_sqnorm2) +uint64_t polyvecl_sqnorm2(const polyvecl *a); + +#define polyvecl_ntt HAETAE_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *x); + +#define polyvecl_highbits HAETAE_NAMESPACE(polyvecl_highbits) +void polyvecl_highbits(polyvecl *v2, const polyvecl *v); +#define polyvecl_lowbits HAETAE_NAMESPACE(polyvecl_lowbits) +void polyvecl_lowbits(polyvecl *v2, const polyvecl *v); + +#define polyvecl_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + + +/* Vectors of polynomials of length M */ +typedef struct { + poly vec[M]; +} polyvecm; + +typedef struct { + poly_frozen vec[M]; +} polyvecm_frozen; + +#define polyvecm_ntt HAETAE_NAMESPACE(polyvecm_ntt) +void polyvecm_ntt(polyvecm *x); + +#define polyvecmk_uniform_eta HAETAE_NAMESPACE(polyvecmk_uniform_eta) +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecm_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecm_pointwise_acc_montgomery) +void polyvecm_pointwise_acc_montgomery(poly *w, + const polyvecm *u, + const polyvecm *v); + +#define polyvecmk_sqsing_value HAETAE_NAMESPACE(polyvecmk_sqsing_value) +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2); + +#define polyvecmk_sing_value HAETAE_NAMESPACE(polyvecmk_sing_value) +int64_t polyvecmk_sing_value(const polyvecm *s1, const polyveck *s2); + +#endif +//clang-format on diff --git a/crypto_sign/haetae2/m4f/rans_byte.h b/crypto_sign/haetae2/m4f/rans_byte.h new file mode 100644 index 00000000..403ce20e --- /dev/null +++ b/crypto_sign/haetae2/m4f/rans_byte.h @@ -0,0 +1,333 @@ +// Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014 +// +// Not intended to be "industrial strength"; just meant to illustrate the general +// idea. + +#ifndef RANS_BYTE_HEADER +#define RANS_BYTE_HEADER + +#include + +#ifdef assert +#define RansAssert assert +#else +#define RansAssert(x) +#endif + +// READ ME FIRST: +// +// This is designed like a typical arithmetic coder API, but there's three +// twists you absolutely should be aware of before you start hacking: +// +// 1. You need to encode data in *reverse* - last symbol first. rANS works +// like a stack: last in, first out. +// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give +// it a pointer to the *end* of your buffer (exclusive), and it will +// slowly move towards the beginning as more bytes are emitted. +// 3. Unlike basically any other entropy coder implementation you might +// have used, you can interleave data from multiple independent rANS +// encoders into the same bytestream without any extra signaling; +// you can also just write some bytes by yourself in the middle if +// you want to. This is in addition to the usual arithmetic encoder +// property of being able to switch models on the fly. Writing raw +// bytes can be useful when you have some data that you know is +// incompressible, and is cheaper than going through the rANS encode +// function. Using multiple rANS coders on the same byte stream wastes +// a few bytes compared to using just one, but execution of two +// independent encoders can happen in parallel on superscalar and +// Out-of-Order CPUs, so this can be *much* faster in tight decoding +// loops. +// +// This is why all the rANS functions take the write pointer as an +// argument instead of just storing it in some context struct. + +// -------------------------------------------------------------------------- + +// L ('l' in the paper) is the lower bound of our normalization interval. +// Between this and our byte-aligned emission, we use 31 (not 32!) bits. +// This is done intentionally because exact reciprocals for 31-bit uints +// fit in 32-bit uints: this permits some optimizations during encoding. +#define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval + +// State for a rANS encoder. Yep, that's all there is to it. +typedef uint32_t RansState; + +// Initialize a rANS encoder. +static inline void RansEncInit(RansState* r) +{ + *r = RANS_BYTE_L; +} + +// Renormalize the encoder. Internal function. +static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits) +{ + uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift. + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + return x; +} + +// Encodes a single symbol with range start "start" and frequency "freq". +// All frequencies are assumed to sum to "1 << scale_bits", and the +// resulting bytes get written to ptr (which is updated). +// +// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from +// beginning to end! Likewise, the output bytestream is written *backwards*: +// ptr starts pointing at the end of the output buffer and keeps decrementing. +static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + // renormalize + RansState x = RansEncRenorm(*r, pptr, freq, scale_bits); + + // x = C(s,x) + *r = ((x / freq) << scale_bits) + (x % freq) + start; +} + +// Flushes the rANS encoder. +static inline void RansEncFlush(RansState* r, uint8_t** pptr) +{ + uint32_t x = *r; + uint8_t* ptr = *pptr; + + ptr -= 4; + ptr[0] = (uint8_t) (x >> 0); + ptr[1] = (uint8_t) (x >> 8); + ptr[2] = (uint8_t) (x >> 16); + ptr[3] = (uint8_t) (x >> 24); + + *pptr = ptr; +} + +// Initializes a rANS decoder. +// Unlike the encoder, the decoder works forwards as you'd expect. +static inline int RansDecInit(RansState* r, uint8_t** pptr) +{ + uint32_t x; + uint8_t* ptr = *pptr; + + x = ptr[0] << 0; + x |= ptr[1] << 8; + x |= ptr[2] << 16; + x |= ptr[3] << 24; + if (x < RANS_BYTE_L || (RANS_BYTE_L << 8) <= x ) + return 1; // initial state out of range + + ptr += 4; + *pptr = ptr; + *r = x; + return 0; +} + +// Returns the current cumulative frequency (map it to a symbol yourself!) +static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits) +{ + return *r & ((1u << scale_bits) - 1); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", +// and the resulting bytes get written to ptr (which is updated). +static inline void RansDecAdvance(RansState* r, uint8_t** pptr, const uint8_t* end, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + x = freq * (x >> scale_bits) + (x & mask) - start; + + // renormalize + if (x < RANS_BYTE_L && *pptr < end) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L && ptr < end); + *pptr = ptr; + } + + *r = x; +} + +// -------------------------------------------------------------------------- + +// That's all you need for a full encoder; below here are some utility +// functions with extra convenience or optimizations. + +// Encoder symbol description +// This (admittedly odd) selection of parameters was chosen to make +// RansEncPutSymbol as cheap as possible. +typedef struct { + uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval + uint32_t rcp_freq; // Fixed-point reciprocal frequency + uint32_t bias; // Bias + uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq + uint16_t rcp_shift; // Reciprocal shift +} RansEncSymbol; + +// Decoder symbols are straightforward. +typedef struct { + uint16_t start; // Start of range. + uint16_t freq; // Symbol frequency. +} RansDecSymbol; + +// Initializes an encoder symbol to start "start" and frequency "freq" +static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + RansAssert(scale_bits <= 16); + RansAssert(start <= (1u << scale_bits)); + RansAssert(freq <= (1u << scale_bits) - start); + + // Say M := 1 << scale_bits. + // + // The original encoder does: + // x_new = (x/freq)*M + start + (x%freq) + // + // The fast encoder does (schematically): + // q = mul_hi(x, rcp_freq) >> rcp_shift (division) + // r = x - q*freq (remainder) + // x_new = q*M + bias + r (new x) + // plugging in r into x_new yields: + // x_new = bias + x + q*(M - freq) + // =: bias + x + q*cmpl_freq (*) + // + // and we can just precompute cmpl_freq. Now we just need to + // set up our parameters such that the original encoder and + // the fast encoder agree. + + s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; + s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq); + if (freq < 2) { + // freq=0 symbols are never valid to encode, so it doesn't matter what + // we set our values to. + // + // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately, + // our fixed-point reciprocal approximation can only multiply by values + // smaller than 1. + // + // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0. + // This gives: + // q = mul_hi(x, rcp_freq) >> rcp_shift + // = mul_hi(x, (1<<32) - 1)) >> 0 + // = floor(x - x/(2^32)) + // = x - 1 if 1 <= x < 2^32 + // and we know that x>0 (x=0 is never in a valid normalization interval). + // + // So we now need to choose the other parameters such that + // x_new = x*M + start + // plug it in: + // x*M + start (desired result) + // = bias + x + q*cmpl_freq (*) + // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq) + // = bias + 1 + (x - 1)*M + // = x*M + (bias + 1 - M) + // + // so we have start = bias + 1 - M, or equivalently + // bias = start + M - 1. + s->rcp_freq = ~0u; + s->rcp_shift = 0; + s->bias = start + (1 << scale_bits) - 1; + } else { + // Alverson, "Integer Division using reciprocals" + // shift=ceil(log2(freq)) + uint32_t shift = 0; + while (freq > (1u << shift)) + shift++; + + s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq); + s->rcp_shift = shift - 1; + + // With these values, 'q' is the correct quotient, so we + // have bias=start. + s->bias = start; + } +} + +// Initialize a decoder symbol to start "start" and frequency "freq" +static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq) +{ + RansAssert(start <= (1 << 16)); + RansAssert(freq <= (1 << 16) - start); + s->start = (uint16_t) start; + s->freq = (uint16_t) freq; +} + +// Encodes a given symbol. This is faster than straight RansEnc since we can do +// multiplications instead of a divide. +// +// See RansEncSymbolInit for a description of how this works. +static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym) +{ + RansAssert(sym->x_max != 0); // can't encode symbol with freq=0 + + // renormalize + uint32_t x = *r; + uint32_t x_max = sym->x_max; + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + + // x = C(s,x) + // NOTE: written this way so we get a 32-bit "multiply high" when + // available. If you're on a 64-bit platform with cheap multiplies + // (e.g. x64), just bake the +32 into rcp_shift. + uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift; + *r = x + sym->bias + q * sym->cmpl_freq; +} + +// Equivalent to RansDecAdvance that takes a symbol. +static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, const uint8_t* end, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvance(r, pptr, end, sym->start, sym->freq, scale_bits); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". +// No renormalization or output happens. +static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + *r = freq * (x >> scale_bits) + (x & mask) - start; +} + +// Equivalent to RansDecAdvanceStep that takes a symbol. +static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits); +} + +// Renormalize. +static inline void RansDecRenorm(RansState* r, uint8_t** pptr) +{ + // renormalize + uint32_t x = *r; + if (x < RANS_BYTE_L) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L); + *pptr = ptr; + } + + *r = x; +} + +// Verify final state +static inline int RansDecVerify(const RansState* const r) +{ + if (*r != RANS_BYTE_L) + { + return 1; // the final state is inconsistent with the initial state + } + return 0; +} + +#endif // RANS_BYTE_HEADER \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/reduce.c b/crypto_sign/haetae2/m4f/reduce.c new file mode 100644 index 00000000..fccfa4c4 --- /dev/null +++ b/crypto_sign/haetae2/m4f/reduce.c @@ -0,0 +1,95 @@ +#include "reduce.h" +#include "params.h" +#include + +/************************************************* + * Name: montgomery_reduce + * + * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, + * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. + * + * Arguments: - int64_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t montgomery_reduce(int64_t a) { + return _montgomery_reduce(a); + /* + int32_t t; + + t = (int64_t)(int32_t)a * QINV; + t = (a - (int64_t)t * Q) >> 32; + return t; + */ +} + +/************************************************* + * Name: caddq + * + * Description: Add Q if input coefficient is negative. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* + * Name: freeze + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze(int32_t a) { + int64_t t = (int64_t)a * QREC; + t = t >> 32; + t = a - t * Q; // -2Q < t < 2Q + t += (t >> 31) & DQ; // 0 <= t < 2Q + t -= ~((t - Q) >> 31) & Q; // 0 <= t < Q + return t; +} + +/************************************************* + * Name: reduce32_2q + * + * Description: compute reduction with 2Q + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t reduce32_2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + t -= ~((t - Q) >> 31) & DQ; // centered representation + return (int32_t)t; +} + +/************************************************* + * Name: freeze2q + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ 2Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + return (int32_t)t; +} diff --git a/crypto_sign/haetae2/m4f/reduce.h b/crypto_sign/haetae2/m4f/reduce.h new file mode 100644 index 00000000..b96b1a2b --- /dev/null +++ b/crypto_sign/haetae2/m4f/reduce.h @@ -0,0 +1,41 @@ +#ifndef HAETAE_REDUCE_H +#define HAETAE_REDUCE_H + +#include "params.h" +#include + +#define MONT 14321 // 2^32 % Q +#define MONTSQ 4214 // 2^64 % Q +#define QINV 940508161 // q^(-1) mod 2^32 +#define QREC 66575 // 2^32 / Q for Barrett +#define DQREC 33287 // 2^32 / DQ for Barrett + +#define montgomery_reduce HAETAE_NAMESPACE(montgomery_reduce) +int32_t montgomery_reduce(int64_t a); + + +#define _montgomery_reduce HAETAE_NAMESPACE(_montgomery_reduce) +inline int32_t _montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a * QINV; + t = (a - (int64_t)t * Q) >> 32; + return t; +} + + + + +#define caddq HAETAE_NAMESPACE(caddq) +int32_t caddq(int32_t a); + +#define freeze HAETAE_NAMESPACE(freeze) +int32_t freeze(int32_t a); + +#define reduce32_2q HAETAE_NAMESPACE(reduce32_2q) +int32_t reduce32_2q(int32_t a); + +#define freeze2q HAETAE_NAMESPACE(freeze2q) +int32_t freeze2q(int32_t a); + +#endif diff --git a/crypto_sign/haetae2/m4f/sampler.c b/crypto_sign/haetae2/m4f/sampler.c new file mode 100644 index 00000000..4738f014 --- /dev/null +++ b/crypto_sign/haetae2/m4f/sampler.c @@ -0,0 +1,377 @@ +#include "config.h" +#include "sampler.h" +#include "fixpoint.h" +#include "symmetric.h" +#include "fast_sampler.h" +#include "fpa.h" +#include "fp84_76.h" +#include "fast_exp_asm.h" +#include +#include + +/************************************************* + * Name: rej_uniform + * + * Description: Sample uniformly random coefficients in [0, Q-1] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + uint32_t t; + + ctr = pos = 0; + while (ctr < len && pos + 2 <= buflen) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + + if (t < Q) + a[ctr++] = t; + } + return ctr; +} + +/************************************************* + * Name: rej_uniform_frozen + * + * Description: Sample uniformly random coefficients in [0, Q-1] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + uint16_t t; + + ctr = pos = 0; + while (ctr < len && pos + 2 <= buflen) { + t = buf[pos++]; + t |= (uint16_t)buf[pos++] << 8; + + if (t < Q) + a[ctr++] = t; + } + return ctr; +} + +/************************************************* + * Name: rej_eta + * + * Description: Sample uniformly random coefficients in [-ETA, ETA] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +static int32_t mod3(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq26(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq8(uint8_t t) { + int32_t r; + r = (t >> 2) + (t & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + + ctr = pos = 0; + while (ctr < len && pos < buflen) { +#if ETA == 1 + uint32_t t = buf[pos++]; + if (t < 243) { + // reduce mod 3 + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; // 171*3 = 1 mod 256 + t >>= 9; + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq26(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq8(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = (int32_t)t - (int32_t)3 * (t >> 1); + } +#elif ETA == 2 + uint32_t t0, t1; + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + if (t0 < 15) { + t0 = t0 - (205 * t0 >> 10) * 5; + a[ctr++] = 2 - t0; + } + if (t1 < 15 && ctr < len) { + t1 = t1 - (205 * t1 >> 10) * 5; + a[ctr++] = 2 - t1; + } +#endif + } + return ctr; +} + +static inline uint16_t read_gauss16_asm(const uint8_t src[GAUSS_RAND_BYTES]){ + uint16_t result; + asm( + "ldrh %[dest], [%[ptr]]": + [dest] "=r" (result): + [ptr] "r" (src) + ); + return result; +} + +static fp63_48 read_rej_asm(const uint8_t src[GAUSS_RAND_BYTES]){ + uint32_t result_lo; + uint32_t result_hi; + asm( + "ldrh %[hi], [%[ptr], #6]\n\t" + "ldr %[lo], [%[ptr], #2]": + [lo] "=r" (result_lo), [hi] "=r" (result_hi): + [ptr] "r" (src) + ); + return (fp63_48) result_hi << 32 | result_lo; +} + +void read_y_typepunning(fp84_76* y, const uint8_t src[GAUSS_RAND_BYTES]){ + y->digit[0] = ((int32_t) *(&src[8])) & ((1<<28)-1); + y->digit[1] = ((int32_t) *(&src[11])) >> 4; + y->digit[2] = ((int32_t) *(&src[13])) >> 16; +} + +/************************************************************* + * Name: read_y + * Description: Read the 72 lsb bits of y from bytes 8-16 + * of src into 28-bit digits. The nibbles of + * the high byte of byte 11 are shared between + * lo and md. No data out of bounds is being read. + *************************************************************/ +static inline void read_y(fp84_76* y, const uint8_t src[GAUSS_RAND_BYTES]){ + uint32_t result_lo; + uint32_t result_md; + uint32_t result_hi; + + asm( + "ldr %[lo], [%[ptr], #8]\n\t" // read bytes 8-11 + "ldr %[md], [%[ptr], #11]\n\t" // read bytes 11-14 + "ldrh %[hi], [%[ptr], #15]\n\t" // read bytes 15-16 + "bic %[lo], %[lo], #0xF0000000\n\t" // clear upper nibble of byte 11 + "lsr %[md], %[md], #4\n\t": // lose lower nibble of byte 11 + [lo] "=r" (result_lo), [md] "=r" (result_md), [hi] "=r" (result_hi): + [ptr] "r" (src) + ); + y->digit[0] = (digit28) result_lo; + y->digit[1] = (digit28) result_md; + y->digit[2] = (digit28) result_hi; +} + +static inline fp63_48 signed_clear_lsb(fp63_48 x) { + return (fp63_48) (x ^ (x & 1)); +} + +/*********************************************************************** + * Description: Round y/(2**16). The result has 56-bit scaling and + * 63-bit precision. + ***********************************************************************/ +static inline uint64_t compute_y_rnd(uint64_t bits_0_to_47, uint64_t bits_48_to_79){ + uint64_t result = 0; + + result = (bits_0_to_47 >> 15) ^ (bits_48_to_79 << 33); + result += 1; // rounding + result >>= 1; + return result; +}; + +static inline uint64_t compute_y84_rnd(fp84_76* y){ + uint32_t lo = y->digit[0]; + uint32_t md = y->digit[1]; + uint32_t hi = y->digit[2]; + uint64_t result; + + lo += 1 << 15; + result = lo >> 16; + result += (uint64_t) md << (28 - 16); + result += (uint64_t) hi << (56 - 16); + return result; +} + +/******************************************************************** + * Name: compute_exp_in + * Description: Compute y(y + 2kx)/(2 sigma**2) used as an + * argument in exp(-x) to determine the rejection s + * threshold. Binomial formula yields: + * (y+kx)**2 = y**2+2kxy+(kx)**2, + * hence: y(y + 2kx) == (y+kx)**2 - (kx)**2. + * We have (y+kx)**2 == [hi,md,lo] from sqr84 + * in sample_gauss_sigma76(), already. lo is rounded + * out of the result. Furthermore, kx == msb <> 1); // incorporate rounding + return result; +}; + +/******************************************************************** + * Check, whether or not the argument is zero. + ********************************************************************/ +static inline uint64_t is_zero(const uint64_t r){ + return ((r | -r) >> 63); +} + +/********************************************************************** + * Name: sample_gauss_sigma76 + * Description: Try to sample one sample from a Gaussian distribution + * + * Byte-layout of rand (packed, in order, little-endian): + * 0 - 1: rand_gauss16 (16 bits) + * 2 - 7: rand_rej (48 bits) + * 8 - 13: y.limb48[0] (48 bits) + * 14 - 16: y.limb48[1] (24 bits) + *********************************************************************/ +int sample_gauss_sigma76(uint64_t *r, fp84_76 *sqr84, const uint8_t rand[GAUSS_RAND_BYTES]){ + fp63_48 rand_rej; // value in [0.0, 1.0) + fp8_4 y_msb; // most significant bits of y, value in [0, 64] (i.e., 0x00 to 0x40) + fp63_48 exp_in; // value in [0.0, 0.25] + fp84_76 y84; + uint16_t rand_gauss16; + +#ifdef ENABLE_COUNT_CALLS_TO_SAMPLE_GAUSS_SIGMA_76 + counter_calls_to_sample_gauss_sigma76 += 1; +#endif + rand_gauss16 = read_gauss16_asm(rand); + y_msb = haetae_fast_sample_gauss16(rand_gauss16); + read_y(&y84, rand); + y84.digit[2] |= (y_msb << 16); + *r = compute_y84_rnd(&y84); + fp84_76_square(sqr84, &y84); + exp_in = compute_exp_in(sqr84->digit[2], sqr84->digit[1], y_msb); +#ifdef PQC_GEN_KAT_ACTIVE + //log_error_with_int64_t("r: ", *r); + //log_error_with_fp84_76("y84: ", &y84.digit[0]); + //log_error_with_int64_t("exp_in: ", (int64_t) exp_in); +#endif + rand_rej = read_rej_asm(rand); + return ( + ( + ( + signed_clear_lsb(rand_rej) // set lowest bit to zero in order to + // use it for rejection if sample==0 + - (int64_t)haetae_approx_exp_asm(exp_in) + ) >> 63 // reject with prob 1-approx_exp(exp_in) + ) + & (is_zero(*r) | rand_rej)) + & 1; // if the sample is zero, clear the return value with prob 1/2 +} + +int sample_gauss(uint64_t *r, fp112_76 *sqsum, const uint8_t *buf, const size_t buflen, const size_t len, const int dont_write_last) +{ + const uint8_t *pos = buf; + fp84_76 sqr84; + size_t bytecnt = buflen, coefcnt = 0, cnt = 0; + int accepted; + uint64_t extra_coefficient; // used to sample the two extra coefficients + + while (coefcnt < len) { + if (bytecnt < GAUSS_RAND_BYTES) { + return coefcnt; + } + + if (dont_write_last && coefcnt == len-1) + { + accepted = sample_gauss_sigma76(&extra_coefficient, &sqr84, pos); + } else { + accepted = sample_gauss_sigma76(&r[coefcnt], &sqr84, pos); + } + cnt += 1; + coefcnt += accepted; + pos += GAUSS_RAND_BYTES; + bytecnt -= GAUSS_RAND_BYTES; + + conditional_accumulate_fp112_96(sqsum, &sqr84, accepted); + normalize_fp112_96(sqsum); + } + + return len; +} + +#define POLY_HYPERBALL_BUFLEN (GAUSS_RAND_BYTES * N) +#define POLY_HYPERBALL_NBLOCKS ((POLY_HYPERBALL_BUFLEN + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp112_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len) { + uint8_t buf[POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES]; + size_t bytecnt, coefcnt, firstflag = 1; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_HYPERBALL_NBLOCKS, &state); + for (size_t i = 0; i < len / 8; i++) { + signs[i] = buf[i]; + } + bytecnt = POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES - len / 8; + coefcnt = sample_gauss(r, sqsum, buf + len / 8, bytecnt, len, len%N); + while (coefcnt < len) { + size_t off = bytecnt % GAUSS_RAND_BYTES; + for (size_t i = 0; i < off; i++) { + buf[i] = buf[bytecnt + len/8*firstflag - off + i]; + } + stream256_squeezeblocks(buf + off, 1, &state); + bytecnt = STREAM256_BLOCKBYTES + off; + + coefcnt += sample_gauss(r + coefcnt, sqsum, buf, bytecnt, len - coefcnt, len%N); + firstflag = 0; + } +} diff --git a/crypto_sign/haetae2/m4f/sampler.h b/crypto_sign/haetae2/m4f/sampler.h new file mode 100644 index 00000000..56697229 --- /dev/null +++ b/crypto_sign/haetae2/m4f/sampler.h @@ -0,0 +1,35 @@ +#ifndef HAETAE_SAMPLER_H +#define HAETAE_SAMPLER_H + +#include "fixpoint.h" +#include "params.h" +#include "reduce.h" +#include "fpa.h" +#include + +#define rej_uniform HAETAE_NAMESPACE(rej_uniform) +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); + +#define rej_uniform_frozen HAETAE_NAMESPACE(rej_uniform_frozen) +unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); + +#define rej_eta HAETAE_NAMESPACE(rej_eta) +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); + +#define GAUSS_RAND_BYTES (((72 + 16 + 48) + 7) / 8) +#define sample_gauss_sigma76 HAETAE_NAMESPACE(sample_gauss_sigma76) +int sample_gauss_sigma76(uint64_t *r, fp84_76 *sqr84, const uint8_t rand[GAUSS_RAND_BYTES]); + +#define sample_gauss HAETAE_NAMESPACE(sample_gauss) +int sample_gauss(uint64_t *r, fp112_76 *sqsum, const uint8_t *buf, const size_t buflen, + const size_t len, const int dont_write_last); + +#define sample_gauss_N HAETAE_NAMESPACE(sample_gauss_N) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp112_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len); + +#endif diff --git a/crypto_sign/haetae2/m4f/sign.c b/crypto_sign/haetae2/m4f/sign.c new file mode 100644 index 00000000..dd7b6449 --- /dev/null +++ b/crypto_sign/haetae2/m4f/sign.c @@ -0,0 +1,919 @@ +#include "sign.h" +#include "packing.h" +#include "params.h" +#include "poly.h" +#include "polyfix.h" +#include "polymat.h" +#include "polyvec.h" +#include "randombytes.h" +#include "symmetric.h" +#include "decompose.h" +#include +#include +#include +#include + + +/************************************************* + * Name: generate_seed_from_one_source + * + * Description: Use SHAKE256 to generate a seed from one byte source. + * + * Arguments: - uint8_t *seed: pointer to buffer of seed to be generated + * - size_t seed_len: desired length of the seed + * - uint8_t *src: pointer to source to be absorbed + * - size_t src_len: length of source + * + * Returns void + **************************************************/ +static void generate_seed_from_one_source(uint8_t *seed, size_t seed_len, + const uint8_t *src, size_t src_len){ + xof256_state state; + xof256_absorb_once(&state, src, src_len); + xof256_squeeze(seed, seed_len, &state); + return; +} + +/************************************************* + * Name: generate_seed_from_two_sources + * + * Description: Use SHAKE256 to generate a seed from two byte sources. + * + * Arguments: - uint8_t *seed: pointer to buffer of seed to be generated + * - size_t seed_len: desired length of the seed + * - uint8_t *src1: pointer to first source to be absorbed + * - size_t src1_len: length of first source + * - uint8_t *src2: pointer to second source to be absorbed + * - size_t src2_len: length of second source + * + * Returns void + **************************************************/ +static void generate_seed_from_two_sources(uint8_t *seed, size_t seed_len, + const uint8_t *src1, size_t src1_len, + const uint8_t *src2, size_t src2_len){ + xof256_state state; + xof256_absorb_twice(&state, src1, src1_len, src2, src2_len); + xof256_squeeze(seed, seed_len, &state); + return; +} + +static inline uint16_t nonce_a(const size_t row){ + return (K << 8) + M + row; +} +static inline uint16_t nonce_A_gen(const size_t row, const size_t column){ + return (row << 8) + column; +} +static inline uint16_t nonce_s_gen(const size_t nonce_offset, const size_t column){ + return nonce_offset + column; +} +static inline uint16_t nonce_e_gen(const size_t nonce_offset, const size_t row){ + return nonce_offset + M + row; +} + +static void pointwise_montgomery_by_A_gen_elem_frozen(poly *dest, + const uMatrixPointerM_frozen agenptr, + const size_t row, const size_t column, const poly *src){ +#ifdef ENABLE_KEYPAIR_MATRIX_BUFFER + poly_pointwise_montgomery_mixed(dest, &agenptr.vec[row].vec[column], src); +#else + poly_frozen a_gen_elem; + poly_uniform_frozen(&a_gen_elem, agenptr.seed, nonce_A_gen(row, column)); + poly_pointwise_montgomery_mixed(dest, &a_gen_elem, src); +#endif /* ENABLE_KEYPAIR_MATRIX_BUFFER */ +} + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### + +/************************************************* + * Name: crypto_sign_keypair + * + * Description: Generates public and private key. + * + * Arguments: - uint8_t *pk: pointer to output public key (allocated + * array of CRYPTO_PUBLICKEYBYTES bytes) + * - uint8_t *sk: pointer to output private key (allocated + * array of CRYPTO_SECRETKEYBYTES bytes) + * + * Returns 0 (success) + **************************************************/ + +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES] = {0}; + uint16_t nonce = 0; + const uint8_t *rhoprime; + const uint8_t *sigma; + const uint8_t *key; + polyvecm s_gen; + polyveck e_gen; + polyveck b; + poly temp_poly; + +#if D > 0 + polyveck a; +#endif +#ifdef ENABLE_KEYPAIR_MATRIX_BUFFER + polyvecm_frozen A_gen[K]; + uMatrixPointerM_frozen A_gen_ptr = { .vec = A_gen }; +#else + uMatrixPointerM_frozen A_gen_ptr = { .seed = seedbuf }; +#endif + + // Get entropy \rho + randombytes(seedbuf, SEEDBYTES); + // Sample seeds with entropy \rho + generate_seed_from_one_source(seedbuf, 2 * SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES); + + rhoprime = seedbuf; + sigma = rhoprime + SEEDBYTES; + key = sigma + CRHBYTES; + +#ifdef ENABLE_KEYPAIR_MATRIX_BUFFER + // Expand Matrix A0 and vector a + for (size_t row = 0; row < K; ++row){ + for (size_t column = 0; column < M; ++column){ + poly_uniform_frozen(&A_gen[row].vec[column], rhoprime, nonce_A_gen(row, column)); + } + } +#endif + +#if D > 0 + /********************************************** + * If there is rounding (D > 0), we need another polyveck a. + * Then, b = a + A0 * s_gen + e_gen and the lower D bits are + * rounded from b. The lower D bits are subsequently + * subtracted from e_gen. + **********************************************/ + for (size_t row = 0; row < K; ++row){ + poly_uniform(&a.vec[row], rhoprime, nonce_a(row)); + } + +reject: + // Sample secret vectors s_gen and e_gen + for (size_t column = 0; column < M; column++){ + poly_uniform_eta(&s_gen.vec[column], sigma, nonce_s_gen(nonce, column)); + } + for (size_t row = 0; row < K; row++){ + poly_uniform_eta(&e_gen.vec[row], sigma, nonce_e_gen(nonce, row)); + } + nonce += M + K; + + // b = a + A0 * s_gen + e_gen mod q + { + poly s_gen_hat_elem; + + // column 0 + s_gen_hat_elem = s_gen.vec[0]; + poly_ntt(&s_gen_hat_elem); + for (size_t row = 0; row < K; row++){ + pointwise_montgomery_by_A_gen_elem_frozen(&b.vec[row], A_gen_ptr, row, 0, &s_gen_hat_elem); + } + // columns 1 to M-1 + for (size_t column = 1; column < M; column++){ + s_gen_hat_elem = s_gen.vec[column]; + poly_ntt(&s_gen_hat_elem); + for (size_t row = 0; row < K; row++){ + pointwise_montgomery_by_A_gen_elem_frozen(&temp_poly, A_gen_ptr, row, column, &s_gen_hat_elem); + poly_add(&b.vec[row], &b.vec[row], &temp_poly); + } + } + } + + for (size_t row = 0; row < K; row++){ + poly *b_elem = &b.vec[row]; + poly *e_gen_elem = &e_gen.vec[row]; + + poly_invntt_tomont(b_elem); + poly_add(b_elem, b_elem, e_gen_elem); + poly_add(b_elem, b_elem, &a.vec[row]); + poly_freeze(b_elem); + // round off D bits + poly_decompose_vk(&temp_poly, b_elem); + poly_sub(e_gen_elem, e_gen_elem, &temp_poly); + } + + int64_t squared_singular_value = polyvecmk_sqsing_value(&s_gen, &e_gen); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } +#else + /********************************************** + * If there is no rounding (D == 0), we store + * -2b directly in NTT domain into the public key. + **********************************************/ +reject: + // Sample secret vectors s_gen and e_gen + // Sample secret vectors s_gen and e_gen + for (size_t column = 0; column < M; column++){ + poly_uniform_eta(&s_gen.vec[column], sigma, nonce_s_gen(nonce, column)); + } + for (size_t row = 0; row < K; row++){ + poly_uniform_eta(&e_gen.vec[row], sigma, nonce_e_gen(nonce, row)); + } + nonce += M + K; + + int64_t squared_singular_value = polyvecmk_sqsing_value(&s_gen, &e_gen); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } + + { + // b = A0 * s_gen + poly s_gen_hat_elem; + + // column 0 + s_gen_hat_elem = s_gen.vec[0]; + poly_ntt(&s_gen_hat_elem); + for (size_t row = 0; row < K; row++){ + pointwise_montgomery_by_A_gen_elem_frozen(&b.vec[row], A_gen_ptr, row, 0, &s_gen_hat_elem); + } + // columns 1 to M-1 + for (size_t column = 1; column < M; column++){ + s_gen_hat_elem = s_gen.vec[column]; + poly_ntt(&s_gen_hat_elem); + for (size_t row = 0; row < K; row++){ + pointwise_montgomery_by_A_gen_elem_frozen(&temp_poly, A_gen_ptr, row, column, &s_gen_hat_elem); + poly_add(&b.vec[row], &b.vec[row], &temp_poly); + } + } + } + + // b += e_gen mod q + for (size_t row = 0; row < K; row++){ + poly s2hat_elem; + + s2hat_elem = e_gen.vec[row]; + poly_ntt(&s2hat_elem); + poly_frommont(&b.vec[row]); + poly_add(&b.vec[row], &b.vec[row], &s2hat_elem); + poly_double_negate(&b.vec[row]); + poly_caddq(&b.vec[row]); + } + +#endif + + pack_pk(pk, &b, rhoprime); + pack_sk(sk, pk, &s_gen, &e_gen, key); + + return 0; +} + + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### + +/************************************************* + * Name: make_hint_veck + * + * Description: Make hint from z2, Ay and highbits(z2) + * + * Arguments: - polyveck *h: pointer to the hint + * - polyfixveck *z2: pointer to z2 + * - polyveck *Ay: pointer to Ay + * - polyveck *highbits: highbits(z2) + * + * Returns void + **************************************************/ +static void make_hint_veck(polyveck *h, const polyfixveck *z2, const polyveck *Ay, const polyveck *highbits){ + poly z2rnd;// round of z2 + poly htmp; + + for (size_t row = 0; row < K; row ++){ + // Round z2 + polyfix_round(&z2rnd, &z2->vec[row]); + // recover htmp == A1 * round(z1) - qcj mod 2q + poly_double(&z2rnd); + poly_sub(&htmp, &Ay->vec[row], &z2rnd); + poly_freeze2q(&htmp); + + // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) + poly_highbits_hint(&htmp, &htmp); + poly_sub(&h->vec[row], &highbits->vec[row], &htmp); + poly_caddDQ2ALPHA(&h->vec[row]); + } +} + +/************************************************* + * Name: decompose_z1_vecl + * + * Description: decompose z1 into LowBits and HighBits + * + * Arguments: - polyvecl *lb_z1: pointer to LowBits(z1) + * - polyvecl *hb_z1: pointer to HighBits(z1) + * - polyfixvecl *z1: pointer to z1 + * + * Returns void + **************************************************/ +static void decompose_z1_vecl(polyvecl *lb_z1, polyvecl *hb_z1, const polyfixvecl *z1){ + poly z1rnd; // rounded polynomial of z1 + + for (size_t column = 0; column < L; column++){ + polyfix_round(&z1rnd, &z1->vec[column]); + poly_lowbits(&lb_z1->vec[column], &z1rnd); + poly_highbits(&hb_z1->vec[column], &z1rnd); + } +} + +/************************************************* + * Name: compute_z_veckl + * + * Description: Compute z1 and z2, where z == (z1 || z2) is a candidate + * for the uncompressed signature. + * + * Arguments: - polyfixvecl *z1: part of the signature candidate + * - polyfixveck *z2: part of the signature candidate + * - uint8_t cseed: seed of the challenge polynomial + * - polyvecm *s1: part of the secret key, NTT domain + * - polyveck *s2: part of the secret key, NTT domain + * - polyfixvecl *y1: part of the uniform samples from the hyperball + * - polyfixveck *y2: part of the uniform samples from the hyperball + * - uint8_t b: a random byte for bimodal selection + * + * Returns void + **************************************************/ +static void compute_z_veckl(polyfixvecl *z1, polyfixveck *z2, const uint8_t cseed[SEEDBYTES], + const polyvecm *s1, const polyveck *s2, + const polyfixvecl *y1, const polyfixveck *y2, const uint8_t b){ + poly c; + poly t; + + // c = challenge(c_seed) + poly_challenge(&c, cseed); + + // t = (c * s).vec[i] = (c * (1 || s1 || s2)).vec[i] + // z = y + (-1)^b (c * s) = z1 || z2 + + // z1[0] + t = c; + poly_cneg(&t, b & 1); + polyfix_add(&z1->vec[0], &y1->vec[0], &t); + + // z1.vec[1..L-1] + poly_ntt(&c); + for (size_t column = 1; column < L; ++column) { + poly_pointwise_montgomery(&t, &c, &s1->vec[column - 1]); + poly_invntt_tomont(&t); + poly_cneg(&t, b & 1); + polyfix_add(&z1->vec[column], &y1->vec[column], &t); + } + + // z2.vec[0..K-1] + for (size_t row = 0; row < K; row++) { + poly_pointwise_montgomery(&t, &s2->vec[row], &c); + poly_invntt_tomont(&t); + poly_cneg(&t, b & 1); + polyfix_add(&z2->vec[row], &y2->vec[row], &t); + } +}; + +/************************************************* + * Name: is_norm_of_z_geq_big_b_prime + * + * Description: Test whether norm(z) >= B' + * + * Arguments: - polyfixvecl *z1: part of the signature candidate + * - polyfixveck *z2: part of the signature candidate + * + * Returns 0 if the test passed, 1 if the signature needs to be rejected. + **************************************************/ +static uint64_t is_norm_of_z_geq_big_b_prime(const polyfixvecl *z1, const polyfixveck *z2){ + uint64_t reject1; + + // reject if norm(z) >= B' + reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(z1, z2)) >> 63; + reject1 &= 1; // get the sign + return reject1; +}; + +/************************************************* + * Name: is_rejected_in_intersection + * + * Description: In bimodal sampling the sample may lie in the intersection of both + * hyperballs of radius r', in which case the sample is rejected + * with a probability of 50%. + * + * Arguments: - polyfixvecl *z1: part of the signature candidate + * - polyfixveck *z2: part of the signature candidate + * - polyfixvecl *y1: part of the uniform samples from the hyperball + * - polyfixveck *y2: part of the uniform samples from the hyperball + * - uint8_t b: a random byte for bimodal selection, this function + * uses bits corresponding to the mask 0x02 + * + * Returns 0 if the test passed, 1 if the signature needs to be rejected. + **************************************************/ +static uint64_t is_rejected_in_intersection(const polyfixvecl *z1, const polyfixveck *z2, const polyfixvecl *y1, const polyfixveck *y2, uint8_t b){ + polyfix tmp; + uint64_t reject2; + uint64_t sqnorm2 = - (uint64_t)B0SQ * LN * LN; + + for (size_t column = 0; column < L; column++){ + polyfix_double(&tmp, &z1->vec[column]); + polyfix_sub(&tmp, &tmp, &y1->vec[column]); + sqnorm2 += polyfix_sqnorm2(&tmp); + } + + for (size_t row = 0; row < K; row++){ + polyfix_double(&tmp, &z2->vec[row]); + polyfix_sub(&tmp, &tmp, &y2->vec[row]); + sqnorm2 += polyfix_sqnorm2(&tmp); + } + + // reject if norm(2z-y) < B and b' = 0 + reject2 = sqnorm2 >> 63; + reject2 &= 1; // get the sign, 1 indicates that the sample lies in the overlap region + reject2 &= (b & 0x2) >> 1; // if sample is in the overlap region, reject with 50% probability + return reject2; +} + + +/************************************************* + * Name: multiply_a1_by_rounded_y1_mod_q + * + * Description: Computes Ay = A1 * round(y1) mod q and a copy of round(y1)[0]. + * Subfunction of compute_challenge_seed() + * + * Arguments: - poly *z1rnd0: round(y1)[0], not in Montgomery domain + * - polyveck *Ay: vector mod q + * - polyfixvecl *y1: part of the hyperball samples + * - polyvecl A1[K]: matrix A1 + * + * Returns void + **************************************************/ +static void multiply_a1_by_rounded_y1_mod_q(poly *z1rnd0, + polyveck *Ay, + const polyfixvecl *y1, + uMatrixPointerL_frozen a1ptr){ + poly z1rnd; + poly t; +#ifdef ENABLE_SIGNATURE_MATRIX_BUFFER + const poly_frozen *a1_poly_ptr; +#else + poly_frozen a1_poly; + poly_frozen *a1_poly_ptr = &a1_poly; +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + + + polyfix_round(&z1rnd, &y1->vec[0]); + poly_clone(z1rnd0, &z1rnd); + poly_ntt(&z1rnd); + + for (size_t row = 0; row < K; ++row) { +#ifdef ENABLE_SIGNATURE_MATRIX_BUFFER + a1_poly_ptr = &a1ptr.vec[row].vec[0]; +#else + expand_pk_matrix_elem_frozen(a1_poly_ptr, row, 0, a1ptr.seed); +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + poly_pointwise_montgomery_mixed(&Ay->vec[row], a1_poly_ptr, &z1rnd); + } + + for (size_t column = 1; column < L; ++column) { + polyfix_round(&z1rnd, &y1->vec[column]); + poly_ntt(&z1rnd); + for (size_t row = 0; row < K; ++row) { +#ifdef ENABLE_SIGNATURE_MATRIX_BUFFER + a1_poly_ptr = &a1ptr.vec[row].vec[column]; +#else + expand_pk_matrix_elem_frozen(a1_poly_ptr, row, column, a1ptr.seed); +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + poly_pointwise_montgomery_mixed(&t, a1_poly_ptr, &z1rnd); + poly_add(&Ay->vec[row], &Ay->vec[row], &t); + } + } + polyveck_invntt_tomont(Ay); +}; + +/************************************************* + * Name: accumulate_two_times_rounded_y2_mod_q + * + * Description: Accumulates 2 * round(y2) mod q to Ay + * Subfunction of compute_challenge_seed() + * + * Arguments: - polyveck *Ay: vector mod q + * - polyfixveck *y2: part of the hyperball samples + * + * Returns void + **************************************************/ +static void accumulate_two_times_rounded_y2_mod_q(polyveck *Ay, const polyfixveck *y2){ + polyveck z2rnd; + + // Round y2 + polyfixveck_round(&z2rnd, y2); + + // Ay += 2 * round(y2) mod q + polyveck_double(&z2rnd); + polyveck_add(Ay, Ay, &z2rnd); +} + +/************************************************* + * Name: compute_challenge_seed + * + * Description: Computes a challenge seed, Ay and HighBits(hint) + * + * Arguments: - uint8_t *cseed[SEEDBYTES]: seed to expand challenge polynomial from + * - polyveck *Ay: A1 * round(y1) + 2 * round(y2) mod q + * - polyveck *highbits: HighBits of hint (A * round(y) mod 2q) + * - const polyvecl *A1[K]: public key matrix + * - const polyfixvecl *y1: part of the hyperball samples + * - const polyfixveck *y2: part of the hyperball samples + * - const uint8_t *mu[SEEDBYTES]: seed generated from secret key and message + * + * Returns 0 (success) + **************************************************/ +static void compute_challenge_seed(uint8_t cseed[SEEDBYTES], polyveck *Ay, polyveck *highbits, + const uMatrixPointerL_frozen a1ptr, const polyfixvecl *y1, + const polyfixveck *y2, const uint8_t mu[SEEDBYTES]){ + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + poly z1rnd0; + poly lsb; + + // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q + multiply_a1_by_rounded_y1_mod_q(&z1rnd0, Ay, y1, a1ptr); + accumulate_two_times_rounded_y2_mod_q(Ay, y2); + + // recover A * round(y) mod 2q + polyveck_poly_fromcrt(Ay, Ay, &z1rnd0); + polyveck_freeze2q(Ay); + + // HighBits of (A * round(y) mod 2q) + polyveck_highbits_hint(highbits, Ay); + + // LSB(round(y_0) * j) + poly_lsb(&lsb, &z1rnd0); + + // Pack HighBits of A * round(y) mod 2q and LSB of round(y0) + polyveck_pack_highbits(buf, highbits); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); + + // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + generate_seed_from_two_sources(cseed, SEEDBYTES, + buf, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, + mu, SEEDBYTES); + return; +}; + +/************************************************* + * Name: compress_and_pack_signature + * + * Description: Compress and pack the components of the signature + * + * Arguments: - uint8_t *sig: pointer to output signature (of length + * CRYPTO_BYTES) + * - size_t *siglen: pointer to output length of signature + * + * Returns 0 (success) or 1 (fail) + **************************************************/ +static int compress_and_pack_signature( + uint8_t *sig, + uint8_t cseed[SEEDBYTES], + const polyfixvecl *z1, + const polyfixveck *z2, + const polyveck *Ay, + const polyveck *highbits +){ + polyvecl hb_z1, lb_z1; + polyveck h; + /*------------------- 4. Make a hint and decompose z1 -----------*/ + make_hint_veck(&h, z2, Ay, highbits); + decompose_z1_vecl(&lb_z1, &hb_z1, z1); + + /*------------------ Pack signature -----------------------------*/ + if (pack_sig(sig, cseed, &lb_z1, &hb_z1, &h)) { // reject if signature is too big + return 1; + } + return 0; +} + +/************************************************* + * Name: crypto_sign_signature + * + * Description: Computes signature. + * + * Arguments: - uint8_t *sig: pointer to output signature (of length + * CRYPTO_BYTES) + * - size_t *siglen: pointer to output length of signature + * - uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk) { + + uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; + uint8_t mu[SEEDBYTES] = {0}; + uint8_t cseed[SEEDBYTES] = {0}; // seed of a challenge polynomial c + uint8_t b = 0; // one bit + uint16_t counter = 0; + uint64_t reject1, reject2; + + polyvecm s1; + polyveck s2, highbits, Ay; + polyfixvecl y1, z1; + polyfixveck y2, z2; + +#ifdef ENABLE_SIGNATURE_MATRIX_BUFFER + polyvecl_frozen A1[K]; + uMatrixPointerL_frozen a1ptr = { .vec = A1}; +#else + uMatrixPointerL_frozen a1ptr = { .seed = sk }; +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + + // Unpack secret key + unpack_sk(a1ptr.vec, &s1, &s2, key, sk); + +#ifndef ENABLE_SIGNATURE_MATRIX_BUFFER +#endif /* ENABLE_SIGNATURE_MATRIX_BUFFER */ + + generate_seed_from_two_sources(mu, SEEDBYTES, sk, CRYPTO_PUBLICKEYBYTES, m, mlen); + generate_seed_from_two_sources(seedbuf, CRHBYTES, key, SEEDBYTES, mu, SEEDBYTES); + + polyvecm_ntt(&s1); + polyveck_ntt(&s2); + +reject: + + /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ + randombytes(&b, sizeof(uint8_t)); + +#ifdef ENABLE_TWO_PASS_SAMPLING + counter = polyfixveclk_two_pass_sample_hyperball(&y1, &y2, seedbuf, counter); +#else + counter = polyfixveclk_sample_hyperball(&y1, &y2, seedbuf, counter); +#endif + + /*------------------- 2. Compute a challenge c --------------------------*/ + compute_challenge_seed(cseed, &Ay, &highbits, a1ptr, &y1, &y2, mu); + + /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ + compute_z_veckl(&z1, &z2, cseed, &s1, &s2, &y1, &y2, b); + + reject1 = is_norm_of_z_geq_big_b_prime(&z1, &z2); + reject2 = is_rejected_in_intersection(&z1, &z2, &y1, &y2, b); + if (reject1 | reject2) { + goto reject; + } + + /*------------------- 4. Make a hint and decompose z1 -----------*/ + /*------------------ Pack signature -----------------------------*/ + if (0 != compress_and_pack_signature(sig, cseed, &z1, &z2, &Ay, &highbits)) + goto reject; + *siglen = CRYPTO_BYTES; + + return 0; +} + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### + +/************************************************* + * Name: crypto_sign + * + * Description: Compute signed message. + * + * Arguments: - uint8_t *sm: pointer to output signed message (allocated + * array with CRYPTO_BYTES + mlen bytes), + * can be equal to m + * - size_t *smlen: pointer to output length of signed + * message + * - const uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - const uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t i; + + for (i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + *smlen += mlen; + return 0; +} + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### + +static int unpack_cseed_z1_and_hint_from_sig(uint8_t c_seed[SEEDBYTES], polyvecl *z1, + polyveck *h, const uint8_t sig[CRYPTO_BYTES]){ + polyvecl highbits_z1; + + // Unpack signature and Check conditions -- low bits are stored in z1 + if (unpack_sig(c_seed, &highbits_z1, z1, h, sig)) { + return -1; + } + + // Compose z1 out of HighBits(z1) and LowBits(z1) + for (size_t row = 0; row < L; ++row) { + poly_compose(&z1->vec[row], &z1->vec[row], &highbits_z1.vec[row]); + } + return 0; +} + +static void poly_csubDQ2ALPHA(poly *v) { + unsigned int j; + for (j = 0; j < N; j++) { + v->coeffs[j] -= + ~((v->coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & + ((DQ - 2) / ALPHA_HINT); + } +} + +static void poly_mul_alpha(poly *v, const poly *u) { + unsigned int j; + for (j = 0; j < N; j++) { + v->coeffs[j] = u->coeffs[j] * ALPHA_HINT; + } +} + +static void poly_div2(poly *v) { + unsigned j; + for (j = 0; j < N; ++j) + v->coeffs[j] >>= 1; +} + +/************************************************* + * Name: crypto_sign_verify + * + * Description: Verifies signature. + * + * Arguments: - uint8_t *m: pointer to input signature + * - size_t siglen: length of signature + * - const uint8_t *m: pointer to message + * - size_t mlen: length of message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signature could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk) { + unsigned int i; + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + uint8_t c_seed[SEEDBYTES] = {0}, c_seed2[SEEDBYTES] = {0}; + uint8_t rhoprime[SEEDBYTES] = {0}; + uint64_t sqnorm2; + polyvecl z1; + polyveck b; + polyveck highbits; + polyveck h; + polyveck z2; + polyveck w; + poly c; + poly wprime; + + // Check signature length + if (siglen != CRYPTO_BYTES) { + return -1; + } + + // Unpack public key + unpack_pk(&b, rhoprime, pk); + unpack_cseed_z1_and_hint_from_sig(c_seed, &z1, &h, sig); + + /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ + // c = challenge(c_seed) + poly_challenge(&c, c_seed); + + // compute w' = lsb(z1[0] - c) and the squared norm of z1 before NTT + sqnorm2 = polyvecl_sqnorm2(&z1); + poly_sub(&wprime, &z1.vec[0], &c); + poly_lsb(&wprime, &wprime); + + // A1 * round(z1) - qcj mod q + for (size_t column = 0; column < L; column++) { + poly_ntt(&z1.vec[column]); + } + // highbits = A1 * z1 + for (size_t row = 0; row < K; ++row) { + poly t; + poly_frozen a1_elem; // we need A1 only once, so compute its elements on demand + + expand_pk_matrix_elem_frozen(&a1_elem, row, 0, pk); + poly_pointwise_montgomery_mixed(&highbits.vec[row], &a1_elem, &z1.vec[0]); + for (size_t column = 1; column < L; ++column) { + expand_pk_matrix_elem_frozen(&a1_elem, row, column, pk); + poly_pointwise_montgomery_mixed(&t, &a1_elem, &z1.vec[column]); + poly_add(&highbits.vec[row], &highbits.vec[row], &t); + } + poly_invntt_tomont(&highbits.vec[row]); + } + + // recover A1 * round(z1) - qcj mod 2q + + for (size_t row = 0; row < K; ++row){ + poly *highbits_elem_ptr = &highbits.vec[row]; + poly *h_elem_ptr; + poly *w_elem_ptr; + poly *z2_elem_ptr; + + h_elem_ptr = &h.vec[row]; + w_elem_ptr = &w.vec[row]; + z2_elem_ptr = &z2.vec[row]; + + + if (0 == row) { + poly_fromcrt(highbits_elem_ptr, highbits_elem_ptr, &wprime); + } else { + poly_fromcrt0(highbits_elem_ptr, highbits_elem_ptr); + } + poly_freeze2q(highbits_elem_ptr); + // recover w1 + poly_highbits_hint(w_elem_ptr, highbits_elem_ptr); + poly_add(w_elem_ptr, w_elem_ptr, h_elem_ptr); + poly_csubDQ2ALPHA(w_elem_ptr); + // recover \tilde{z}_2 mod q + poly_mul_alpha(z2_elem_ptr, w_elem_ptr); + poly_sub(z2_elem_ptr, z2_elem_ptr, highbits_elem_ptr); + if (0 == row) { + poly_add(z2_elem_ptr, z2_elem_ptr, &wprime); + } + poly_reduce2q(z2_elem_ptr); + poly_div2(z2_elem_ptr); + } + + // check final norm of \tilde{z} + if (sqnorm2 + polyveck_sqnorm2(&z2) > B2SQ) { + return -1; + } + + /*------------------- 3. Compute c_seed' and Compare ---------------------*/ + + // Pack highBits(A * round(z) - qcj mod 2q) and h' + polyveck_pack_highbits(buf, &w); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); + + generate_seed_from_two_sources(c_seed2, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); + + // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + generate_seed_from_two_sources(c_seed2, SEEDBYTES, + buf, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, + c_seed2, SEEDBYTES); + + for (i = 0; i < SEEDBYTES; ++i) { + if (c_seed[i] != c_seed2[i]) { + return -1; + } + } + return 0; +} + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### + +/************************************************* + * Name: crypto_sign_open + * + * Description: Verify signed message. + * + * Arguments: - uint8_t *m: pointer to output message (allocated + * array with smlen bytes), can be equal to sm + * - size_t *mlen: pointer to output length of message + * - const uint8_t *sm: pointer to signed message + * - size_t smlen: length of signed message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signed message could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + size_t i; + + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if (crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for (i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + for (i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} + +// ################################################################### +// ################################################################### +// ################################################################### +// ################################################################### diff --git a/crypto_sign/haetae2/m4f/sign.h b/crypto_sign/haetae2/m4f/sign.h new file mode 100644 index 00000000..cee7fb2f --- /dev/null +++ b/crypto_sign/haetae2/m4f/sign.h @@ -0,0 +1,40 @@ +#ifndef HAETAE_SIGN_H +#define HAETAE_SIGN_H + +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include +#include + +typedef union MatrixPointerL_frozen{ + const uint8_t *seed; + polyvecl_frozen *vec; +} uMatrixPointerL_frozen; + +typedef union MatrixPointerM_frozen{ + const uint8_t *seed; + polyvecm_frozen *vec; +} uMatrixPointerM_frozen; + +#define crypto_sign_keypair HAETAE_NAMESPACE(keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature HAETAE_NAMESPACE(signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk); + +#define crypto_sign HAETAE_NAMESPACE(sign) +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify HAETAE_NAMESPACE(verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk); + +#define crypto_sign_open HAETAE_NAMESPACE(open) +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif // HAETAE_SIGN_H \ No newline at end of file diff --git a/crypto_sign/haetae2/m4f/symmetric-shake.c b/crypto_sign/haetae2/m4f/symmetric-shake.c new file mode 100644 index 00000000..9fedb325 --- /dev/null +++ b/crypto_sign/haetae2/m4f/symmetric-shake.c @@ -0,0 +1,59 @@ +#include "fips202.h" +#include "params.h" +#include "symmetric.h" +#include + +void haetae_shake128_stream_init(stream128_state *state, + const uint8_t seed[SEEDBYTES], + uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake128_inc_init(state); + shake128_inc_absorb(state, seed, SEEDBYTES); + shake128_inc_absorb(state, t, 2); + shake128_inc_finalize(state); +} + +void haetae_shake256_stream_init(stream256_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake256_inc_init(state); + shake256_inc_absorb(state, seed, CRHBYTES); + shake256_inc_absorb(state, t, 2); + shake256_inc_finalize(state); +} + +void haetae_shake256_absorb_twice(xof256_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, + size_t in2len) { + shake256_inc_init(state); + shake256_inc_absorb(state, in1, in1len); + shake256_inc_absorb(state, in2, in2len); + shake256_inc_finalize(state); +} + +void haetae_shake256_absorb_once(xof256_state *state, const uint8_t *in1, + size_t in1len) { + shake256_inc_init(state); + shake256_inc_absorb(state, in1, in1len); + shake256_inc_finalize(state); +} + +void haetae_shake256_squeezeblocks(uint8_t *output, size_t nblocks, xof256_state *state){ + shake256_inc_squeeze(output, nblocks * XOF256_BLOCKBYTES, state); +} + + +void haetae_shake128_stream_squeezeblocks(uint8_t *output, size_t nblocks, stream128_state *state){ + shake128_inc_squeeze(output, nblocks * STREAM128_BLOCKBYTES, state); +} + +void haetae_shake256_stream_squeezeblocks(uint8_t *output, size_t nblocks, stream256_state *state){ + shake256_inc_squeeze(output, nblocks * STREAM256_BLOCKBYTES, state); +} + diff --git a/crypto_sign/haetae2/m4f/symmetric.h b/crypto_sign/haetae2/m4f/symmetric.h new file mode 100644 index 00000000..e64820e5 --- /dev/null +++ b/crypto_sign/haetae2/m4f/symmetric.h @@ -0,0 +1,85 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include "fips202.h" +#include "params.h" +#include + +// Cryptographic XOF function: shake256 + +typedef shake256incctx xof256_state; + +#define haetae_shake256_absorb_twice \ + HAETAE_NAMESPACE(haetae_shake256_absorb_twice) +void haetae_shake256_absorb_twice(xof256_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, + size_t in2len); + +#define haetae_shake256_absorb_once \ + HAETAE_NAMESPACE(haetae_shake256_absorb_once) +void haetae_shake256_absorb_once(xof256_state *state, const uint8_t *in1, + size_t in1len); + +#define haetae_shake256_squeezeblocks \ + HAETAE_NAMESPACE(haetae_shake256_squeezeblocks) +void haetae_shake256_squeezeblocks(uint8_t *output, size_t nblocks, + xof256_state *state); + + + +#define XOF256_BLOCKBYTES SHAKE256_RATE + +#define xof256_absorb_once(STATE, IN, IN_LEN) \ + haetae_shake256_absorb_once(STATE, IN, IN_LEN) +#define xof256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) \ + haetae_shake256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) +#define xof256_squeeze(OUT, OUT_LEN, STATE) \ + shake256_inc_squeeze(OUT, OUT_LEN, STATE) +#define xof256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + haetae_shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + + + + + +// Stream function: shake128|256 + +typedef shake128incctx stream128_state; +typedef shake256incctx stream256_state; + +#define haetae_shake128_stream_init \ + HAETAE_NAMESPACE(haetae_shake128_stream_init) +void haetae_shake128_stream_init(stream128_state *state, + const uint8_t seed[SEEDBYTES], uint16_t nonce); + +#define haetae_shake128_stream_squeezeblocks \ + HAETAE_NAMESPACE(haetae_shake128_stream_squeezeblocks) +void haetae_shake128_stream_squeezeblocks(uint8_t *output, size_t nblocks, + stream128_state *state); + +#define haetae_shake256_stream_init \ + HAETAE_NAMESPACE(haetae_shake256_stream_init) +void haetae_shake256_stream_init(stream256_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define haetae_shake256_stream_squeezeblocks \ + HAETAE_NAMESPACE(haetae_shake256_stream_squeezeblocks) +void haetae_shake256_stream_squeezeblocks(uint8_t *output, size_t nblocks, + stream256_state *state); + + + + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) \ + haetae_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + haetae_shake128_stream_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + haetae_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + haetae_shake256_stream_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#endif // SYMMETRIC_H diff --git a/crypto_sign/haetae3/m4f/api.h b/crypto_sign/haetae3/m4f/api.h new file mode 120000 index 00000000..ed30462c --- /dev/null +++ b/crypto_sign/haetae3/m4f/api.h @@ -0,0 +1 @@ +../../haetae2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/arm_simd.h b/crypto_sign/haetae3/m4f/arm_simd.h new file mode 120000 index 00000000..ab7a4b77 --- /dev/null +++ b/crypto_sign/haetae3/m4f/arm_simd.h @@ -0,0 +1 @@ +../../haetae2/m4f/arm_simd.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/config.h b/crypto_sign/haetae3/m4f/config.h new file mode 100644 index 00000000..437f7b8b --- /dev/null +++ b/crypto_sign/haetae3/m4f/config.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 3 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif +#endif diff --git a/crypto_sign/haetae3/m4f/decompose.c b/crypto_sign/haetae3/m4f/decompose.c new file mode 120000 index 00000000..746692b6 --- /dev/null +++ b/crypto_sign/haetae3/m4f/decompose.c @@ -0,0 +1 @@ +../../haetae2/m4f/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/decompose.h b/crypto_sign/haetae3/m4f/decompose.h new file mode 120000 index 00000000..73905f3b --- /dev/null +++ b/crypto_sign/haetae3/m4f/decompose.h @@ -0,0 +1 @@ +../../haetae2/m4f/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/encoding.c b/crypto_sign/haetae3/m4f/encoding.c new file mode 120000 index 00000000..f5be8a1c --- /dev/null +++ b/crypto_sign/haetae3/m4f/encoding.c @@ -0,0 +1 @@ +../../haetae2/m4f/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/encoding.h b/crypto_sign/haetae3/m4f/encoding.h new file mode 120000 index 00000000..ff18a912 --- /dev/null +++ b/crypto_sign/haetae3/m4f/encoding.h @@ -0,0 +1 @@ +../../haetae2/m4f/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fast_exp_asm.S b/crypto_sign/haetae3/m4f/fast_exp_asm.S new file mode 120000 index 00000000..6e72d6e3 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fast_exp_asm.S @@ -0,0 +1 @@ +../../haetae2/m4f/fast_exp_asm.S \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fast_exp_asm.h b/crypto_sign/haetae3/m4f/fast_exp_asm.h new file mode 120000 index 00000000..6c507fb6 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fast_exp_asm.h @@ -0,0 +1 @@ +../../haetae2/m4f/fast_exp_asm.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fast_sampler.S b/crypto_sign/haetae3/m4f/fast_sampler.S new file mode 120000 index 00000000..1698a0e5 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fast_sampler.S @@ -0,0 +1 @@ +../../haetae2/m4f/fast_sampler.S \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fast_sampler.h b/crypto_sign/haetae3/m4f/fast_sampler.h new file mode 120000 index 00000000..24fc54a0 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fast_sampler.h @@ -0,0 +1 @@ +../../haetae2/m4f/fast_sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fft.c b/crypto_sign/haetae3/m4f/fft.c new file mode 120000 index 00000000..32649ba0 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fft.c @@ -0,0 +1 @@ +../../haetae2/m4f/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fft.h b/crypto_sign/haetae3/m4f/fft.h new file mode 120000 index 00000000..975238f8 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fft.h @@ -0,0 +1 @@ +../../haetae2/m4f/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fips202.h b/crypto_sign/haetae3/m4f/fips202.h new file mode 120000 index 00000000..a4abf3d6 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fips202.h @@ -0,0 +1 @@ +../../haetae2/m4f/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fixpoint.c b/crypto_sign/haetae3/m4f/fixpoint.c new file mode 120000 index 00000000..138d2382 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fixpoint.c @@ -0,0 +1 @@ +../../haetae2/m4f/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fixpoint.h b/crypto_sign/haetae3/m4f/fixpoint.h new file mode 120000 index 00000000..262f3b85 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fixpoint.h @@ -0,0 +1 @@ +../../haetae2/m4f/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fp84_76.c b/crypto_sign/haetae3/m4f/fp84_76.c new file mode 120000 index 00000000..4afcaf8e --- /dev/null +++ b/crypto_sign/haetae3/m4f/fp84_76.c @@ -0,0 +1 @@ +../../haetae2/m4f/fp84_76.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fp84_76.h b/crypto_sign/haetae3/m4f/fp84_76.h new file mode 120000 index 00000000..db9289b4 --- /dev/null +++ b/crypto_sign/haetae3/m4f/fp84_76.h @@ -0,0 +1 @@ +../../haetae2/m4f/fp84_76.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/fpa.h b/crypto_sign/haetae3/m4f/fpa.h new file mode 120000 index 00000000..93034adc --- /dev/null +++ b/crypto_sign/haetae3/m4f/fpa.h @@ -0,0 +1 @@ +../../haetae2/m4f/fpa.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/header_macros.i b/crypto_sign/haetae3/m4f/header_macros.i new file mode 120000 index 00000000..cd82baaa --- /dev/null +++ b/crypto_sign/haetae3/m4f/header_macros.i @@ -0,0 +1 @@ +../../haetae2/m4f/header_macros.i \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/ntt332.S b/crypto_sign/haetae3/m4f/ntt332.S new file mode 120000 index 00000000..b71edf8c --- /dev/null +++ b/crypto_sign/haetae3/m4f/ntt332.S @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332.S \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/ntt332.h b/crypto_sign/haetae3/m4f/ntt332.h new file mode 120000 index 00000000..8f740ae8 --- /dev/null +++ b/crypto_sign/haetae3/m4f/ntt332.h @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/ntt332_macros.i b/crypto_sign/haetae3/m4f/ntt332_macros.i new file mode 120000 index 00000000..e848e98d --- /dev/null +++ b/crypto_sign/haetae3/m4f/ntt332_macros.i @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332_macros.i \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/packing.c b/crypto_sign/haetae3/m4f/packing.c new file mode 120000 index 00000000..c1316119 --- /dev/null +++ b/crypto_sign/haetae3/m4f/packing.c @@ -0,0 +1 @@ +../../haetae2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/packing.h b/crypto_sign/haetae3/m4f/packing.h new file mode 120000 index 00000000..a0128ac6 --- /dev/null +++ b/crypto_sign/haetae3/m4f/packing.h @@ -0,0 +1 @@ +../../haetae2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/params.h b/crypto_sign/haetae3/m4f/params.h new file mode 120000 index 00000000..e0572703 --- /dev/null +++ b/crypto_sign/haetae3/m4f/params.h @@ -0,0 +1 @@ +../../haetae2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/poly.c b/crypto_sign/haetae3/m4f/poly.c new file mode 120000 index 00000000..a67ca149 --- /dev/null +++ b/crypto_sign/haetae3/m4f/poly.c @@ -0,0 +1 @@ +../../haetae2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/poly.h b/crypto_sign/haetae3/m4f/poly.h new file mode 120000 index 00000000..e93c1c2c --- /dev/null +++ b/crypto_sign/haetae3/m4f/poly.h @@ -0,0 +1 @@ +../../haetae2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polyfix.c b/crypto_sign/haetae3/m4f/polyfix.c new file mode 120000 index 00000000..23119f58 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polyfix.c @@ -0,0 +1 @@ +../../haetae2/m4f/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polyfix.h b/crypto_sign/haetae3/m4f/polyfix.h new file mode 120000 index 00000000..e1a37bd5 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polyfix.h @@ -0,0 +1 @@ +../../haetae2/m4f/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polymat.c b/crypto_sign/haetae3/m4f/polymat.c new file mode 120000 index 00000000..e9f991c3 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polymat.c @@ -0,0 +1 @@ +../../haetae2/m4f/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polymat.h b/crypto_sign/haetae3/m4f/polymat.h new file mode 120000 index 00000000..f15ef444 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polymat.h @@ -0,0 +1 @@ +../../haetae2/m4f/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polyvec.c b/crypto_sign/haetae3/m4f/polyvec.c new file mode 120000 index 00000000..9a7e2bf6 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polyvec.c @@ -0,0 +1 @@ +../../haetae2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/polyvec.h b/crypto_sign/haetae3/m4f/polyvec.h new file mode 120000 index 00000000..68162b22 --- /dev/null +++ b/crypto_sign/haetae3/m4f/polyvec.h @@ -0,0 +1 @@ +../../haetae2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/rans_byte.h b/crypto_sign/haetae3/m4f/rans_byte.h new file mode 120000 index 00000000..ae04a80d --- /dev/null +++ b/crypto_sign/haetae3/m4f/rans_byte.h @@ -0,0 +1 @@ +../../haetae2/m4f/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/reduce.c b/crypto_sign/haetae3/m4f/reduce.c new file mode 120000 index 00000000..cc4d8476 --- /dev/null +++ b/crypto_sign/haetae3/m4f/reduce.c @@ -0,0 +1 @@ +../../haetae2/m4f/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/reduce.h b/crypto_sign/haetae3/m4f/reduce.h new file mode 120000 index 00000000..e0c8beab --- /dev/null +++ b/crypto_sign/haetae3/m4f/reduce.h @@ -0,0 +1 @@ +../../haetae2/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/sampler.c b/crypto_sign/haetae3/m4f/sampler.c new file mode 120000 index 00000000..dac3d7fb --- /dev/null +++ b/crypto_sign/haetae3/m4f/sampler.c @@ -0,0 +1 @@ +../../haetae2/m4f/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/sampler.h b/crypto_sign/haetae3/m4f/sampler.h new file mode 120000 index 00000000..9d8cbdcb --- /dev/null +++ b/crypto_sign/haetae3/m4f/sampler.h @@ -0,0 +1 @@ +../../haetae2/m4f/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/sign.c b/crypto_sign/haetae3/m4f/sign.c new file mode 120000 index 00000000..08eb186e --- /dev/null +++ b/crypto_sign/haetae3/m4f/sign.c @@ -0,0 +1 @@ +../../haetae2/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/sign.h b/crypto_sign/haetae3/m4f/sign.h new file mode 120000 index 00000000..267fcaf3 --- /dev/null +++ b/crypto_sign/haetae3/m4f/sign.h @@ -0,0 +1 @@ +../../haetae2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/symmetric-shake.c b/crypto_sign/haetae3/m4f/symmetric-shake.c new file mode 120000 index 00000000..e38dc1a5 --- /dev/null +++ b/crypto_sign/haetae3/m4f/symmetric-shake.c @@ -0,0 +1 @@ +../../haetae2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae3/m4f/symmetric.h b/crypto_sign/haetae3/m4f/symmetric.h new file mode 120000 index 00000000..249e9d30 --- /dev/null +++ b/crypto_sign/haetae3/m4f/symmetric.h @@ -0,0 +1 @@ +../../haetae2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/api.h b/crypto_sign/haetae5/m4f/api.h new file mode 120000 index 00000000..ed30462c --- /dev/null +++ b/crypto_sign/haetae5/m4f/api.h @@ -0,0 +1 @@ +../../haetae2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/arm_simd.h b/crypto_sign/haetae5/m4f/arm_simd.h new file mode 120000 index 00000000..ab7a4b77 --- /dev/null +++ b/crypto_sign/haetae5/m4f/arm_simd.h @@ -0,0 +1 @@ +../../haetae2/m4f/arm_simd.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/config.h b/crypto_sign/haetae5/m4f/config.h new file mode 100644 index 00000000..5180b8f0 --- /dev/null +++ b/crypto_sign/haetae5/m4f/config.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 5 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif +#endif diff --git a/crypto_sign/haetae5/m4f/decompose.c b/crypto_sign/haetae5/m4f/decompose.c new file mode 120000 index 00000000..746692b6 --- /dev/null +++ b/crypto_sign/haetae5/m4f/decompose.c @@ -0,0 +1 @@ +../../haetae2/m4f/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/decompose.h b/crypto_sign/haetae5/m4f/decompose.h new file mode 120000 index 00000000..73905f3b --- /dev/null +++ b/crypto_sign/haetae5/m4f/decompose.h @@ -0,0 +1 @@ +../../haetae2/m4f/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/encoding.c b/crypto_sign/haetae5/m4f/encoding.c new file mode 120000 index 00000000..f5be8a1c --- /dev/null +++ b/crypto_sign/haetae5/m4f/encoding.c @@ -0,0 +1 @@ +../../haetae2/m4f/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/encoding.h b/crypto_sign/haetae5/m4f/encoding.h new file mode 120000 index 00000000..ff18a912 --- /dev/null +++ b/crypto_sign/haetae5/m4f/encoding.h @@ -0,0 +1 @@ +../../haetae2/m4f/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fast_exp_asm.S b/crypto_sign/haetae5/m4f/fast_exp_asm.S new file mode 120000 index 00000000..6e72d6e3 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fast_exp_asm.S @@ -0,0 +1 @@ +../../haetae2/m4f/fast_exp_asm.S \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fast_exp_asm.h b/crypto_sign/haetae5/m4f/fast_exp_asm.h new file mode 120000 index 00000000..6c507fb6 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fast_exp_asm.h @@ -0,0 +1 @@ +../../haetae2/m4f/fast_exp_asm.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fast_sampler.S b/crypto_sign/haetae5/m4f/fast_sampler.S new file mode 120000 index 00000000..1698a0e5 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fast_sampler.S @@ -0,0 +1 @@ +../../haetae2/m4f/fast_sampler.S \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fast_sampler.h b/crypto_sign/haetae5/m4f/fast_sampler.h new file mode 120000 index 00000000..24fc54a0 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fast_sampler.h @@ -0,0 +1 @@ +../../haetae2/m4f/fast_sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fft.c b/crypto_sign/haetae5/m4f/fft.c new file mode 120000 index 00000000..32649ba0 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fft.c @@ -0,0 +1 @@ +../../haetae2/m4f/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fft.h b/crypto_sign/haetae5/m4f/fft.h new file mode 120000 index 00000000..975238f8 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fft.h @@ -0,0 +1 @@ +../../haetae2/m4f/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fips202.h b/crypto_sign/haetae5/m4f/fips202.h new file mode 120000 index 00000000..a4abf3d6 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fips202.h @@ -0,0 +1 @@ +../../haetae2/m4f/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fixpoint.c b/crypto_sign/haetae5/m4f/fixpoint.c new file mode 120000 index 00000000..138d2382 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fixpoint.c @@ -0,0 +1 @@ +../../haetae2/m4f/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fixpoint.h b/crypto_sign/haetae5/m4f/fixpoint.h new file mode 120000 index 00000000..262f3b85 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fixpoint.h @@ -0,0 +1 @@ +../../haetae2/m4f/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fp84_76.c b/crypto_sign/haetae5/m4f/fp84_76.c new file mode 120000 index 00000000..4afcaf8e --- /dev/null +++ b/crypto_sign/haetae5/m4f/fp84_76.c @@ -0,0 +1 @@ +../../haetae2/m4f/fp84_76.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fp84_76.h b/crypto_sign/haetae5/m4f/fp84_76.h new file mode 120000 index 00000000..db9289b4 --- /dev/null +++ b/crypto_sign/haetae5/m4f/fp84_76.h @@ -0,0 +1 @@ +../../haetae2/m4f/fp84_76.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/fpa.h b/crypto_sign/haetae5/m4f/fpa.h new file mode 120000 index 00000000..93034adc --- /dev/null +++ b/crypto_sign/haetae5/m4f/fpa.h @@ -0,0 +1 @@ +../../haetae2/m4f/fpa.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/header_macros.i b/crypto_sign/haetae5/m4f/header_macros.i new file mode 120000 index 00000000..cd82baaa --- /dev/null +++ b/crypto_sign/haetae5/m4f/header_macros.i @@ -0,0 +1 @@ +../../haetae2/m4f/header_macros.i \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/ntt332.S b/crypto_sign/haetae5/m4f/ntt332.S new file mode 120000 index 00000000..b71edf8c --- /dev/null +++ b/crypto_sign/haetae5/m4f/ntt332.S @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332.S \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/ntt332.h b/crypto_sign/haetae5/m4f/ntt332.h new file mode 120000 index 00000000..8f740ae8 --- /dev/null +++ b/crypto_sign/haetae5/m4f/ntt332.h @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/ntt332_macros.i b/crypto_sign/haetae5/m4f/ntt332_macros.i new file mode 120000 index 00000000..e848e98d --- /dev/null +++ b/crypto_sign/haetae5/m4f/ntt332_macros.i @@ -0,0 +1 @@ +../../haetae2/m4f/ntt332_macros.i \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/packing.c b/crypto_sign/haetae5/m4f/packing.c new file mode 120000 index 00000000..c1316119 --- /dev/null +++ b/crypto_sign/haetae5/m4f/packing.c @@ -0,0 +1 @@ +../../haetae2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/packing.h b/crypto_sign/haetae5/m4f/packing.h new file mode 120000 index 00000000..a0128ac6 --- /dev/null +++ b/crypto_sign/haetae5/m4f/packing.h @@ -0,0 +1 @@ +../../haetae2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/params.h b/crypto_sign/haetae5/m4f/params.h new file mode 120000 index 00000000..e0572703 --- /dev/null +++ b/crypto_sign/haetae5/m4f/params.h @@ -0,0 +1 @@ +../../haetae2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/poly.c b/crypto_sign/haetae5/m4f/poly.c new file mode 120000 index 00000000..a67ca149 --- /dev/null +++ b/crypto_sign/haetae5/m4f/poly.c @@ -0,0 +1 @@ +../../haetae2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/poly.h b/crypto_sign/haetae5/m4f/poly.h new file mode 120000 index 00000000..e93c1c2c --- /dev/null +++ b/crypto_sign/haetae5/m4f/poly.h @@ -0,0 +1 @@ +../../haetae2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polyfix.c b/crypto_sign/haetae5/m4f/polyfix.c new file mode 120000 index 00000000..23119f58 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polyfix.c @@ -0,0 +1 @@ +../../haetae2/m4f/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polyfix.h b/crypto_sign/haetae5/m4f/polyfix.h new file mode 120000 index 00000000..e1a37bd5 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polyfix.h @@ -0,0 +1 @@ +../../haetae2/m4f/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polymat.c b/crypto_sign/haetae5/m4f/polymat.c new file mode 120000 index 00000000..e9f991c3 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polymat.c @@ -0,0 +1 @@ +../../haetae2/m4f/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polymat.h b/crypto_sign/haetae5/m4f/polymat.h new file mode 120000 index 00000000..f15ef444 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polymat.h @@ -0,0 +1 @@ +../../haetae2/m4f/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polyvec.c b/crypto_sign/haetae5/m4f/polyvec.c new file mode 120000 index 00000000..9a7e2bf6 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polyvec.c @@ -0,0 +1 @@ +../../haetae2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/polyvec.h b/crypto_sign/haetae5/m4f/polyvec.h new file mode 120000 index 00000000..68162b22 --- /dev/null +++ b/crypto_sign/haetae5/m4f/polyvec.h @@ -0,0 +1 @@ +../../haetae2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/rans_byte.h b/crypto_sign/haetae5/m4f/rans_byte.h new file mode 120000 index 00000000..ae04a80d --- /dev/null +++ b/crypto_sign/haetae5/m4f/rans_byte.h @@ -0,0 +1 @@ +../../haetae2/m4f/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/reduce.c b/crypto_sign/haetae5/m4f/reduce.c new file mode 120000 index 00000000..cc4d8476 --- /dev/null +++ b/crypto_sign/haetae5/m4f/reduce.c @@ -0,0 +1 @@ +../../haetae2/m4f/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/reduce.h b/crypto_sign/haetae5/m4f/reduce.h new file mode 120000 index 00000000..e0c8beab --- /dev/null +++ b/crypto_sign/haetae5/m4f/reduce.h @@ -0,0 +1 @@ +../../haetae2/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/sampler.c b/crypto_sign/haetae5/m4f/sampler.c new file mode 120000 index 00000000..dac3d7fb --- /dev/null +++ b/crypto_sign/haetae5/m4f/sampler.c @@ -0,0 +1 @@ +../../haetae2/m4f/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/sampler.h b/crypto_sign/haetae5/m4f/sampler.h new file mode 120000 index 00000000..9d8cbdcb --- /dev/null +++ b/crypto_sign/haetae5/m4f/sampler.h @@ -0,0 +1 @@ +../../haetae2/m4f/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/sign.c b/crypto_sign/haetae5/m4f/sign.c new file mode 120000 index 00000000..08eb186e --- /dev/null +++ b/crypto_sign/haetae5/m4f/sign.c @@ -0,0 +1 @@ +../../haetae2/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/sign.h b/crypto_sign/haetae5/m4f/sign.h new file mode 120000 index 00000000..267fcaf3 --- /dev/null +++ b/crypto_sign/haetae5/m4f/sign.h @@ -0,0 +1 @@ +../../haetae2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/symmetric-shake.c b/crypto_sign/haetae5/m4f/symmetric-shake.c new file mode 120000 index 00000000..e38dc1a5 --- /dev/null +++ b/crypto_sign/haetae5/m4f/symmetric-shake.c @@ -0,0 +1 @@ +../../haetae2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae5/m4f/symmetric.h b/crypto_sign/haetae5/m4f/symmetric.h new file mode 120000 index 00000000..249e9d30 --- /dev/null +++ b/crypto_sign/haetae5/m4f/symmetric.h @@ -0,0 +1 @@ +../../haetae2/m4f/symmetric.h \ No newline at end of file From 7eee34e17aae905fb0eae8721e175cc85c50ddf4 Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 21 Nov 2023 23:58:03 +0100 Subject: [PATCH 029/107] compute challenge polynomial directly and sample hyperball coin deterministically * Move challenge seed generation from crypto_sign() to poly_challenge(). * Sample the random byte b deterministically inside of polyfixveclk_sample_hyperball(). It is used to: * determine the sign in hyperball sampling (bit mask 0x01) * reject with 50% odds in the overlap region (bit mask 0x02) * M4F version corresponds to reference version of 2023-11-20. --- crypto_sign/haetae2/m4f/packing.c | 28 +++++++---- crypto_sign/haetae2/m4f/packing.h | 4 +- crypto_sign/haetae2/m4f/poly.c | 13 +++-- crypto_sign/haetae2/m4f/poly.h | 3 +- crypto_sign/haetae2/m4f/polyfix.c | 26 +++++++++- crypto_sign/haetae2/m4f/polyfix.h | 4 +- crypto_sign/haetae2/m4f/sign.c | 82 ++++++++++++++----------------- 7 files changed, 96 insertions(+), 64 deletions(-) diff --git a/crypto_sign/haetae2/m4f/packing.c b/crypto_sign/haetae2/m4f/packing.c index e88ce939..3b7b5019 100644 --- a/crypto_sign/haetae2/m4f/packing.c +++ b/crypto_sign/haetae2/m4f/packing.c @@ -149,15 +149,15 @@ void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, *Enc(h)). * * Arguments: - uint8_t sig[]: output byte array - * - const uint8_t c_seed[]: pointer to seed of challenge + * - const poly *c: pointer to challenge polynomial * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of - *length L + * length L * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of - *length L + * length L * - const polyveck *h: pointer t vector h of length K * Returns 1 in case the signature size is above the threshold; otherwise 0. **************************************************/ -int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h) { @@ -169,8 +169,12 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], // init/padding with zeros: memset(sig, 0, CRYPTO_BYTES); - memcpy(sig, c_seed, SEEDBYTES); - sig += SEEDBYTES; + // encode challenge + for (size_t i = 0; i < N; i++) + { + sig[i/8] |= c->coeffs[i] << (i%8); + } + sig += N / 8; for (int i = 0; i < L; ++i) poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); @@ -218,7 +222,7 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), *Enc(h)). * - * Arguments: - uint8_t c_seed[]: pointer to output seed of challenge + * Arguments: - poly *c: pointer to output challenge polynomial * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) * - polyveck *h: pointer to output vector h @@ -227,14 +231,18 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], * * Returns 1 in case of malformed signature; otherwise 0. **************************************************/ -int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, +int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]) { uint16_t size_enc_hb_z1, size_enc_h; - memcpy(c_seed, sig, SEEDBYTES); - sig += SEEDBYTES; + // decode challenge + for (size_t i = 0; i < N; i++) + { + c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; + } + sig += N / 8; for (unsigned int i = 0; i < L; ++i) poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); diff --git a/crypto_sign/haetae2/m4f/packing.h b/crypto_sign/haetae2/m4f/packing.h index b000218e..9fa1a3f1 100644 --- a/crypto_sign/haetae2/m4f/packing.h +++ b/crypto_sign/haetae2/m4f/packing.h @@ -17,9 +17,9 @@ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKE void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); #define pack_sig HAETAE_NAMESPACE(pack_sig) -int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); #define unpack_sig HAETAE_NAMESPACE(unpack_sig) -int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); +int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); #endif //HAETAE_PACKING_H diff --git a/crypto_sign/haetae2/m4f/poly.c b/crypto_sign/haetae2/m4f/poly.c index 8c9181ee..43207608 100644 --- a/crypto_sign/haetae2/m4f/poly.c +++ b/crypto_sign/haetae2/m4f/poly.c @@ -413,13 +413,17 @@ uint8_t hammingWeight_8(uint8_t x) { * - const uint8_t seed[]: byte array containing seed of length * SEEDBYTES **************************************************/ -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]) { #if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) unsigned int i, b, pos = 0; uint8_t buf[XOF256_BLOCKBYTES]; xof256_state state; - xof256_absorb_once(&state, seed, SEEDBYTES); + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorb_twice(&state, + highbits_lsb, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, + mu, SEEDBYTES); xof256_squeezeblocks(buf, 1, &state); for (i = 0; i < N; ++i) @@ -443,7 +447,10 @@ void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { uint8_t buf[32] = {0}; xof256_state state; - xof256_absorb_once(&state, seed, SEEDBYTES); + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorb_twice(&state, + highbits_lsb, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, + mu, SEEDBYTES); xof256_squeeze(buf, 32, &state); for (i = 0; i < 32; ++i) diff --git a/crypto_sign/haetae2/m4f/poly.h b/crypto_sign/haetae2/m4f/poly.h index 192c9033..57c9b95f 100644 --- a/crypto_sign/haetae2/m4f/poly.h +++ b/crypto_sign/haetae2/m4f/poly.h @@ -71,7 +71,8 @@ void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t #define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); #define poly_challenge HAETAE_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]); #define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) void poly_decomposed_pack(uint8_t *buf, const poly *a); diff --git a/crypto_sign/haetae2/m4f/polyfix.c b/crypto_sign/haetae2/m4f/polyfix.c index d7d36e8b..2a168afa 100644 --- a/crypto_sign/haetae2/m4f/polyfix.c +++ b/crypto_sign/haetae2/m4f/polyfix.c @@ -266,7 +266,7 @@ uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { return ret; } -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce) { uint16_t ni = nonce; @@ -313,10 +313,23 @@ uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, } sqnorm2 = polyfixveclk_sqnorm2(y1, y2); } while (sqnorm2 > B0SQ * LN * LN); + + { + uint8_t tmp[CRHBYTES + 2]; + for (i = 0; i < CRHBYTES; i++) + { + tmp[i] = seed[i]; + } + tmp[CRHBYTES + 0] = ni >> 0; + tmp[CRHBYTES + 1] = ni >> 8; + shake256(b, 1, tmp, CRHBYTES+2); + } + return ni; } uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, + uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce) { uint16_t ni = nonce; @@ -378,5 +391,16 @@ uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2 } } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); + { + uint8_t tmp[CRHBYTES + 2]; + for (i = 0; i < CRHBYTES; i++) + { + tmp[i] = seed[i]; + } + tmp[CRHBYTES + 0] = ni >> 0; + tmp[CRHBYTES + 1] = ni >> 8; + shake256(b, 1, tmp, CRHBYTES+2); + } + return ni; } diff --git a/crypto_sign/haetae2/m4f/polyfix.h b/crypto_sign/haetae2/m4f/polyfix.h index a77a2740..85469e8a 100644 --- a/crypto_sign/haetae2/m4f/polyfix.h +++ b/crypto_sign/haetae2/m4f/polyfix.h @@ -62,10 +62,10 @@ uint64_t polyfix_sqnorm2(const polyfix *a); uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); #define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); #define polyfixveclk_two_pass_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_two_pass_sample_hyperball) -uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); +uint16_t polyfixveclk_two_pass_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); #endif // clang-format on diff --git a/crypto_sign/haetae2/m4f/sign.c b/crypto_sign/haetae2/m4f/sign.c index dd7b6449..5648ec3e 100644 --- a/crypto_sign/haetae2/m4f/sign.c +++ b/crypto_sign/haetae2/m4f/sign.c @@ -326,7 +326,7 @@ static void decompose_z1_vecl(polyvecl *lb_z1, polyvecl *hb_z1, const polyfixvec * * Arguments: - polyfixvecl *z1: part of the signature candidate * - polyfixveck *z2: part of the signature candidate - * - uint8_t cseed: seed of the challenge polynomial + * - poly *c: challenge polynomial * - polyvecm *s1: part of the secret key, NTT domain * - polyveck *s2: part of the secret key, NTT domain * - polyfixvecl *y1: part of the uniform samples from the hyperball @@ -335,27 +335,26 @@ static void decompose_z1_vecl(polyvecl *lb_z1, polyvecl *hb_z1, const polyfixvec * * Returns void **************************************************/ -static void compute_z_veckl(polyfixvecl *z1, polyfixveck *z2, const uint8_t cseed[SEEDBYTES], +static void compute_z_veckl(polyfixvecl *z1, polyfixveck *z2, const poly *c, const polyvecm *s1, const polyveck *s2, const polyfixvecl *y1, const polyfixveck *y2, const uint8_t b){ - poly c; poly t; - - // c = challenge(c_seed) - poly_challenge(&c, cseed); + poly chat; // t = (c * s).vec[i] = (c * (1 || s1 || s2)).vec[i] // z = y + (-1)^b (c * s) = z1 || z2 + chat = *c; + poly_ntt(&chat); + // z1[0] - t = c; + t = *c; poly_cneg(&t, b & 1); polyfix_add(&z1->vec[0], &y1->vec[0], &t); // z1.vec[1..L-1] - poly_ntt(&c); for (size_t column = 1; column < L; ++column) { - poly_pointwise_montgomery(&t, &c, &s1->vec[column - 1]); + poly_pointwise_montgomery(&t, &chat, &s1->vec[column - 1]); poly_invntt_tomont(&t); poly_cneg(&t, b & 1); polyfix_add(&z1->vec[column], &y1->vec[column], &t); @@ -363,7 +362,7 @@ static void compute_z_veckl(polyfixvecl *z1, polyfixveck *z2, const uint8_t csee // z2.vec[0..K-1] for (size_t row = 0; row < K; row++) { - poly_pointwise_montgomery(&t, &s2->vec[row], &c); + poly_pointwise_montgomery(&t, &s2->vec[row], &chat); poly_invntt_tomont(&t); poly_cneg(&t, b & 1); polyfix_add(&z2->vec[row], &y2->vec[row], &t); @@ -434,7 +433,7 @@ static uint64_t is_rejected_in_intersection(const polyfixvecl *z1, const polyfix * Name: multiply_a1_by_rounded_y1_mod_q * * Description: Computes Ay = A1 * round(y1) mod q and a copy of round(y1)[0]. - * Subfunction of compute_challenge_seed() + * Subfunction of compute_challenge_polynomial() * * Arguments: - poly *z1rnd0: round(y1)[0], not in Montgomery domain * - polyveck *Ay: vector mod q @@ -490,7 +489,7 @@ static void multiply_a1_by_rounded_y1_mod_q(poly *z1rnd0, * Name: accumulate_two_times_rounded_y2_mod_q * * Description: Accumulates 2 * round(y2) mod q to Ay - * Subfunction of compute_challenge_seed() + * Subfunction of compute_challenge_polynomial() * * Arguments: - polyveck *Ay: vector mod q * - polyfixveck *y2: part of the hyperball samples @@ -509,11 +508,11 @@ static void accumulate_two_times_rounded_y2_mod_q(polyveck *Ay, const polyfixvec } /************************************************* - * Name: compute_challenge_seed + * Name: compute_challenge_polynomial * - * Description: Computes a challenge seed, Ay and HighBits(hint) + * Description: Computes a challenge polynomial, Ay and HighBits(hint) * - * Arguments: - uint8_t *cseed[SEEDBYTES]: seed to expand challenge polynomial from + * Arguments: - poly *c: challenge polynomial * - polyveck *Ay: A1 * round(y1) + 2 * round(y2) mod q * - polyveck *highbits: HighBits of hint (A * round(y) mod 2q) * - const polyvecl *A1[K]: public key matrix @@ -523,7 +522,7 @@ static void accumulate_two_times_rounded_y2_mod_q(polyveck *Ay, const polyfixvec * * Returns 0 (success) **************************************************/ -static void compute_challenge_seed(uint8_t cseed[SEEDBYTES], polyveck *Ay, polyveck *highbits, +static void compute_challenge_polynomial(poly *c, polyveck *Ay, polyveck *highbits, const uMatrixPointerL_frozen a1ptr, const polyfixvecl *y1, const polyfixveck *y2, const uint8_t mu[SEEDBYTES]){ uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; @@ -548,10 +547,9 @@ static void compute_challenge_seed(uint8_t cseed[SEEDBYTES], polyveck *Ay, polyv polyveck_pack_highbits(buf, highbits); poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); - // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - generate_seed_from_two_sources(cseed, SEEDBYTES, - buf, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, - mu, SEEDBYTES); + // c = challenge(HighBits(A * y mod 2q), LSB(round(y0) * j), mu) + poly_challenge(c, buf, mu); + return; }; @@ -568,7 +566,7 @@ static void compute_challenge_seed(uint8_t cseed[SEEDBYTES], polyveck *Ay, polyv **************************************************/ static int compress_and_pack_signature( uint8_t *sig, - uint8_t cseed[SEEDBYTES], + poly *c, const polyfixvecl *z1, const polyfixveck *z2, const polyveck *Ay, @@ -581,7 +579,7 @@ static int compress_and_pack_signature( decompose_z1_vecl(&lb_z1, &hb_z1, z1); /*------------------ Pack signature -----------------------------*/ - if (pack_sig(sig, cseed, &lb_z1, &hb_z1, &h)) { // reject if signature is too big + if (pack_sig(sig, c, &lb_z1, &hb_z1, &h)) { // reject if signature is too big return 1; } return 0; @@ -607,8 +605,8 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; uint8_t mu[SEEDBYTES] = {0}; - uint8_t cseed[SEEDBYTES] = {0}; // seed of a challenge polynomial c - uint8_t b = 0; // one bit + poly c = { .coeffs = {0} }; // challenge polynomial + uint8_t b = 0; // some random bits uint16_t counter = 0; uint64_t reject1, reject2; @@ -639,19 +637,18 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, reject: /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ - randombytes(&b, sizeof(uint8_t)); #ifdef ENABLE_TWO_PASS_SAMPLING - counter = polyfixveclk_two_pass_sample_hyperball(&y1, &y2, seedbuf, counter); + counter = polyfixveclk_two_pass_sample_hyperball(&y1, &y2, &b, seedbuf, counter); #else - counter = polyfixveclk_sample_hyperball(&y1, &y2, seedbuf, counter); + counter = polyfixveclk_sample_hyperball(&y1, &y2, &b, seedbuf, counter); #endif /*------------------- 2. Compute a challenge c --------------------------*/ - compute_challenge_seed(cseed, &Ay, &highbits, a1ptr, &y1, &y2, mu); + compute_challenge_polynomial(&c, &Ay, &highbits, a1ptr, &y1, &y2, mu); /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ - compute_z_veckl(&z1, &z2, cseed, &s1, &s2, &y1, &y2, b); + compute_z_veckl(&z1, &z2, &c, &s1, &s2, &y1, &y2, b); reject1 = is_norm_of_z_geq_big_b_prime(&z1, &z2); reject2 = is_rejected_in_intersection(&z1, &z2, &y1, &y2, b); @@ -661,7 +658,7 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, /*------------------- 4. Make a hint and decompose z1 -----------*/ /*------------------ Pack signature -----------------------------*/ - if (0 != compress_and_pack_signature(sig, cseed, &z1, &z2, &Ay, &highbits)) + if (0 != compress_and_pack_signature(sig, &c, &z1, &z2, &Ay, &highbits)) goto reject; *siglen = CRYPTO_BYTES; @@ -705,12 +702,12 @@ int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, // ################################################################### // ################################################################### -static int unpack_cseed_z1_and_hint_from_sig(uint8_t c_seed[SEEDBYTES], polyvecl *z1, +static int unpack_cseed_z1_and_hint_from_sig(poly *c, polyvecl *z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]){ polyvecl highbits_z1; // Unpack signature and Check conditions -- low bits are stored in z1 - if (unpack_sig(c_seed, &highbits_z1, z1, h, sig)) { + if (unpack_sig(c, &highbits_z1, z1, h, sig)) { return -1; } @@ -760,8 +757,8 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) { unsigned int i; uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t c_seed[SEEDBYTES] = {0}, c_seed2[SEEDBYTES] = {0}; uint8_t rhoprime[SEEDBYTES] = {0}; + uint8_t mu[SEEDBYTES] = {0}; uint64_t sqnorm2; polyvecl z1; polyveck b; @@ -770,6 +767,7 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, polyveck z2; polyveck w; poly c; + poly cprime; poly wprime; // Check signature length @@ -779,12 +777,9 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, // Unpack public key unpack_pk(&b, rhoprime, pk); - unpack_cseed_z1_and_hint_from_sig(c_seed, &z1, &h, sig); + unpack_cseed_z1_and_hint_from_sig(&c, &z1, &h, sig); /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ - // c = challenge(c_seed) - poly_challenge(&c, c_seed); - // compute w' = lsb(z1[0] - c) and the squared norm of z1 before NTT sqnorm2 = polyvecl_sqnorm2(&z1); poly_sub(&wprime, &z1.vec[0], &c); @@ -847,21 +842,18 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, return -1; } - /*------------------- 3. Compute c_seed' and Compare ---------------------*/ + /*------------------- 3. Compute cprime and Compare ---------------------*/ // Pack highBits(A * round(z) - qcj mod 2q) and h' polyveck_pack_highbits(buf, &w); poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); - generate_seed_from_two_sources(c_seed2, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); + generate_seed_from_two_sources(mu, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); - // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - generate_seed_from_two_sources(c_seed2, SEEDBYTES, - buf, POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, - c_seed2, SEEDBYTES); + poly_challenge(&cprime, buf, mu); - for (i = 0; i < SEEDBYTES; ++i) { - if (c_seed[i] != c_seed2[i]) { + for (i = 0; i < N; ++i) { + if (c.coeffs[i] != cprime.coeffs[i]) { return -1; } } From a031ee42f10df7da64b3c25c3895cf4fbe8c1d31 Mon Sep 17 00:00:00 2001 From: Marc Date: Wed, 22 Nov 2023 15:56:35 +0100 Subject: [PATCH 030/107] add STACK_STRATEGY switch to config.h This implementation offers different stack strategies: * 0: Optimized for speed. * 1: Does not buffer the polynomials of the verification key in crypto_sign_keypair() and crypto_sign_signature(), thus reducing stack usage at the cost of some speed. * 2: In addition to 1, the hyperballs are sampled in multiple passes in crypto_sign_signature(), which reduces the stack usage for temporary variables. This roughly doubles the execution time of crypto_sign_signature(). --- crypto_sign/haetae2/m4f/config.h | 10 +++++++++ crypto_sign/haetae2/m4f/params.h | 35 +++++++++++++++++++++++++------- crypto_sign/haetae2/m4f/sign.c | 6 +++--- crypto_sign/haetae3/m4f/config.h | 10 +++++++++ crypto_sign/haetae5/m4f/config.h | 10 +++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/crypto_sign/haetae2/m4f/config.h b/crypto_sign/haetae2/m4f/config.h index 52c9e87b..436854fb 100644 --- a/crypto_sign/haetae2/m4f/config.h +++ b/crypto_sign/haetae2/m4f/config.h @@ -3,6 +3,16 @@ #define HAETAE_MODE 2 +/********************************************************************* + * STACK_STRATEGY + * 0 or undefined: optimized for speed (default) + * 1: do not buffer the polynomials of + * the verification key + * 2: as 1, and use multiple passes + * to sample the hyperball + *********************************************************************/ +#define STACK_STRATEGY 0 + #if HAETAE_MODE == 2 #define CRYPTO_ALGNAME "HAETAE2" #define HAETAE_NAMESPACETOP haetae2 diff --git a/crypto_sign/haetae2/m4f/params.h b/crypto_sign/haetae2/m4f/params.h index 7fac531b..09009bfc 100644 --- a/crypto_sign/haetae2/m4f/params.h +++ b/crypto_sign/haetae2/m4f/params.h @@ -5,24 +5,45 @@ #include "config.h" /*************************************************************** - * Settings for Stack Management + * Settings for Stack Management, use STACK_STRATEGY + * in config.h to select these. * ENABLE_TWO_PASS_SAMPLING: * - Default: not defined * - relates to polyfixveclk_sample_hyperball() + * - Discards and recomputes some intermediate results * - use about (L + K - 1) * 2kB less stack memory * - roughly double the execution time * ENABLE_SIGNATURE_MATRIX_BUFFER: * - Default: defined - * - Enables the use of large matrices to - * store the public key matrix + * - Enables the use of large matrices in + * crypto_sign() to store the public key matrix * - Uses about L * K * 2kB stack memory - * - increases runtime, as the matrix needs - * - to be recomputed for each rejection cycle + * - disabling increases runtime, as the matrix needs + * to be recomputed for each rejection cycle + * ENABLE_KEYPAIR_MATRIX_BUFFER: + * - Default: defined + * - Enables the use of large matrices in + * crypto_keypair() to store the public key matrix + * - Uses about L * K * 2kB stack memory + * - disabling increases runtime, as the matrix needs + * to be recomputed for each rejection cycle * Execute "make clean" to ensure the switches take effect. ***************************************************************/ +#ifndef STACK_STRATEGY +#define ENABLE_SIGNATURE_MATRIX_BUFFER +#define ENABLE_KEYPAIR_MATRIX_BUFFER +#else +#if STACK_STRATEGY == 0 +#define ENABLE_SIGNATURE_MATRIX_BUFFER +#define ENABLE_KEYPAIR_MATRIX_BUFFER +#elif STACK_STRATEGY == 1 +#elif STACK_STRATEGY == 2 #define ENABLE_TWO_PASS_SAMPLING -//#define ENABLE_SIGNATURE_MATRIX_BUFFER -//#define ENABLE_KEYPAIR_MATRIX_BUFFER +#else +#error Unknown STACK_STRATEGY specified +#endif /* if STACK_STRATEGY == 0 */ +#endif /* ifndef STACK_STRATEGY */ + #define SEEDBYTES 32 diff --git a/crypto_sign/haetae2/m4f/sign.c b/crypto_sign/haetae2/m4f/sign.c index 5648ec3e..59f52176 100644 --- a/crypto_sign/haetae2/m4f/sign.c +++ b/crypto_sign/haetae2/m4f/sign.c @@ -331,7 +331,7 @@ static void decompose_z1_vecl(polyvecl *lb_z1, polyvecl *hb_z1, const polyfixvec * - polyveck *s2: part of the secret key, NTT domain * - polyfixvecl *y1: part of the uniform samples from the hyperball * - polyfixveck *y2: part of the uniform samples from the hyperball - * - uint8_t b: a random byte for bimodal selection + * - uint8_t b: a random byte for bimodal selection using byte mask 0x01 * * Returns void **************************************************/ @@ -399,8 +399,8 @@ static uint64_t is_norm_of_z_geq_big_b_prime(const polyfixvecl *z1, const polyfi * - polyfixveck *z2: part of the signature candidate * - polyfixvecl *y1: part of the uniform samples from the hyperball * - polyfixveck *y2: part of the uniform samples from the hyperball - * - uint8_t b: a random byte for bimodal selection, this function - * uses bits corresponding to the mask 0x02 + * - uint8_t b: a random byte for rejection in the overlap + * region using byte mask 0x02 * * Returns 0 if the test passed, 1 if the signature needs to be rejected. **************************************************/ diff --git a/crypto_sign/haetae3/m4f/config.h b/crypto_sign/haetae3/m4f/config.h index 437f7b8b..ecfe6441 100644 --- a/crypto_sign/haetae3/m4f/config.h +++ b/crypto_sign/haetae3/m4f/config.h @@ -3,6 +3,16 @@ #define HAETAE_MODE 3 +/********************************************************************* + * STACK_STRATEGY + * 0 or undefined: optimized for speed (default) + * 1: do not buffer the polynomials of + * the verification key + * 2: as 1, and use multiple passes + * to sample the hyperball + *********************************************************************/ +#define STACK_STRATEGY 0 + #if HAETAE_MODE == 2 #define CRYPTO_ALGNAME "HAETAE2" #define HAETAE_NAMESPACETOP haetae2 diff --git a/crypto_sign/haetae5/m4f/config.h b/crypto_sign/haetae5/m4f/config.h index 5180b8f0..e1e73da3 100644 --- a/crypto_sign/haetae5/m4f/config.h +++ b/crypto_sign/haetae5/m4f/config.h @@ -3,6 +3,16 @@ #define HAETAE_MODE 5 +/********************************************************************* + * STACK_STRATEGY + * 0 or undefined: optimized for speed (default) + * 1: do not buffer the polynomials of + * the verification key + * 2: as 1, and use multiple passes + * to sample the hyperball + *********************************************************************/ +#define STACK_STRATEGY 0 + #if HAETAE_MODE == 2 #define CRYPTO_ALGNAME "HAETAE2" #define HAETAE_NAMESPACETOP haetae2 From 0bdc33efbefea6e2ab381b2df641b2da812e9c15 Mon Sep 17 00:00:00 2001 From: Marc Date: Wed, 22 Nov 2023 17:10:51 +0100 Subject: [PATCH 031/107] add clean implementation for HAETAE2 The clean implementation is only minimally changed from the reference implementation to conform with the PQM4 API. The clean implementation would run out of memory for HAETAE3 and HAETAE5 and is therefore not added for those modes. --- crypto_sign/haetae2/clean/api.h | 6 + crypto_sign/haetae2/clean/config.h | 19 + crypto_sign/haetae2/clean/decompose.c | 69 ++ crypto_sign/haetae2/clean/decompose.h | 16 + crypto_sign/haetae2/clean/encoding.c | 227 ++++++ crypto_sign/haetae2/clean/encoding.h | 17 + crypto_sign/haetae2/clean/fft.c | 231 ++++++ crypto_sign/haetae2/clean/fft.h | 19 + crypto_sign/haetae2/clean/fips202.c | 746 ++++++++++++++++++++ crypto_sign/haetae2/clean/fips202.h | 57 ++ crypto_sign/haetae2/clean/fixpoint.c | 140 ++++ crypto_sign/haetae2/clean/fixpoint.h | 126 ++++ crypto_sign/haetae2/clean/ntt.c | 95 +++ crypto_sign/haetae2/clean/ntt.h | 13 + crypto_sign/haetae2/clean/packing.c | 272 +++++++ crypto_sign/haetae2/clean/packing.h | 25 + crypto_sign/haetae2/clean/params.h | 116 +++ crypto_sign/haetae2/clean/poly.c | 653 +++++++++++++++++ crypto_sign/haetae2/clean/poly.h | 80 +++ crypto_sign/haetae2/clean/polyfix.c | 281 ++++++++ crypto_sign/haetae2/clean/polyfix.h | 61 ++ crypto_sign/haetae2/clean/polymat.c | 73 ++ crypto_sign/haetae2/clean/polymat.h | 28 + crypto_sign/haetae2/clean/polyvec.c | 543 ++++++++++++++ crypto_sign/haetae2/clean/polyvec.h | 129 ++++ crypto_sign/haetae2/clean/rans_byte.h | 333 +++++++++ crypto_sign/haetae2/clean/reduce.c | 92 +++ crypto_sign/haetae2/clean/reduce.h | 28 + crypto_sign/haetae2/clean/sampler.c | 272 +++++++ crypto_sign/haetae2/clean/sampler.h | 21 + crypto_sign/haetae2/clean/sign.c | 467 ++++++++++++ crypto_sign/haetae2/clean/sign.h | 30 + crypto_sign/haetae2/clean/symmetric-shake.c | 38 + crypto_sign/haetae2/clean/symmetric.h | 78 ++ 34 files changed, 5401 insertions(+) create mode 100644 crypto_sign/haetae2/clean/api.h create mode 100644 crypto_sign/haetae2/clean/config.h create mode 100644 crypto_sign/haetae2/clean/decompose.c create mode 100644 crypto_sign/haetae2/clean/decompose.h create mode 100644 crypto_sign/haetae2/clean/encoding.c create mode 100644 crypto_sign/haetae2/clean/encoding.h create mode 100644 crypto_sign/haetae2/clean/fft.c create mode 100644 crypto_sign/haetae2/clean/fft.h create mode 100644 crypto_sign/haetae2/clean/fips202.c create mode 100644 crypto_sign/haetae2/clean/fips202.h create mode 100644 crypto_sign/haetae2/clean/fixpoint.c create mode 100644 crypto_sign/haetae2/clean/fixpoint.h create mode 100644 crypto_sign/haetae2/clean/ntt.c create mode 100644 crypto_sign/haetae2/clean/ntt.h create mode 100644 crypto_sign/haetae2/clean/packing.c create mode 100644 crypto_sign/haetae2/clean/packing.h create mode 100644 crypto_sign/haetae2/clean/params.h create mode 100644 crypto_sign/haetae2/clean/poly.c create mode 100644 crypto_sign/haetae2/clean/poly.h create mode 100644 crypto_sign/haetae2/clean/polyfix.c create mode 100644 crypto_sign/haetae2/clean/polyfix.h create mode 100644 crypto_sign/haetae2/clean/polymat.c create mode 100644 crypto_sign/haetae2/clean/polymat.h create mode 100644 crypto_sign/haetae2/clean/polyvec.c create mode 100644 crypto_sign/haetae2/clean/polyvec.h create mode 100644 crypto_sign/haetae2/clean/rans_byte.h create mode 100644 crypto_sign/haetae2/clean/reduce.c create mode 100644 crypto_sign/haetae2/clean/reduce.h create mode 100644 crypto_sign/haetae2/clean/sampler.c create mode 100644 crypto_sign/haetae2/clean/sampler.h create mode 100644 crypto_sign/haetae2/clean/sign.c create mode 100644 crypto_sign/haetae2/clean/sign.h create mode 100644 crypto_sign/haetae2/clean/symmetric-shake.c create mode 100644 crypto_sign/haetae2/clean/symmetric.h diff --git a/crypto_sign/haetae2/clean/api.h b/crypto_sign/haetae2/clean/api.h new file mode 100644 index 00000000..28d58fca --- /dev/null +++ b/crypto_sign/haetae2/clean/api.h @@ -0,0 +1,6 @@ +#ifndef API_H +#define API_H + +#include "sign.h" + +#endif diff --git a/crypto_sign/haetae2/clean/config.h b/crypto_sign/haetae2/clean/config.h new file mode 100644 index 00000000..983cd91b --- /dev/null +++ b/crypto_sign/haetae2/clean/config.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 2 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/decompose.c b/crypto_sign/haetae2/clean/decompose.c new file mode 100644 index 00000000..467767e5 --- /dev/null +++ b/crypto_sign/haetae2/clean/decompose.c @@ -0,0 +1,69 @@ +#include "decompose.h" +#include "params.h" +#include + +/************************************************* + * Name: decompose_z1 + * + * Description: For finite field element r, compute high and lowbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *lowbits: pointer to output element lb + * - int32_t *highbits: pointer to output element hb + **************************************************/ +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r) { + const int alpha = 256; // TODO magic numbers! + const int log_alpha = 8; + + int32_t lb, center; + uint32_t alpha_mask = alpha - 1; + + lb = r & alpha_mask; + center = ((alpha >> 1) - (lb + 1)) >> 31; // if lb >= HALF_ALPHA + lb -= alpha & center; + *lowbits = lb; + *highbits = (r + (alpha >> 1)) >> log_alpha; +} + +/************************************************* + * Name: decompose_hint + * + * Description: For finite field element r, compute highbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *highbits: pointer to output element hb + **************************************************/ + +void decompose_hint(int32_t *highbits, const int32_t r) { + int32_t hb, edgecase; + + hb = (r + HALF_ALPHA_HINT) >> LOG_ALPHA_HINT; + edgecase = + ((DQ - 2) / ALPHA_HINT - (hb + 1)) >> 31; // if hb == (DQ-2)/ALPHA + hb -= (DQ - 2) / ALPHA_HINT & edgecase; // hb = 0 + + *highbits = hb; +} + +/************************************************* + * Name: decompose_vk + * + * Description: For finite field element a, compute a0, a1 such that + * a mod^+ Q = a1*2^D + a0 with -2^{D-1} <= a0 < 2^{D-1}. + * Assumes a to be standard representative. + * + * Arguments: - int32_t a: input element + * - int32_t *a0: pointer to output element a0 + * + * Returns a1 + **************************************************/ +int32_t decompose_vk(int32_t *a0, const int32_t a) { +#if D > 1 +#error "Only implemented for D = 1" +#endif + *a0 = a & 1; + *a0 -= ((a >> 1) & *a0) << 1; + return (a - *a0) >> 1; +} diff --git a/crypto_sign/haetae2/clean/decompose.h b/crypto_sign/haetae2/clean/decompose.h new file mode 100644 index 00000000..67146cf1 --- /dev/null +++ b/crypto_sign/haetae2/clean/decompose.h @@ -0,0 +1,16 @@ +#ifndef HAETAE_ROUNDING_H +#define HAETAE_ROUNDING_H + +#include "params.h" +#include + +#define decompose_z1 HAETAE_NAMESPACE(decompose_z1) +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r); + +#define decompose_hint HAETAE_NAMESPACE(decompose_hint) +void decompose_hint(int32_t *highbits, const int32_t r); + +#define decompose_vk HAETAE_NAMESPACE(decompose_vk) +int32_t decompose_vk(int32_t *a0, const int32_t a); + +#endif diff --git a/crypto_sign/haetae2/clean/encoding.c b/crypto_sign/haetae2/clean/encoding.c new file mode 100644 index 00000000..ca6a182f --- /dev/null +++ b/crypto_sign/haetae2/clean/encoding.c @@ -0,0 +1,227 @@ +#include "encoding.h" +#include "params.h" +#include "rans_byte.h" + +#include +#include +#include + +#define SCALE_BITS 10 +#define SCALE (1u << SCALE_BITS) + +#if HAETAE_MODE == 2 +#define M_H 13 +#define OFFSET_H 239 +#define M_HB_Z1 13 +#define OFFSET_HB_Z1 6 +static RansEncSymbol esyms_h[M_H] = {{801112064, -1416664605, 0, 642, 8}, {515899392, -2060187564, 382, 778, 7}, {136314880, -66076419, 628, 959, 6}, {14680064, -1840700269, 693, 1017, 2}, {2097152, -1, 1723, 1023, 0}, {2097152, -1, 1724, 1023, 0}, {2097152, -1, 1725, 1023, 0}, {2097152, -1, 1726, 1023, 0}, {2097152, -1, 1727, 1023, 0}, {2097152, -1, 1728, 1023, 0}, {14680064, -1840700269, 706, 1017, 2}, {136314880, -66076419, 713, 959, 6}, {515899392, -2060187564, 778, 778, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 382}, {382, 246}, {628, 65}, {693, 7}, {700, 1}, {701, 1}, {702, 1}, {703, 1}, {704, 1}, {705, 1}, {706, 7}, {713, 65}, {778, 246}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {10485760, -858993459, 3, 1019, 2}, {121634816, -1925330167, 8, 966, 5}, {515899392, -2060187564, 66, 778, 7}, {834666496, -1532375266, 312, 626, 8}, {517996544, -2069235255, 710, 777, 7}, {123731968, -1965493508, 957, 965, 5}, {10485760, -858993459, 1016, 1019, 2}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 5}, {8, 58}, {66, 246}, {312, 398}, {710, 247}, {957, 59}, {1016, 5}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 11, 12, }; + +#elif HAETAE_MODE == 3 +#define M_H 17 +#define OFFSET_H 235 +#define M_HB_Z1 17 +#define OFFSET_HB_Z1 8 +static RansEncSymbol esyms_h[M_H] = {{557842432, -161464935, 0, 758, 8}, {446693376, -1713954085, 266, 811, 7}, {236978176, -1862419446, 479, 911, 6}, {83886080, -858993459, 592, 984, 5}, {18874368, -477218588, 632, 1015, 3}, {2097152, -1, 1664, 1023, 0}, {2097152, -1, 1665, 1023, 0}, {2097152, -1, 1666, 1023, 0}, {2097152, -1, 1667, 1023, 0}, {2097152, -1, 1668, 1023, 0}, {2097152, -1, 1669, 1023, 0}, {2097152, -1, 1670, 1023, 0}, {2097152, -1, 1671, 1023, 0}, {18874368, -477218588, 649, 1015, 3}, {83886080, -858993459, 658, 984, 5}, {236978176, -1862419446, 698, 911, 6}, {446693376, -1713954085, 811, 811, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 266}, {266, 213}, {479, 113}, {592, 40}, {632, 9}, {641, 1}, {642, 1}, {643, 1}, {644, 1}, {645, 1}, {646, 1}, {647, 1}, {648, 1}, {649, 9}, {658, 40}, {698, 113}, {811, 213}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {16777216, -2147483648, 4, 1016, 2}, {77594624, -580400985, 12, 987, 5}, {234881024, -1840700269, 49, 912, 6}, {452984832, -1749801490, 161, 808, 7}, {564133888, -207563475, 377, 755, 8}, {452984832, -1749801490, 646, 808, 7}, {234881024, -1840700269, 862, 912, 6}, {79691776, -678152730, 974, 986, 5}, {16777216, -2147483648, 1012, 1016, 2}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 8}, {12, 37}, {49, 112}, {161, 216}, {377, 269}, {646, 216}, {862, 112}, {974, 38}, {1012, 8}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, }; + +#elif HAETAE_MODE == 5 +#define M_H 33 +#define OFFSET_H 471 +#define M_HB_Z1 19 +#define OFFSET_HB_Z1 9 +static RansEncSymbol esyms_h[M_H] = {{255852544, -2041869698, 0, 902, 6}, {245366784, -1945583475, 122, 907, 6}, {213909504, -1600085855, 239, 922, 6}, {169869312, -901412889, 341, 943, 6}, {123731968, -1965493508, 422, 965, 5}, {81788928, -770891565, 481, 985, 5}, {48234496, -1307163959, 520, 1001, 4}, {27262976, -1651910498, 543, 1011, 3}, {12582912, -1431655765, 556, 1018, 2}, {6291456, -1431655765, 562, 1021, 1}, {2097152, -1, 1588, 1023, 0}, {2097152, -1, 1589, 1023, 0}, {2097152, -1, 1590, 1023, 0}, {2097152, -1, 1591, 1023, 0}, {2097152, -1, 1592, 1023, 0}, {2097152, -1, 1593, 1023, 0}, {2097152, -1, 1594, 1023, 0}, {2097152, -1, 1595, 1023, 0}, {2097152, -1, 1596, 1023, 0}, {2097152, -1, 1597, 1023, 0}, {2097152, -1, 1598, 1023, 0}, {2097152, -1, 1599, 1023, 0}, {2097152, -1, 1600, 1023, 0}, {2097152, -1, 1601, 1023, 0}, {6291456, -1431655765, 579, 1021, 1}, {12582912, -1431655765, 582, 1018, 2}, {27262976, -1651910498, 588, 1011, 3}, {50331648, -1431655765, 601, 1000, 4}, {81788928, -770891565, 625, 985, 5}, {123731968, -1965493508, 664, 965, 5}, {169869312, -901412889, 723, 943, 6}, {213909504, -1600085855, 804, 922, 6}, {247463936, -1965493508, 906, 906, 6}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 122}, {122, 117}, {239, 102}, {341, 81}, {422, 59}, {481, 39}, {520, 23}, {543, 13}, {556, 6}, {562, 3}, {565, 1}, {566, 1}, {567, 1}, {568, 1}, {569, 1}, {570, 1}, {571, 1}, {572, 1}, {573, 1}, {574, 1}, {575, 1}, {576, 1}, {577, 1}, {578, 1}, {579, 3}, {582, 6}, {588, 13}, {601, 24}, {625, 39}, {664, 59}, {723, 81}, {804, 102}, {906, 118}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {4194304, -2147483648, 4, 1022, 0}, {27262976, -1651910498, 6, 1011, 3}, {100663296, -1431655765, 19, 976, 5}, {247463936, -1965493508, 67, 906, 6}, {427819008, -1600085855, 185, 820, 7}, {513802240, -2051066014, 389, 779, 7}, {427819008, -1600085855, 634, 820, 7}, {247463936, -1965493508, 838, 906, 6}, {100663296, -1431655765, 956, 976, 5}, {29360128, -1840700269, 1004, 1010, 3}, {4194304, -2147483648, 1018, 1022, 0}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 2}, {6, 13}, {19, 48}, {67, 118}, {185, 204}, {389, 245}, {634, 204}, {838, 118}, {956, 48}, {1004, 14}, {1018, 2}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 15, 16, 17, 18, }; + +#endif // HAETAE_MODE +#define H_CUT ((M_H -1) >>1) + +/************************************************* + * Name: encode_h + * + * Description: rANS encode polynomial vector h + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *h: pointer to polynomial vector h + **************************************************/ +uint16_t encode_h(uint8_t *buf, const int32_t *h) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + uint8_t encoding[size_h]; // size_h is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_h; // end of encoding buffer + + for (size_t i = size_h; i > 0; i--) { + tmp = h[i - 1]; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(H_CUT < tmp && tmp <= H_CUT + OFFSET_H) { + return 0; + } + // map the upper likely part of symbols next to the lower part + // to have a dense and compact distribution: + tmp = (tmp > (H_CUT + OFFSET_H)) ? tmp - OFFSET_H : tmp; + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_h[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_h - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_h + * + * Description: rANS decode polynomial vector h + * + * Arguments: - int32_t *h: pointer to polynomial vector h + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_h; i++) { + s = symbol_h[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_H) { + return 1; // invalid symbol + } + tmp = (H_CUT < tmp) ? (tmp + OFFSET_H) : tmp; + h[i] = tmp; + RansDecAdvanceSymbol(&rans, (uint8_t **) &buf, buf_end, &dsyms_h[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} + +/************************************************* + * Name: encode_hb_z1 + * + * Description: rANS encode polynomial vector HighBits(z1) + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *hb_z1: pointer to polynomial vector + *HighBits(z1) + **************************************************/ +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_hb_z1 = N * L; + int8_t s; + int32_t tmp; + uint8_t encoding[size_hb_z1]; // size_hb_z1 is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_hb_z1; // end of output buffer + + for (size_t i = size_hb_z1; i > 0; i--) { + // from centered to positive representation: + tmp = hb_z1[i - 1] + OFFSET_HB_Z1; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(tmp < 0 || M_HB_Z1 <= tmp) { + return 0; + } + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_hb_z1[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_hb_z1 - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_hb_z1 + * + * Description: rANS decode polynomial vector HighBits(z1) + * + * Arguments: - int32_t *hb_z1: pointer to polynomial vector HighBits(z1) + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_hb_z1 = N * L; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_hb_z1; i++) { + s = symbol_hb_z1[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_HB_Z1) { + return 1; // invalid symbol + } + // from positive to centered representation: + hb_z1[i] = tmp - OFFSET_HB_Z1; + RansDecAdvanceSymbol(&rans, (uint8_t **)&buf, buf_end, &dsyms_hb_z1[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/encoding.h b/crypto_sign/haetae2/clean/encoding.h new file mode 100644 index 00000000..b1e6239d --- /dev/null +++ b/crypto_sign/haetae2/clean/encoding.h @@ -0,0 +1,17 @@ +#ifndef HAETAE_ENCODING_H +#define HAETAE_ENCODING_H + +#include "params.h" +#include +#include + +#define encode_h HAETAE_NAMESPACE(encode_h) +uint16_t encode_h(uint8_t *buf, const int32_t *h); +#define decode_h HAETAE_NAMESPACE(decode_h) +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in); +#define encode_hb_z1 HAETAE_NAMESPACE(encode_hb_z1) +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1); +#define decode_hb_z1 HAETAE_NAMESPACE(decode_hb_z1) +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in); + +#endif // HAETAE_ENCODING_H diff --git a/crypto_sign/haetae2/clean/fft.c b/crypto_sign/haetae2/clean/fft.c new file mode 100644 index 00000000..f625ad79 --- /dev/null +++ b/crypto_sign/haetae2/clean/fft.c @@ -0,0 +1,231 @@ +#include "fft.h" + +static const complex_fp32_16 roots[] = { + {.real = +65536L, .imag = +0L}, {.real = +65531L, .imag = -804L}, + {.real = +65516L, .imag = -1608L}, {.real = +65492L, .imag = -2412L}, + {.real = +65457L, .imag = -3216L}, {.real = +65413L, .imag = -4019L}, + {.real = +65358L, .imag = -4821L}, {.real = +65294L, .imag = -5623L}, + {.real = +65220L, .imag = -6424L}, {.real = +65137L, .imag = -7224L}, + {.real = +65043L, .imag = -8022L}, {.real = +64940L, .imag = -8820L}, + {.real = +64827L, .imag = -9616L}, {.real = +64704L, .imag = -10411L}, + {.real = +64571L, .imag = -11204L}, {.real = +64429L, .imag = -11996L}, + {.real = +64277L, .imag = -12785L}, {.real = +64115L, .imag = -13573L}, + {.real = +63944L, .imag = -14359L}, {.real = +63763L, .imag = -15143L}, + {.real = +63572L, .imag = -15924L}, {.real = +63372L, .imag = -16703L}, + {.real = +63162L, .imag = -17479L}, {.real = +62943L, .imag = -18253L}, + {.real = +62714L, .imag = -19024L}, {.real = +62476L, .imag = -19792L}, + {.real = +62228L, .imag = -20557L}, {.real = +61971L, .imag = -21320L}, + {.real = +61705L, .imag = -22078L}, {.real = +61429L, .imag = -22834L}, + {.real = +61145L, .imag = -23586L}, {.real = +60851L, .imag = -24335L}, + {.real = +60547L, .imag = -25080L}, {.real = +60235L, .imag = -25821L}, + {.real = +59914L, .imag = -26558L}, {.real = +59583L, .imag = -27291L}, + {.real = +59244L, .imag = -28020L}, {.real = +58896L, .imag = -28745L}, + {.real = +58538L, .imag = -29466L}, {.real = +58172L, .imag = -30182L}, + {.real = +57798L, .imag = -30893L}, {.real = +57414L, .imag = -31600L}, + {.real = +57022L, .imag = -32303L}, {.real = +56621L, .imag = -33000L}, + {.real = +56212L, .imag = -33692L}, {.real = +55794L, .imag = -34380L}, + {.real = +55368L, .imag = -35062L}, {.real = +54934L, .imag = -35738L}, + {.real = +54491L, .imag = -36410L}, {.real = +54040L, .imag = -37076L}, + {.real = +53581L, .imag = -37736L}, {.real = +53114L, .imag = -38391L}, + {.real = +52639L, .imag = -39040L}, {.real = +52156L, .imag = -39683L}, + {.real = +51665L, .imag = -40320L}, {.real = +51166L, .imag = -40951L}, + {.real = +50660L, .imag = -41576L}, {.real = +50146L, .imag = -42194L}, + {.real = +49624L, .imag = -42806L}, {.real = +49095L, .imag = -43412L}, + {.real = +48559L, .imag = -44011L}, {.real = +48015L, .imag = -44604L}, + {.real = +47464L, .imag = -45190L}, {.real = +46906L, .imag = -45769L}, + {.real = +46341L, .imag = -46341L}, {.real = +45769L, .imag = -46906L}, + {.real = +45190L, .imag = -47464L}, {.real = +44604L, .imag = -48015L}, + {.real = +44011L, .imag = -48559L}, {.real = +43412L, .imag = -49095L}, + {.real = +42806L, .imag = -49624L}, {.real = +42194L, .imag = -50146L}, + {.real = +41576L, .imag = -50660L}, {.real = +40951L, .imag = -51166L}, + {.real = +40320L, .imag = -51665L}, {.real = +39683L, .imag = -52156L}, + {.real = +39040L, .imag = -52639L}, {.real = +38391L, .imag = -53114L}, + {.real = +37736L, .imag = -53581L}, {.real = +37076L, .imag = -54040L}, + {.real = +36410L, .imag = -54491L}, {.real = +35738L, .imag = -54934L}, + {.real = +35062L, .imag = -55368L}, {.real = +34380L, .imag = -55794L}, + {.real = +33692L, .imag = -56212L}, {.real = +33000L, .imag = -56621L}, + {.real = +32303L, .imag = -57022L}, {.real = +31600L, .imag = -57414L}, + {.real = +30893L, .imag = -57798L}, {.real = +30182L, .imag = -58172L}, + {.real = +29466L, .imag = -58538L}, {.real = +28745L, .imag = -58896L}, + {.real = +28020L, .imag = -59244L}, {.real = +27291L, .imag = -59583L}, + {.real = +26558L, .imag = -59914L}, {.real = +25821L, .imag = -60235L}, + {.real = +25080L, .imag = -60547L}, {.real = +24335L, .imag = -60851L}, + {.real = +23586L, .imag = -61145L}, {.real = +22834L, .imag = -61429L}, + {.real = +22078L, .imag = -61705L}, {.real = +21320L, .imag = -61971L}, + {.real = +20557L, .imag = -62228L}, {.real = +19792L, .imag = -62476L}, + {.real = +19024L, .imag = -62714L}, {.real = +18253L, .imag = -62943L}, + {.real = +17479L, .imag = -63162L}, {.real = +16703L, .imag = -63372L}, + {.real = +15924L, .imag = -63572L}, {.real = +15143L, .imag = -63763L}, + {.real = +14359L, .imag = -63944L}, {.real = +13573L, .imag = -64115L}, + {.real = +12785L, .imag = -64277L}, {.real = +11996L, .imag = -64429L}, + {.real = +11204L, .imag = -64571L}, {.real = +10411L, .imag = -64704L}, + {.real = +9616L, .imag = -64827L}, {.real = +8820L, .imag = -64940L}, + {.real = +8022L, .imag = -65043L}, {.real = +7224L, .imag = -65137L}, + {.real = +6424L, .imag = -65220L}, {.real = +5623L, .imag = -65294L}, + {.real = +4821L, .imag = -65358L}, {.real = +4019L, .imag = -65413L}, + {.real = +3216L, .imag = -65457L}, {.real = +2412L, .imag = -65492L}, + {.real = +1608L, .imag = -65516L}, {.real = +804L, .imag = -65531L}, + {.real = +0L, .imag = -65536L}, {.real = -804L, .imag = -65531L}, + {.real = -1608L, .imag = -65516L}, {.real = -2412L, .imag = -65492L}, + {.real = -3216L, .imag = -65457L}, {.real = -4019L, .imag = -65413L}, + {.real = -4821L, .imag = -65358L}, {.real = -5623L, .imag = -65294L}, + {.real = -6424L, .imag = -65220L}, {.real = -7224L, .imag = -65137L}, + {.real = -8022L, .imag = -65043L}, {.real = -8820L, .imag = -64940L}, + {.real = -9616L, .imag = -64827L}, {.real = -10411L, .imag = -64704L}, + {.real = -11204L, .imag = -64571L}, {.real = -11996L, .imag = -64429L}, + {.real = -12785L, .imag = -64277L}, {.real = -13573L, .imag = -64115L}, + {.real = -14359L, .imag = -63944L}, {.real = -15143L, .imag = -63763L}, + {.real = -15924L, .imag = -63572L}, {.real = -16703L, .imag = -63372L}, + {.real = -17479L, .imag = -63162L}, {.real = -18253L, .imag = -62943L}, + {.real = -19024L, .imag = -62714L}, {.real = -19792L, .imag = -62476L}, + {.real = -20557L, .imag = -62228L}, {.real = -21320L, .imag = -61971L}, + {.real = -22078L, .imag = -61705L}, {.real = -22834L, .imag = -61429L}, + {.real = -23586L, .imag = -61145L}, {.real = -24335L, .imag = -60851L}, + {.real = -25080L, .imag = -60547L}, {.real = -25821L, .imag = -60235L}, + {.real = -26558L, .imag = -59914L}, {.real = -27291L, .imag = -59583L}, + {.real = -28020L, .imag = -59244L}, {.real = -28745L, .imag = -58896L}, + {.real = -29466L, .imag = -58538L}, {.real = -30182L, .imag = -58172L}, + {.real = -30893L, .imag = -57798L}, {.real = -31600L, .imag = -57414L}, + {.real = -32303L, .imag = -57022L}, {.real = -33000L, .imag = -56621L}, + {.real = -33692L, .imag = -56212L}, {.real = -34380L, .imag = -55794L}, + {.real = -35062L, .imag = -55368L}, {.real = -35738L, .imag = -54934L}, + {.real = -36410L, .imag = -54491L}, {.real = -37076L, .imag = -54040L}, + {.real = -37736L, .imag = -53581L}, {.real = -38391L, .imag = -53114L}, + {.real = -39040L, .imag = -52639L}, {.real = -39683L, .imag = -52156L}, + {.real = -40320L, .imag = -51665L}, {.real = -40951L, .imag = -51166L}, + {.real = -41576L, .imag = -50660L}, {.real = -42194L, .imag = -50146L}, + {.real = -42806L, .imag = -49624L}, {.real = -43412L, .imag = -49095L}, + {.real = -44011L, .imag = -48559L}, {.real = -44604L, .imag = -48015L}, + {.real = -45190L, .imag = -47464L}, {.real = -45769L, .imag = -46906L}, + {.real = -46341L, .imag = -46341L}, {.real = -46906L, .imag = -45769L}, + {.real = -47464L, .imag = -45190L}, {.real = -48015L, .imag = -44604L}, + {.real = -48559L, .imag = -44011L}, {.real = -49095L, .imag = -43412L}, + {.real = -49624L, .imag = -42806L}, {.real = -50146L, .imag = -42194L}, + {.real = -50660L, .imag = -41576L}, {.real = -51166L, .imag = -40951L}, + {.real = -51665L, .imag = -40320L}, {.real = -52156L, .imag = -39683L}, + {.real = -52639L, .imag = -39040L}, {.real = -53114L, .imag = -38391L}, + {.real = -53581L, .imag = -37736L}, {.real = -54040L, .imag = -37076L}, + {.real = -54491L, .imag = -36410L}, {.real = -54934L, .imag = -35738L}, + {.real = -55368L, .imag = -35062L}, {.real = -55794L, .imag = -34380L}, + {.real = -56212L, .imag = -33692L}, {.real = -56621L, .imag = -33000L}, + {.real = -57022L, .imag = -32303L}, {.real = -57414L, .imag = -31600L}, + {.real = -57798L, .imag = -30893L}, {.real = -58172L, .imag = -30182L}, + {.real = -58538L, .imag = -29466L}, {.real = -58896L, .imag = -28745L}, + {.real = -59244L, .imag = -28020L}, {.real = -59583L, .imag = -27291L}, + {.real = -59914L, .imag = -26558L}, {.real = -60235L, .imag = -25821L}, + {.real = -60547L, .imag = -25080L}, {.real = -60851L, .imag = -24335L}, + {.real = -61145L, .imag = -23586L}, {.real = -61429L, .imag = -22834L}, + {.real = -61705L, .imag = -22078L}, {.real = -61971L, .imag = -21320L}, + {.real = -62228L, .imag = -20557L}, {.real = -62476L, .imag = -19792L}, + {.real = -62714L, .imag = -19024L}, {.real = -62943L, .imag = -18253L}, + {.real = -63162L, .imag = -17479L}, {.real = -63372L, .imag = -16703L}, + {.real = -63572L, .imag = -15924L}, {.real = -63763L, .imag = -15143L}, + {.real = -63944L, .imag = -14359L}, {.real = -64115L, .imag = -13573L}, + {.real = -64277L, .imag = -12785L}, {.real = -64429L, .imag = -11996L}, + {.real = -64571L, .imag = -11204L}, {.real = -64704L, .imag = -10411L}, + {.real = -64827L, .imag = -9616L}, {.real = -64940L, .imag = -8820L}, + {.real = -65043L, .imag = -8022L}, {.real = -65137L, .imag = -7224L}, + {.real = -65220L, .imag = -6424L}, {.real = -65294L, .imag = -5623L}, + {.real = -65358L, .imag = -4821L}, {.real = -65413L, .imag = -4019L}, + {.real = -65457L, .imag = -3216L}, {.real = -65492L, .imag = -2412L}, + {.real = -65516L, .imag = -1608L}, {.real = -65531L, .imag = -804L}}; + +static inline int32_t _mulrnd16(const int32_t x, const int32_t y) { + int64_t r = ((int64_t)x * (int64_t)y) + (1 << 15); + return r >> 16; +} + +static inline int32_t _complex_mul_real(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.real) - _mulrnd16(x.imag, y.imag); +} + +static inline int32_t _complex_mul_imag(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.imag) + _mulrnd16(x.imag, y.real); +} + +static void _complex_mul(complex_fp32_16 *r, const complex_fp32_16 x, + const complex_fp32_16 y) { + r->real = _complex_mul_real(x, y); + r->imag = _complex_mul_imag(x, y); +} + +const uint16_t brv9[] = { + 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, + 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, + 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, + 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, + 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, + 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, + 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, + 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, + 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, + 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, + 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, + 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, + 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, + 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, + 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, + 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, + 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, + 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, + 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, + 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, + 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, + 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, + 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, + 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, + 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, + 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, + 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, + 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, + 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, + 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 263, + 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, + 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, + 15, 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, + 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, + 255, 511}; + +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x) { + int i, inv_i; + for (i = 0; i < N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = x->coeffs[i] << 16; + } + for (i = N; i < FFT_N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = 0; + } +} + +int32_t complex_fp_sqabs(complex_fp32_16 x) { + return _mulrnd16(x.real, x.real) + _mulrnd16(x.imag, x.imag); +} + +void fft(complex_fp32_16 data[FFT_N]) { + unsigned int r, m, md2, n, k, even, odd, twid; + complex_fp32_16 u, t; + + for (r = 1; r <= FFT_LOGN; r++) { + m = 1 << r; + md2 = m >> 1; + for (n = 0; n < FFT_N; n += m) { + for (k = 0; k < md2; k++) { + even = n + k; + odd = even + md2; + twid = k << (FFT_LOGN - r); + + u = data[even]; + _complex_mul(&t, roots[twid], data[odd]); + data[even].real = u.real + t.real; + data[even].imag = u.imag + t.imag; + data[odd].real = u.real - t.real; + data[odd].imag = u.imag - t.imag; + } + } + } +} diff --git a/crypto_sign/haetae2/clean/fft.h b/crypto_sign/haetae2/clean/fft.h new file mode 100644 index 00000000..46a365ce --- /dev/null +++ b/crypto_sign/haetae2/clean/fft.h @@ -0,0 +1,19 @@ +#ifndef FFT__H +#define FFT__H + +#include "poly.h" +#include + +#define FFT_N 512 +#define FFT_LOGN 9 + +typedef struct { + int32_t real; + int32_t imag; +} complex_fp32_16; + +void fft(complex_fp32_16 data[FFT_N]); +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x); +int32_t complex_fp_sqabs(complex_fp32_16 x); + +#endif diff --git a/crypto_sign/haetae2/clean/fips202.c b/crypto_sign/haetae2/clean/fips202.c new file mode 100644 index 00000000..e0ec2668 --- /dev/null +++ b/crypto_sign/haetae2/clean/fips202.c @@ -0,0 +1,746 @@ +/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ + * from http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public + * domain "TweetFips202" implementation from https://twitter.com/tweetfips202 by + * Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ + +#include "fips202.h" +#include +#include + +#define NROUNDS 24 +#define ROL(a, offset) ((a << offset) ^ (a >> (64 - offset))) + +/************************************************* + * Name: load64 + * + * Description: Load 8 bytes into uint64_t in little-endian order + * + * Arguments: - const uint8_t *x: pointer to input byte array + * + * Returns the loaded 64-bit unsigned integer + **************************************************/ +static uint64_t load64(const uint8_t x[8]) { + unsigned int i; + uint64_t r = 0; + + for (i = 0; i < 8; ++i) + r |= (uint64_t)x[i] << 8 * i; + + return r; +} + +/************************************************* + * Name: store64 + * + * Description: Store a 64-bit integer to array of 8 bytes in little-endian + *order + * + * Arguments: - uint8_t *x: pointer to the output byte array (allocated) + * - uint64_t u: input 64-bit unsigned integer + **************************************************/ +static void store64(uint8_t x[8], uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) + x[i] = u >> 8 * i; +} + +/* Keccak round constants */ +const uint64_t KeccakF_RoundConstants[NROUNDS] = { + (uint64_t)0x0000000000000001ULL, (uint64_t)0x0000000000008082ULL, + (uint64_t)0x800000000000808aULL, (uint64_t)0x8000000080008000ULL, + (uint64_t)0x000000000000808bULL, (uint64_t)0x0000000080000001ULL, + (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008009ULL, + (uint64_t)0x000000000000008aULL, (uint64_t)0x0000000000000088ULL, + (uint64_t)0x0000000080008009ULL, (uint64_t)0x000000008000000aULL, + (uint64_t)0x000000008000808bULL, (uint64_t)0x800000000000008bULL, + (uint64_t)0x8000000000008089ULL, (uint64_t)0x8000000000008003ULL, + (uint64_t)0x8000000000008002ULL, (uint64_t)0x8000000000000080ULL, + (uint64_t)0x000000000000800aULL, (uint64_t)0x800000008000000aULL, + (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008080ULL, + (uint64_t)0x0000000080000001ULL, (uint64_t)0x8000000080008008ULL}; + +/************************************************* + * Name: KeccakF1600_StatePermute + * + * Description: The Keccak F1600 Permutation + * + * Arguments: - uint64_t *state: pointer to input/output Keccak state + **************************************************/ +static void KeccakF1600_StatePermute(uint64_t state[25]) { + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + // copyFromState(A, state) + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; + BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + // thetaRhoPiChiIotaPrepareTheta(round, A, E) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^ ((~BCe) & BCi); + Eba ^= (uint64_t)KeccakF_RoundConstants[round]; + Ebe = BCe ^ ((~BCi) & BCo); + Ebi = BCi ^ ((~BCo) & BCu); + Ebo = BCo ^ ((~BCu) & BCa); + Ebu = BCu ^ ((~BCa) & BCe); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^ ((~BCe) & BCi); + Ege = BCe ^ ((~BCi) & BCo); + Egi = BCi ^ ((~BCo) & BCu); + Ego = BCo ^ ((~BCu) & BCa); + Egu = BCu ^ ((~BCa) & BCe); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^ ((~BCe) & BCi); + Eke = BCe ^ ((~BCi) & BCo); + Eki = BCi ^ ((~BCo) & BCu); + Eko = BCo ^ ((~BCu) & BCa); + Eku = BCu ^ ((~BCa) & BCe); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^ ((~BCe) & BCi); + Eme = BCe ^ ((~BCi) & BCo); + Emi = BCi ^ ((~BCo) & BCu); + Emo = BCo ^ ((~BCu) & BCa); + Emu = BCu ^ ((~BCa) & BCe); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^ ((~BCe) & BCi); + Ese = BCe ^ ((~BCi) & BCo); + Esi = BCi ^ ((~BCo) & BCu); + Eso = BCo ^ ((~BCu) & BCa); + Esu = BCu ^ ((~BCa) & BCe); + + // prepareTheta + BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^ ((~BCe) & BCi); + Aba ^= (uint64_t)KeccakF_RoundConstants[round + 1]; + Abe = BCe ^ ((~BCi) & BCo); + Abi = BCi ^ ((~BCo) & BCu); + Abo = BCo ^ ((~BCu) & BCa); + Abu = BCu ^ ((~BCa) & BCe); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^ ((~BCe) & BCi); + Age = BCe ^ ((~BCi) & BCo); + Agi = BCi ^ ((~BCo) & BCu); + Ago = BCo ^ ((~BCu) & BCa); + Agu = BCu ^ ((~BCa) & BCe); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^ ((~BCe) & BCi); + Ake = BCe ^ ((~BCi) & BCo); + Aki = BCi ^ ((~BCo) & BCu); + Ako = BCo ^ ((~BCu) & BCa); + Aku = BCu ^ ((~BCa) & BCe); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^ ((~BCe) & BCi); + Ame = BCe ^ ((~BCi) & BCo); + Ami = BCi ^ ((~BCo) & BCu); + Amo = BCo ^ ((~BCu) & BCa); + Amu = BCu ^ ((~BCa) & BCe); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^ ((~BCe) & BCi); + Ase = BCe ^ ((~BCi) & BCo); + Asi = BCi ^ ((~BCo) & BCu); + Aso = BCo ^ ((~BCu) & BCa); + Asu = BCu ^ ((~BCa) & BCe); + } + + // copyToState(state, A) + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* + * Name: keccak_init + * + * Description: Initializes the Keccak state. + * + * Arguments: - uint64_t *s: pointer to Keccak state + **************************************************/ +static void keccak_init(uint64_t s[25]) { + unsigned int i; + for (i = 0; i < 25; ++i) + s[i] = 0; +} + +/************************************************* + * Name: keccak_absorb + * + * Description: Absorb step of Keccak; incremental. + * + * Arguments: - uint64_t *s: pointer to Keccak state + * - unsigned int pos: position in current block to be absorbed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + * + * Returns new position pos in current block + **************************************************/ +static unsigned int keccak_absorb(uint64_t s[25], unsigned int pos, + unsigned int r, const uint8_t *in, + size_t inlen) { + unsigned int i; + + while (pos + inlen >= r) { + for (i = pos; i < r; ++i) + s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); + inlen -= r - pos; + KeccakF1600_StatePermute(s); + pos = 0; + } + + for (i = pos; i < pos + inlen; ++i) + s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); + + return i; +} + +/************************************************* + * Name: keccak_finalize + * + * Description: Finalize absorb step. + * + * Arguments: - uint64_t *s: pointer to Keccak state + * - unsigned int pos: position in current block to be absorbed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - uint8_t p: domain separation byte + **************************************************/ +static void keccak_finalize(uint64_t s[25], unsigned int pos, unsigned int r, + uint8_t p) { + s[pos / 8] ^= (uint64_t)p << 8 * (pos % 8); + s[r / 8 - 1] ^= 1ULL << 63; +} + +/************************************************* + * Name: keccak_squeeze + * + * Description: Squeeze step of Keccak. Squeezes arbitratrily many bytes. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: number of bytes to be squeezed (written to out) + * - uint64_t *s: pointer to input/output Keccak state + * - unsigned int pos: number of bytes in current block already + *squeezed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * + * Returns new position pos in current block + **************************************************/ +static unsigned int keccak_squeeze(uint8_t *out, size_t outlen, uint64_t s[25], + unsigned int pos, unsigned int r) { + unsigned int i; + + while (outlen) { + if (pos == r) { + KeccakF1600_StatePermute(s); + pos = 0; + } + for (i = pos; i < r && i < pos + outlen; ++i) + *out++ = s[i / 8] >> 8 * (i % 8); + outlen -= i - pos; + pos = i; + } + + return pos; +} + +/************************************************* + * Name: keccak_absorb_once + * + * Description: Absorb step of Keccak; + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + * - uint8_t p: domain-separation byte for different Keccak-derived + *functions + **************************************************/ +static void keccak_absorb_once(uint64_t s[25], unsigned int r, + const uint8_t *in, size_t inlen, uint8_t p) { + unsigned int i; + + for (i = 0; i < 25; ++i) + s[i] = 0; + + while (inlen >= r) { + for (i = 0; i < r / 8; ++i) + s[i] ^= load64(in + 8 * i); + in += r; + inlen -= r; + KeccakF1600_StatePermute(s); + } + + for (i = 0; i < inlen; ++i) + s[i / 8] ^= (uint64_t)in[i] << 8 * (i % 8); + + s[i / 8] ^= (uint64_t)p << 8 * (i % 8); + s[(r - 1) / 8] ^= 1ULL << 63; +} + +/************************************************* + * Name: keccak_squeezeblocks + * + * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. Assumes zero bytes of current + * block have already been squeezed. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *out) + * - uint64_t *s: pointer to input/output Keccak state + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_squeezeblocks(uint8_t *out, size_t nblocks, uint64_t s[25], + unsigned int r) { + unsigned int i; + + while (nblocks) { + KeccakF1600_StatePermute(s); + for (i = 0; i < r / 8; ++i) + store64(out + 8 * i, s[i]); + out += r; + nblocks -= 1; + } +} + +/************************************************* + * Name: shake128_init + * + * Description: Initilizes Keccak state for use as SHAKE128 XOF + * + * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state + **************************************************/ +void shake128_init(keccak_state *state) { + keccak_init(state->s); + state->pos = 0; +} + +/************************************************* + * Name: shake128_absorb + * + * Description: Absorb step of the SHAKE128 XOF; incremental. + * + * Arguments: - keccak_state *state: pointer to (initialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { + state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); +} + +/************************************************* + * Name: shake128_finalize + * + * Description: Finalize absorb step of the SHAKE128 XOF. + * + * Arguments: - keccak_state *state: pointer to Keccak state + **************************************************/ +void shake128_finalize(keccak_state *state) { + keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* + * Name: shake128_squeeze + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many + * bytes. Can be called multiple times to keep squeezing. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t outlen : number of bytes to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { + state->pos = + keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); +} + +/************************************************* + * Name: shake128_absorb_once + * + * Description: Initialize, absorb into and finalize SHAKE128 XOF; + *non-incremental. + * + * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb_once(keccak_state *state, const uint8_t *in, + size_t inlen) { + keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* + * Name: shake128_squeezeblocks + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of + * SHAKE128_RATE bytes each. Can be called multiple times + * to keep squeezing. Assumes new block has not yet been + * started (state->pos = SHAKE128_RATE). + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { + keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); +} + +/************************************************* + * Name: shake256_init + * + * Description: Initilizes Keccak state for use as SHAKE256 XOF + * + * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state + **************************************************/ +void shake256_init(keccak_state *state) { + keccak_init(state->s); + state->pos = 0; +} + +/************************************************* + * Name: shake256_absorb + * + * Description: Absorb step of the SHAKE256 XOF; incremental. + * + * Arguments: - keccak_state *state: pointer to (initialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { + state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); +} + +/************************************************* + * Name: shake256_finalize + * + * Description: Finalize absorb step of the SHAKE256 XOF. + * + * Arguments: - keccak_state *state: pointer to Keccak state + **************************************************/ +void shake256_finalize(keccak_state *state) { + keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* + * Name: shake256_squeeze + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many + * bytes. Can be called multiple times to keep squeezing. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t outlen : number of bytes to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { + state->pos = + keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); +} + +/************************************************* + * Name: shake256_absorb_once + * + * Description: Initialize, absorb into and finalize SHAKE256 XOF; + *non-incremental. + * + * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb_once(keccak_state *state, const uint8_t *in, + size_t inlen) { + keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* + * Name: shake256_squeezeblocks + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of + * SHAKE256_RATE bytes each. Can be called multiple times + * to keep squeezing. Assumes next block has not yet been + * started (state->pos = SHAKE256_RATE). + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { + keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); +} + +/************************************************* + * Name: shake128 + * + * Description: SHAKE128 XOF with non-incremental API + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { + size_t nblocks; + keccak_state state; + + shake128_absorb_once(&state, in, inlen); + nblocks = outlen / SHAKE128_RATE; + shake128_squeezeblocks(out, nblocks, &state); + outlen -= nblocks * SHAKE128_RATE; + out += nblocks * SHAKE128_RATE; + shake128_squeeze(out, outlen, &state); +} + +/************************************************* + * Name: shake256 + * + * Description: SHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { + size_t nblocks; + keccak_state state; + + shake256_absorb_once(&state, in, inlen); + nblocks = outlen / SHAKE256_RATE; + shake256_squeezeblocks(out, nblocks, &state); + outlen -= nblocks * SHAKE256_RATE; + out += nblocks * SHAKE256_RATE; + shake256_squeeze(out, outlen, &state); +} + +/************************************************* + * Name: sha3_256 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *h: pointer to output (32 bytes) + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) { + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for (i = 0; i < 4; ++i) + store64(h + 8 * i, s[i]); +} + +/************************************************* + * Name: sha3_512 + * + * Description: SHA3-512 with non-incremental API + * + * Arguments: - uint8_t *h: pointer to output (64 bytes) + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) { + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for (i = 0; i < 8; ++i) + store64(h + 8 * i, s[i]); +} diff --git a/crypto_sign/haetae2/clean/fips202.h b/crypto_sign/haetae2/clean/fips202.h new file mode 100644 index 00000000..58aa8ff2 --- /dev/null +++ b/crypto_sign/haetae2/clean/fips202.h @@ -0,0 +1,57 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_512_RATE 72 + +#define FIPS202_NAMESPACE(s) haetae_fips202_##s + +typedef struct { + uint64_t s[25]; + unsigned int pos; +} keccak_state; + +#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) +extern const uint64_t KeccakF_RoundConstants[]; + +#define shake128_init FIPS202_NAMESPACE(shake128_init) +void shake128_init(keccak_state *state); +#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) +void shake128_finalize(keccak_state *state); +#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) +void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake256_init FIPS202_NAMESPACE(shake256_init) +void shake256_init(keccak_state *state); +#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) +void shake256_finalize(keccak_state *state); +#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) +void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake128 FIPS202_NAMESPACE(shake128) +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define shake256 FIPS202_NAMESPACE(shake256) +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define sha3_256 FIPS202_NAMESPACE(sha3_256) +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); +#define sha3_512 FIPS202_NAMESPACE(sha3_512) +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); + +#endif diff --git a/crypto_sign/haetae2/clean/fixpoint.c b/crypto_sign/haetae2/clean/fixpoint.c new file mode 100644 index 00000000..831f15ec --- /dev/null +++ b/crypto_sign/haetae2/clean/fixpoint.c @@ -0,0 +1,140 @@ +#include "fixpoint.h" +#include "params.h" +#include +#include + +static void __cneg(fp96_76 *x, const uint8_t sign) { + x->limb48[0] ^= (-(int64_t)sign) & ((1ULL << 48) - 1); + x->limb48[1] ^= -(int64_t)sign; + x->limb48[0] += sign; + renormalize(x); +} + +static void __copy_cneg(fp96_76 *y, const fp96_76 *x, const uint8_t sign) { + y->limb48[0] = ((-(int64_t)sign) & ((1ULL << 48) - 1)) ^ x->limb48[0]; + ; + y->limb48[1] = x->limb48[1] ^ (-(int64_t)sign); + y->limb48[0] += sign; + renormalize(y); +} + +static void fixpoint_mul(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y->limb48[0]); + + // shift right by 48, rounding + xy->limb48[0] = xy->limb48[1] + (((xy->limb48[0] >> 47) + 1) >> 1); + + mul48(tmp, x->limb48[0], y->limb48[1]); + xy->limb48[0] += tmp[0]; + xy->limb48[1] = tmp[1]; + mulacc48(&xy->limb48[0], x->limb48[1], y->limb48[0]); + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + mul64(tmp, x->limb48[1], y->limb48[1]); + xy->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(xy); +} + +static void fixpoint_unsigned_signed_mul(fp96_76 *xy, const fp96_76 *y) { + fp96_76 x, z; + uint8_t sign = (y->limb48[1] >> 63) & 1; + __copy_cneg(&x, y, sign); + fixpoint_mul(&z, &x, xy); + __copy_cneg(xy, &z, sign); +} + +static void fixpoint_sub(fp96_76 *xminy, const fp96_76 *x, const fp96_76 *y) { + fp96_76 yneg; + __copy_cneg(&yneg, y, 1); + fixpoint_add(xminy, x, &yneg); +} + +static void fixpoint_sub_from_threehalves(fp96_76 *x) { + __cneg(x, 1); + x->limb48[1] += 3ULL << 27; // left shift by 28 would be "3" + renormalize(x); +} + +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x) { + uint64_t tmp[2]; + sq48(&sqx->limb48[0], x->limb48[0]); + + // shift right by 48, rounding + //sqx->limb48[0] += 1ULL << 47; + sqx->limb48[0] >>= 48; + sqx->limb48[0] += sqx->limb48[1]; + + // mul + mul48(tmp, x->limb48[0], x->limb48[1]); + sqx->limb48[0] += tmp[0] << 1; + sqx->limb48[1] = tmp[1] << 1; + + // shift right by 28, rounding + //sqx->limb48[0] += 1ULL << 27; + sqx->limb48[0] >>= 28; + sqx->limb48[0] += (sqx->limb48[1] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] >>= 28; + + sq64(tmp, x->limb48[1]); + sqx->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(sqx); +} + +// start_cube = hex(round(2^64/(sqrt((K + L)*N + 2)^3))) +// start_times_threehalfs = hex(round(2^64 * 2/(3 * sqrt((K + L)*N + 2)))) +#if L == 4 +const fp96_76 start_cube = {.limb48 = {0x770077e2e41aULL, 0x1162ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x693861ad937bULL, 0x9caa56ULL}}; +#elif L == 6 +const fp96_76 start_cube = {.limb48 = {0x1a2935cfae68ULL, 0x978ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x7ad215218533ULL, 0x7ff1c9ULL}}; +#elif L == 7 +const fp96_76 start_cube = {.limb48 = {0x700ff3e8890dULL, 0x702ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x5768588eed31ULL, 0x73bd40ULL}}; +#endif + +// implements Newton's method +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf) { + fp96_76 tmp, tmp2; + fixpoint_mul(&tmp, xhalf, &start_cube); // definitely two positive values + fixpoint_sub(invsqrtx, &start_times_threehalves, + &tmp); // first Newton iteration done, might be negative (very + // improbable) + + for (int i = 0; i < 6; i++) // 6 more iterations + { + fixpoint_square(&tmp, invsqrtx); // tmp = y^2, never negative + fixpoint_mul(&tmp2, xhalf, &tmp); // tmp2 = x/2 * y^2, never negative + fixpoint_sub_from_threehalves(&tmp2); // tmp = 3/2 - x/2 * y^2 + fixpoint_unsigned_signed_mul(invsqrtx, &tmp2); // y * (3/2 - x/2 * y^2) + } +} + +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign) { + int64_t res; + fp96_76 tmp, xx; + xx.limb48[1] = x >> 32; + xx.limb48[0] = (x & ((1ULL << 32) - 1)) << 16; + fixpoint_mul(&tmp, &xx, y); + res = (tmp.limb48[1] + (1UL << 14)) >> 15; // rounding + return (1 - 2 * (int32_t)sign) * res; +} + +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + xy->limb48[0] = x->limb48[0] + y->limb48[0]; + xy->limb48[1] = x->limb48[1] + y->limb48[1]; +} diff --git a/crypto_sign/haetae2/clean/fixpoint.h b/crypto_sign/haetae2/clean/fixpoint.h new file mode 100644 index 00000000..7e608aa0 --- /dev/null +++ b/crypto_sign/haetae2/clean/fixpoint.h @@ -0,0 +1,126 @@ +#ifndef FP__H +#define FP__H + +#include "config.h" +#include +#include + +#ifdef __SIZEOF_INT128__ +__extension__ typedef __int128 int128; +__extension__ typedef unsigned __int128 uint128; +#endif + +typedef struct { + uint64_t limb48[2]; +} fp96_76; + +#define fixpoint_square HAETAE_NAMESPACE(fixpoint_square) +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x); + +#define fixpoint_newton_invsqrt HAETAE_NAMESPACE(fixpoint_newton_invsqrt) +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf); + +#define fixpoint_mul_rnd13 HAETAE_NAMESPACE(fixpoint_mul_rnd13) +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign); + +#define fixpoint_add HAETAE_NAMESPACE(fixpoint_add) +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y); + +static inline void renormalize(fp96_76 *x) { + x->limb48[1] += x->limb48[0] >> 48; + x->limb48[0] &= (1ULL << 48) - 1; +} + +static inline int64_t smulh48(int64_t a, uint64_t b) { +#ifndef __SIZEOF_INT128__ + int64_t ah = a >> 24; + int64_t al = a - (ah << 24); + int64_t bl = b & ((1<<24)-1); + int64_t bh = b >> 24; + + int64_t res = (al*bl) >> 24; + res += al * bh + ah * bl + (1 << 23); // rounding + res >>= 24; + return res + (ah * bh); +#else + return ((int128)a * (int128)b + (1ULL << 47)) >> 48; // rounding +#endif +} + +static inline void mul64(uint64_t r[2], const uint64_t b, const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), bl = b & ((1ULL << 32) - 1), + ah = a >> 32, bh = b >> 32; + r[0] = a * b; + r[1] = ah * bl + al * bh + ((al * bl) >> 32); + r[1] >>= 32; + r[1] += ah * bh; +#else + uint128 res = ((uint128)a * (uint128)b); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void sq64(uint64_t r[2], const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = ah * al * 2; + r[1] >>= 32; + r[1] += ah * ah; +#else + uint128 res = ((uint128)a * (uint128)a); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void mul48(uint64_t r[2], const uint64_t b, const uint64_t a) { + mul64(r, b, a); + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void mulacc48(uint64_t r[2], const uint64_t b, const uint64_t a) { + uint64_t tmp[2]; + mul48(tmp, b, a); + r[0] += tmp[0]; + r[1] += tmp[1]; +} + +// (a0 + a1*2^32)^2 = a0^2 + 2^33*a0*a1 + 2^64*a1^2 +static inline void sq48(uint64_t r[2], const uint64_t a) { + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = al * ah << 1; + r[1] >>= 32; + r[1] += ah * ah; + + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void fixpoint_mul_high(fp96_76 *xy, const fp96_76 *x, + const uint64_t y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y); // implicitly shifted right by 48 + + mul48(tmp, x->limb48[1], y); + xy->limb48[1] += tmp[0]; + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + xy->limb48[1] += tmp[1] << 20; + + renormalize(xy); +} + +#endif diff --git a/crypto_sign/haetae2/clean/ntt.c b/crypto_sign/haetae2/clean/ntt.c new file mode 100644 index 00000000..6b66d3f6 --- /dev/null +++ b/crypto_sign/haetae2/clean/ntt.c @@ -0,0 +1,95 @@ +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include + +static const int32_t zetas[N] = { + 0, 26964, -16505, 22229, 30746, 20243, 19064, -31218, 9395, + -30985, 22859, -8851, 32144, 13744, 21408, 17599, -16039, -22946, + 6241, -19553, 10681, 22935, 22431, -29104, 28147, -27527, -29133, + -20035, 20143, -11361, 30820, 25252, -22562, -6789, -10049, 9383, + 16304, -12296, 16446, 18239, -1296, -19725, -32076, 11782, -17941, + 29643, -8577, 7893, -21464, -19646, -15130, -2391, 30608, -23970, + -16608, 19616, -7941, 26533, -19129, 27690, 7597, -11459, 10615, + -9430, 11591, 7814, 12697, 32114, -3761, -9604, 19813, 20353, + 17456, -16267, -19555, 598, -29942, 4538, 835, 15546, 3970, + -27685, 1488, 8311, -12442, 31352, -17631, 1806, -5342, 9790, + 29068, 16507, -29051, 22131, 6759, 15510, -14941, 28710, 1160, + -31327, 24985, 11261, -10623, -27727, 21502, 18731, -16186, -4127, + -18832, 12050, -14501, 7929, 29563, -31064, 5913, 5322, -16405, + 2844, 29439, 5876, -9522, -18586, -9874, 23844, 30362, -21442, + 9560, 17671, -27989, 3350, 787, -13857, 1657, -21224, -7374, + -9190, 2464, 25555, -3529, -28772, 16588, -15739, 23475, 13666, + 5764, 30980, 13633, -7401, -30317, 28847, 7682, -11808, -8796, + 14864, -24162, -19194, 689, -1311, -31332, -16319, 1025, 10971, + -23016, -2648, -21900, -12543, -25921, 28254, 28521, -16160, 12380, + -12882, -30332, -16630, 23439, 7742, 17182, 17494, 5920, 13642, + 7382, -18166, 21422, -30274, -28190, 13283, -20316, -9939, 10672, + 21454, 6080, -17374, -29735, -25912, -10170, 3808, 10639, -26985, + -10865, 25636, 17261, -26851, -8253, -3304, 18282, -2202, -31368, + -22243, 13882, 12069, -11242, -7729, -10226, 1761, -27298, -4800, + -17737, -22805, -3528, 65, 10770, 8908, -23751, 26934, 21921, + -27010, -21944, 8889, -1035, 23224, -9488, -5823, -994, -20206, + 7655, -16251, -22820, -27740, 15822, 23078, 13803, -8099, 2931, + 9217, -21126, -14203, 25492, -12831, 7947, 17463, -12979, 29003, + 31612, 26554, 8241, -20175}; // q = 64513 + +/************************************************* + * Name: ntt + * + * Description: Forward NTT, in-place. No modular reduction is performed after + * additions or subtractions. Output vector is in bitreversed + *order. + * + * Arguments: - uint32_t p[N]: input/output coefficient array + **************************************************/ +void ntt(int32_t a[N]) { + unsigned int len, start, j, k; + int32_t zeta, t; + + k = 0; + for (len = 128; len > 0; len >>= 1) { + for (start = 0; start < N; start = j + len) { + zeta = zetas[++k]; + for (j = start; j < start + len; ++j) { + t = montgomery_reduce((int64_t)zeta * a[j + len]); + a[j + len] = a[j] - t; + a[j] = a[j] + t; + } + } + } +} + +/************************************************* + * Name: invntt_tomont + * + * Description: Inverse NTT and multiplication by Montgomery factor 2^32. + * In-place. No modular reductions after additions or + * subtractions; input coefficients need to be smaller than + * Q in absolute value. Output coefficient are smaller than Q in + * absolute value. + * + * Arguments: - uint32_t p[N]: input/output coefficient array + **************************************************/ +void invntt_tomont(int32_t a[N]) { + unsigned int start, len, j, k; + int32_t t, zeta; + const int32_t f = -29720; // mont^2/256 + + k = 256; + for (len = 1; len < N; len <<= 1) { + for (start = 0; start < N; start = j + len) { + zeta = -zetas[--k]; + for (j = start; j < start + len; ++j) { + t = a[j]; + a[j] = t + a[j + len]; + a[j + len] = t - a[j + len]; + a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); + } + } + } + + for (j = 0; j < N; ++j) { + a[j] = montgomery_reduce((int64_t)f * a[j]); + } +} diff --git a/crypto_sign/haetae2/clean/ntt.h b/crypto_sign/haetae2/clean/ntt.h new file mode 100644 index 00000000..c7732a34 --- /dev/null +++ b/crypto_sign/haetae2/clean/ntt.h @@ -0,0 +1,13 @@ +#ifndef NTT_H +#define NTT_H + +#include "params.h" +#include + +#define ntt HAETAE_NAMESPACE(ntt) +void ntt(int32_t a[N]); + +#define invntt_tomont HAETAE_NAMESPACE(invntt_tomont) +void invntt_tomont(int32_t a[N]); + +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/packing.c b/crypto_sign/haetae2/clean/packing.c new file mode 100644 index 00000000..261d3628 --- /dev/null +++ b/crypto_sign/haetae2/clean/packing.c @@ -0,0 +1,272 @@ +#include "packing.h" +#include "encoding.h" +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: pack_pk + * + * Description: Bit-pack public key pk = (seed, b). + * + * Arguments: - uint8_t pk[]: output byte array + * - const polyveck *b: polynomial vector of length K containg b + * - const uint8_t seed[]: seed for A' + **************************************************/ +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, + const uint8_t seed[SEEDBYTES]) { + unsigned int i; + + memcpy(pk, seed, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_pack(pk + i * POLYQ_PACKEDBYTES, &b->vec[i]); + } +} + +/************************************************* + * Name: unpack_pk + * + * Description: Unpack public key pk = (seed, b). + * + * Arguments: - uint8_t seed[]: seed for A' + * - polyveck *b: polynomial vector of length K containg b + * - const uint8_t pk[]: output byte array + **************************************************/ +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) { + unsigned int i; + + memcpy(seed, pk, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_unpack(&b->vec[i], pk + i * POLYQ_PACKEDBYTES); + } +} + +/************************************************* + * Name: pack_sk + * + * Description: Bit-pack secret key sk = (pk, s). + * + * Arguments: - uint8_t sk[]: output byte array + * - const uint8_t pk[PUBLICKEYBYTES]: packed pk + * - const polyvecl *s0: polyvecl pointer containing s0 (encoding + *starting at offset 1) + * - const polyveck *s1: polyveck pointer containing s1 + **************************************************/ +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, + const polyveck *s1, const uint8_t key[SEEDBYTES]) { + unsigned int i; + memcpy(sk, pk, CRYPTO_PUBLICKEYBYTES); + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s0->vec[i]); + + sk += (L - 1) * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_pack(sk + i * POLY2ETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(sk, key, SEEDBYTES); +} + +/************************************************* + * Name: unpack_sk + * + * Description: Unpack secret key sk = (A, s). + * + * Arguments: - polyvecl A[K]: output polyvecl array for A + * - polyvecl s0: output polyvecl pointer for s0 + * - polyveck s1: output polyveck pointer for s1 + * - const uint8_t sk[]: byte array containing bit-packed sk + **************************************************/ +void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { + unsigned int i; + uint8_t rhoprime[SEEDBYTES]; + polyveck b1; +#if D > 0 + polyveck a; +#endif + + unpack_pk(&b1, rhoprime, sk); + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_unpack(&s0->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += M * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_unpack(&s1->vec[i], sk + i * POLY2ETA_PACKEDBYTES); + + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_unpack(&s1->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(key, sk, SEEDBYTES); + + // A' = PRG(rhoprime) + polymatkl_expand(A, rhoprime); + polymatkl_double(A); +#if D > 0 + polyveck_expand(&a, rhoprime); +#endif + +#if D == 1 + // first column of A = 2(a-b1*2^d) + polyveck_double(&b1); + polyveck_sub(&b1, &a, &b1); + polyveck_double(&b1); + polyveck_ntt(&b1); +#elif D == 0 +#else +#error "Not yet implemented." +#endif + // append b into A + for (i = 0; i < K; ++i) { + A[i].vec[0] = b1.vec[i]; + } +} + +/************************************************* + * Name: pack_sig + * + * Description: Bit-pack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - uint8_t sig[]: output byte array + * - const uint8_t c_seed[]: pointer to seed of challenge + * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of + *length L + * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of + *length L + * - const polyveck *h: pointer t vector h of length K + * Returns 1 in case the signature size is above the threshold; otherwise 0. + **************************************************/ +int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], + const polyvecl *lowbits_z1, const polyvecl *highbits_z1, + const polyveck *h) { + + uint8_t encoded_h[N * K]; + uint8_t encoded_hb_z1[N * L]; + uint16_t size_enc_h, size_enc_hb_z1; + uint8_t offset_enc_h, offset_enc_hb_z1; + + // init/padding with zeros: + memset(sig, 0, CRYPTO_BYTES); + + memcpy(sig, c_seed, SEEDBYTES); + sig += SEEDBYTES; + + for (int i = 0; i < L; ++i) + poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); + sig += L * N; + + size_enc_hb_z1 = + encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]); + size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]); + + if(size_enc_h == 0 || size_enc_hb_z1 == 0) { + return 1; // encoding failed + } + + // The size of the encoded h and HB(z1) does not always fit in one byte, + // thus we output a one byte offset to a fixed baseline + if(size_enc_h < BASE_ENC_H || size_enc_hb_z1 < BASE_ENC_HB_Z1 || + size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { + return 1; // encoding size offset out of range + } + + offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; + offset_enc_h = size_enc_h - BASE_ENC_H; + + if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > + CRYPTO_BYTES) { + return 1; // signature too big + } + + sig[0] = offset_enc_hb_z1; + sig[1] = offset_enc_h; + sig += 2; + + memcpy(sig, encoded_hb_z1, size_enc_hb_z1); + sig += size_enc_hb_z1; + + memcpy(sig, encoded_h, size_enc_h); + sig += size_enc_h; + + return 0; +} + +/************************************************* + * Name: unpack_sig + * + * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - uint8_t c_seed[]: pointer to output seed of challenge + * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) + * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) + * - polyveck *h: pointer to output vector h + * - const uint8_t sig[]: byte array containing + * bit-packed signature + * + * Returns 1 in case of malformed signature; otherwise 0. + **************************************************/ +int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, + polyvecl *highbits_z1, polyveck *h, + const uint8_t sig[CRYPTO_BYTES]) { + + uint16_t size_enc_hb_z1, size_enc_h; + + memcpy(c_seed, sig, SEEDBYTES); + sig += SEEDBYTES; + + for (int i = 0; i < L; ++i) + poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); + sig += L * N; + + size_enc_hb_z1 = (uint16_t)sig[0] + BASE_ENC_HB_Z1; + size_enc_h = (uint16_t)sig[1] + BASE_ENC_H; + sig += 2; + + if(CRYPTO_BYTES < (2 + L*N + SEEDBYTES + size_enc_h + size_enc_hb_z1)) + return 1; // invalid size_enc_h and/or size_enc_hb_z1 + + if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { + return 1; // decoding failed + } + + sig += size_enc_hb_z1; + + if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { + return 1; // decoding failed + } + + sig += size_enc_h; + + for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) + if(sig[i] != 0) return 1; // verify zero padding + + return 0; +} diff --git a/crypto_sign/haetae2/clean/packing.h b/crypto_sign/haetae2/clean/packing.h new file mode 100644 index 00000000..1188d089 --- /dev/null +++ b/crypto_sign/haetae2/clean/packing.h @@ -0,0 +1,25 @@ +// clang-format off +#ifndef HAETAE_PACKING_H +#define HAETAE_PACKING_H + +#include "params.h" +#include "polyvec.h" +#include + +#define pack_pk HAETAE_NAMESPACE(pack_pk) +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, const uint8_t seed[SEEDBYTES]); +#define unpack_pk HAETAE_NAMESPACE(unpack_pk) +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define pack_sk HAETAE_NAMESPACE(pack_sk) +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); +#define unpack_sk HAETAE_NAMESPACE(unpack_sk) +void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +#define pack_sig HAETAE_NAMESPACE(pack_sig) +int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); +#define unpack_sig HAETAE_NAMESPACE(unpack_sig) +int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + +#endif //HAETAE_PACKING_H +// clang-format on diff --git a/crypto_sign/haetae2/clean/params.h b/crypto_sign/haetae2/clean/params.h new file mode 100644 index 00000000..c73e63f2 --- /dev/null +++ b/crypto_sign/haetae2/clean/params.h @@ -0,0 +1,116 @@ +// clang-format off +#ifndef HAETAE_PARAMS_H +#define HAETAE_PARAMS_H + +#include "config.h" + +#define SEEDBYTES 32 +#define CRHBYTES 64 +#define N 256 +#define ROOT_OF_UNITY 3 + +#define Q 64513 +#define DQ (Q << 1)// 2Q + +#if HAETAE_MODE == 2 +#define K 2 +#define L 4 +#define ETA 1 +#define TAU 58 +#define B0 9846.02 +#define B1 9838.99 +#define B2 12777.52 +#define GAMMA 48.858 +#define LN 8192 // Large N +#define SQNM 39.191835884530846 // \sqrt(n * m) +#define D 1 +#define CRYPTO_BYTES 1474 + +#define BASE_ENC_HB_Z1 132 +#define BASE_ENC_H 7 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 3 +#define K 3 +#define L 6 +#define ETA 1 +#define TAU 80 +#define B0 18314.98 +#define B1 18307.70 +#define B2 21906.65 +#define GAMMA 57.707 +#define LN 8192 // Large N +#define SQNM 48.0 +#define D 1 +#define CRYPTO_BYTES 2349 + +#define BASE_ENC_HB_Z1 376 +#define BASE_ENC_H 127 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 5 +#define K 4 +#define L 7 +#define ETA 1 +#define TAU 128 +#define B0 22343.66 +#define B1 22334.95 +#define B2 24441.49 +#define GAMMA 55.13 +#define LN 8192 // Large N +#define SQNM 53.0659966456864 +#define D 0 +#define CRYPTO_BYTES 2948 + +#define BASE_ENC_HB_Z1 501 +#define BASE_ENC_H 358 + +#define ALPHA_HINT 256 +#define LOG_ALPHA_HINT 8 + +#define POLYB1_PACKEDBYTES 512 // 16bits * N / 8bits +#define POLYQ_PACKEDBYTES 512 // 16bits * N / 8bits + +#endif // HAETAE_MODE + +#define HALF_ALPHA_HINT (ALPHA_HINT >> 1) // ALPHA / 2 + +#define B0SQ ((uint64_t)(B0*B0)) +#define B1SQ ((uint64_t)(B1*B1)) +#define B2SQ ((uint64_t)(B2*B2)) + +#define M (L-1) + +#if ETA == 1 +#define POLYETA_PACKEDBYTES 64 +#define POLY2ETA_PACKEDBYTES 96 +#elif ETA == 2 +#define POLYETA_PACKEDBYTES 96 +#endif + +#define POLYC_PACKEDBYTES 32 // 1bit * N / 8bits +#define POLY_HIGHBITS_PACKEDBYTES (N * 9 / 8) +#define POLYVECK_HIGHBITS_PACKEDBYTES (POLY_HIGHBITS_PACKEDBYTES * K) +#define POLYVECK_BYTES (K * N * sizeof(int32_t)) +#define POLYVECL_BYTES (L * N * sizeof(int32_t)) + +#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLYQ_PACKEDBYTES) // seed + b +#if D == 1 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + M * POLYETA_PACKEDBYTES + K * POLY2ETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#elif D == 0 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + (M + K) * POLYETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#else +#error +#endif +#endif +// clang-format on diff --git a/crypto_sign/haetae2/clean/poly.c b/crypto_sign/haetae2/clean/poly.c new file mode 100644 index 00000000..411b9d3e --- /dev/null +++ b/crypto_sign/haetae2/clean/poly.c @@ -0,0 +1,653 @@ +#include "poly.h" +#include "decompose.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: poly_add + * + * Description: Add polynomials. No modular reduction is performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +/************************************************* + * Name: poly_sub + * + * Description: Subtract polynomials. No modular reduction is + * performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial to be + * subtraced from first input polynomial + **************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +/************************************************* + * Name: poly_pointwise_montgomery + * + * Description: Pointwise multiplication of polynomials in NTT domain + * representation and multiplication of resulting polynomial + * by 2^{-32}. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial + **************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); +} + +/************************************************* + * Name: poly_reduce2q + * + * Description: Inplace reduction of all coefficients of polynomial to 2q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_reduce2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = reduce32_2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze2q + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ 2Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze(a->coeffs[i]); +} + +/************************************************* + * Name: poly_highbits + * + * Description: Compute HighBits of polynomial + * + * Arguments: - poly *a2: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_highbits(poly *a2, const poly *a) { + unsigned int i; + int32_t a1tmp; + + for (i = 0; i < N; ++i) + decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]); +} + +/************************************************* + * Name: poly_lowbits + * + * Description: Compute LowBits of polynomial + * + * Arguments: - poly *a1: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lowbits(poly *a1, const poly *a) { + unsigned int i = 0; + int32_t a2tmp = 0; + + for (i = 0; i < N; ++i) + decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]); +} + +/************************************************* + * Name: poly_compose + * + * Description: Compose HighBits and LowBits to recreate the polynomial + * + * Arguments: - poly *a3: pointer to output polynomial + * - const poly *ha: pointer to HighBits polynomial + * - const poly *la: pointer to HighBits polynomial + **************************************************/ +void poly_compose(poly *a, const poly *ha, const poly *la) { + unsigned int i = 0; + + for (i = 0; i < N; ++i) + a->coeffs[i] = (ha->coeffs[i] << 8) + la->coeffs[i]; +} + +/************************************************* + * Name: poly_lsb + * + * Description: Compute least significant bits of polynomial + * + * Arguments: - poly *a0: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lsb(poly *a0, const poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a0->coeffs[i] = a->coeffs[i] & 1; +} + +/************************************************* + * Name: poly_uniform + * + * Description: Sample polynomial with uniformly random coefficients + * in [0,Q-1] by performing rejection sampling on the + * output stream of SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#define POLY_UNIFORM_NBLOCKS \ + ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES) +// N * 2(random bytes for [0, Q - 1]) + +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform(a->coeffs, N, buf, buflen); + + while (ctr < N) { + off = buflen % 2; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* + * Name: poly_uniform_eta + * + * Description: Sample polynomial with uniformly random coefficients + * in [-ETA,ETA] by performing rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#if ETA == 1 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#elif ETA == 2 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#endif + +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int ctr; + unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); + + ctr = rej_eta(a->coeffs, N, buf, buflen); + + while (ctr < N) { + stream256_squeezeblocks(buf, 1, &state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); + } +} + +uint8_t hammingWeight_8(uint8_t x) { + x = (x & 0x55) + (x >> 1 & 0x55); + x = (x & 0x33) + (x >> 2 & 0x33); + x = (x & 0x0F) + (x >> 4 & 0x0F); + + return x; +} + +/************************************************* + * Name: poly_challenge + * + * Description: Implementation of challenge. Samples polynomial with TAU 1 + * coefficients using the output stream of SHAKE256(seed). + * + * Arguments: - poly *c: pointer to output polynomial + * - const uint8_t seed[]: byte array containing seed of length + * SEEDBYTES + **************************************************/ +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { +#if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) + unsigned int i, b, pos = 0; + uint8_t buf[XOF256_BLOCKBYTES]; + xof256_state state; + + xof256_absorbe_once(&state, seed, SEEDBYTES); + xof256_squeezeblocks(buf, 1, &state); + + for (i = 0; i < N; ++i) + c->coeffs[i] = 0; + for (i = N - TAU; i < N; ++i) { + do { + if (pos >= XOF256_BLOCKBYTES) { + xof256_squeezeblocks(buf, 1, &state); + pos = 0; + } + + b = buf[pos++]; + } while (b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1; + } +#elif HAETAE_MODE == 5 + unsigned int i, hwt = 0, cond = 0; + uint8_t mask = 0, w0 = 0; + uint8_t buf[32] = {0}; + xof256_state state; + + xof256_absorbe_once(&state, seed, SEEDBYTES); + xof256_squeeze(buf, 32, &state); + + for (i = 0; i < 32; ++i) + hwt += hammingWeight_8(buf[i]); + + cond = (128 - hwt); + mask = 0xff & (cond >> 8); + w0 = -(buf[0] & 1); + mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0 + for (i = 0; i < 32; ++i) { + buf[i] ^= mask; + c->coeffs[8 * i] = buf[i] & 1; + c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1; + c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1; + c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1; + c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1; + c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1; + c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1; + c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1; + } +#endif +} + +void poly_decomposed_pack(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + buf[i] = a->coeffs[i]; + } +} + +void poly_decomposed_unpack(poly *a, const uint8_t *buf) { + unsigned int i; + for (i = 0; i < N; i++) { + a->coeffs[i] = (int8_t)buf[i]; + } +} + +void poly_pack_highbits(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N / 8; i++) { + buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff; + + buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01; + buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff; + + buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03; + buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff; + + buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07; + buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff; + + buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f; + buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff; + + buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f; + buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff; + + buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f; + buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff; + + buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f; + buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff; + + buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff; + } +} + +void poly_pack_lsb(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + if ((i % 8) == 0) { + buf[i / 8] = 0; + } + buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8); + } +} + +/************************************************* + * Name: polyq_pack + * + * Description: Bit-pack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYQ_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyq_pack(uint8_t *r, const poly *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r[b_idx] = (a->coeffs[d_idx] & 0xff); + r[b_idx + 1] = ((a->coeffs[d_idx] >> 8) & 0x7f) | + ((a->coeffs[d_idx + 1] & 0x1) << 7); + r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff); + r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) | + ((a->coeffs[d_idx + 2] & 0x3) << 6); + r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff); + r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) | + ((a->coeffs[d_idx + 3] & 0x7) << 5); + r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff); + r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) | + ((a->coeffs[d_idx + 4] & 0xf) << 4); + r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff); + r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) | + ((a->coeffs[d_idx + 5] & 0x1f) << 3); + r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff); + r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) | + ((a->coeffs[d_idx + 6] & 0x3f) << 2); + r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff); + r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) | + (a->coeffs[d_idx + 7] & 0x7f) << 1; + r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff); + } +#else + for (i = 0; i < N / 1; ++i) { + r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0; + r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8; + } +#endif +} + +/************************************************* + * Name: polyq_unpack + * + * Description: Unpack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyq_unpack(poly *r, const uint8_t *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8); + r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) | + ((a[b_idx + 2] & 0xff) << 1) | + ((a[b_idx + 3] & 0x3f) << 9); + r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) | + ((a[b_idx + 4] & 0xff) << 2) | + ((a[b_idx + 5] & 0x1f) << 10); + r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) | + ((a[b_idx + 6] & 0xff) << 3) | + ((a[b_idx + 7] & 0xf) << 11); + r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) | + ((a[b_idx + 8] & 0xff) << 4) | + ((a[b_idx + 9] & 0x7) << 12); + r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) | + ((a[b_idx + 10] & 0xff) << 5) | + ((a[b_idx + 11] & 0x3) << 13); + r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) | + ((a[b_idx + 12] & 0xff) << 6) | + ((a[b_idx + 13] & 0x1) << 14); + r->coeffs[d_idx + 7] = + ((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7); + } + +#else + for (i = 0; i < N / 1; ++i) { + r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0; + r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8; + r->coeffs[1 * i + 0] &= 0xffff; + } +#endif +} + +/************************************************* + * Name: polyeta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyeta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + t[0] = ETA - a->coeffs[4 * i + 0]; + t[1] = ETA - a->coeffs[4 * i + 1]; + t[2] = ETA - a->coeffs[4 * i + 2]; + t[3] = ETA - a->coeffs[4 * i + 3]; + r[i] = t[0] >> 0; + r[i] |= t[1] << 2; + r[i] |= t[2] << 4; + r[i] |= t[3] << 6; + } +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + t[0] = ETA - a->coeffs[8 * i + 0]; + t[1] = ETA - a->coeffs[8 * i + 1]; + t[2] = ETA - a->coeffs[8 * i + 2]; + t[3] = ETA - a->coeffs[8 * i + 3]; + t[4] = ETA - a->coeffs[8 * i + 4]; + t[5] = ETA - a->coeffs[8 * i + 5]; + t[6] = ETA - a->coeffs[8 * i + 6]; + t[7] = ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#endif +} + +/************************************************* + * Name: polyeta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyeta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + r->coeffs[4 * i + 0] = a[i] >> 0; + r->coeffs[4 * i + 0] &= 0x3; + + r->coeffs[4 * i + 1] = a[i] >> 2; + r->coeffs[4 * i + 1] &= 0x3; + + r->coeffs[4 * i + 2] = a[i] >> 4; + r->coeffs[4 * i + 2] &= 0x3; + + r->coeffs[4 * i + 3] = a[i] >> 6; + r->coeffs[4 * i + 3] &= 0x3; + + r->coeffs[4 * i + 0] = ETA - r->coeffs[4 * i + 0]; + r->coeffs[4 * i + 1] = ETA - r->coeffs[4 * i + 1]; + r->coeffs[4 * i + 2] = ETA - r->coeffs[4 * i + 2]; + r->coeffs[4 * i + 3] = ETA - r->coeffs[4 * i + 3]; + } + +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7]; + } +#endif +} + +/************************************************* + * Name: poly2eta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly2eta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + t[0] = 2 * ETA - a->coeffs[8 * i + 0]; + t[1] = 2 * ETA - a->coeffs[8 * i + 1]; + t[2] = 2 * ETA - a->coeffs[8 * i + 2]; + t[3] = 2 * ETA - a->coeffs[8 * i + 3]; + t[4] = 2 * ETA - a->coeffs[8 * i + 4]; + t[5] = 2 * ETA - a->coeffs[8 * i + 5]; + t[6] = 2 * ETA - a->coeffs[8 * i + 6]; + t[7] = 2 * ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +/************************************************* + * Name: poly2eta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void poly2eta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = 2 * ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = 2 * ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = 2 * ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = 2 * ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = 2 * ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = 2 * ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = 2 * ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = 2 * ETA - r->coeffs[8 * i + 7]; + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +void poly_fromcrt(poly *w, const poly *u, const poly *v) { + unsigned int i; + int32_t xq, x2; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + x2 = v->coeffs[i]; + w->coeffs[i] = xq + (Q & -((xq ^ x2) & 1)); + } +} + +void poly_fromcrt0(poly *w, const poly *u) { + unsigned int i; + int32_t xq; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + w->coeffs[i] = xq + (Q & -(xq & 1)); + } +} + +void poly_ntt(poly *a) { ntt(&a->coeffs[0]); } + +void poly_invntt_tomont(poly *a) { invntt_tomont(&a->coeffs[0]); } diff --git a/crypto_sign/haetae2/clean/poly.h b/crypto_sign/haetae2/clean/poly.h new file mode 100644 index 00000000..e264bb55 --- /dev/null +++ b/crypto_sign/haetae2/clean/poly.h @@ -0,0 +1,80 @@ +// clang-format off +#ifndef HAETAE_POLY_H +#define HAETAE_POLY_H + +#include "params.h" +#include "reduce.h" +#include "sampler.h" +#include + +typedef struct { + int32_t coeffs[N]; +} poly; + +#define poly_add HAETAE_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub HAETAE_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); + +#define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) +void poly_reduce2q(poly *a); +#define poly_freeze2q HAETAE_NAMESPACE(poly_freeze2q) +void poly_freeze2q(poly *a); +#define poly_freeze HAETAE_NAMESPACE(poly_freeze) +void poly_freeze(poly *a); + +#define poly_highbits HAETAE_NAMESPACE(poly_highbits) +void poly_highbits(poly *a2, const poly *a); +#define poly_lowbits HAETAE_NAMESPACE(poly_lowbits) +void poly_lowbits(poly *a1, const poly *a); +#define poly_compose HAETAE_NAMESPACE(poly_compose) +void poly_compose(poly *a, const poly *ha, const poly *la); +#define poly_lsb HAETAE_NAMESPACE(poly_lsb) +void poly_lsb(poly *a0, const poly *a); + +#define poly_uniform HAETAE_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define poly_challenge HAETAE_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); + +#define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) +void poly_decomposed_pack(uint8_t *buf, const poly *a); +#define poly_decomposed_unpack HAETAE_NAMESPACE(poly_decomposed_unpack) +void poly_decomposed_unpack(poly *a, const uint8_t *buf); + +#define poly_pack_highbits HAETAE_NAMESPACE(poly_pack_highbits) +void poly_pack_highbits(uint8_t *buf, const poly *a); + +#define poly_pack_lsb HAETAE_NAMESPACE(poly_pack_lsb) +void poly_pack_lsb(uint8_t *buf, const poly *a); + +#define polyq_pack HAETAE_NAMESPACE(polyq_pack) +void polyq_pack(uint8_t *r, const poly *a); +#define polyq_unpack HAETAE_NAMESPACE(polyq_unpack) +void polyq_unpack(poly *r, const uint8_t *a); + +#define polyeta_pack HAETAE_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t *r, const poly *a); +#define polyeta_unpack HAETAE_NAMESPACE(polyeta_unpack) +void polyeta_unpack(poly *r, const uint8_t *a); +#define poly2eta_pack HAETAE_NAMESPACE(poly2eta_pack) +void poly2eta_pack(uint8_t *r, const poly *a); +#define poly2eta_unpack HAETAE_NAMESPACE(poly2eta_unpack) +void poly2eta_unpack(poly *r, const uint8_t *a); + +#define poly_fromcrt HAETAE_NAMESPACE(poly_fromcrt) +void poly_fromcrt(poly *w, const poly *u, const poly *v); +#define poly_fromcrt0 HAETAE_NAMESPACE(poly_fromcrt0) +void poly_fromcrt0(poly *w, const poly *u); + +#define poly_ntt HAETAE_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); +#define poly_invntt_tomont HAETAE_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/clean/polyfix.c b/crypto_sign/haetae2/clean/polyfix.c new file mode 100644 index 00000000..65612e90 --- /dev/null +++ b/crypto_sign/haetae2/clean/polyfix.c @@ -0,0 +1,281 @@ +#include "polyfix.h" +#include "decompose.h" +#include "math.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: polyfix_add + * + * Description: Add double polynomial and integer polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output double polynomial + * - const polyfix *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void polyfix_add(polyfix *c, const polyfix *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + LN * b->coeffs[i]; +} + +/************************************************* + * Name: polyfixfix_sub + * + * Description: Subtract fixed polynomial and fixed polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output fixed polynomial + * - const polyfix *a: pointer to first summand + * - const polyfix *b: pointer to second summand + **************************************************/ +void polyfixfix_sub(polyfix *c, const polyfix *a, const polyfix *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +int32_t fix_round(int32_t num) { + num += (num >> 31) & (-LN + 1); + num += + LN / + 2; // total \floor(LN / 2) if positive, -\floor(LN / 2) + 1 if negative + return num / LN; +} + +/************************************************* + * Name: polyfix_round + * + * Description: rounds a fixed polynomial to integer polynomial + * + * Arguments: - poly *a: output integer polynomial + * - poly *b: input fixed polynomial + **************************************************/ +void polyfix_round(poly *a, const polyfix *b) { + unsigned i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = fix_round(b->coeffs[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length K **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixveck_add + * + * Description: Add vector to a vector of double polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixveck_sub + * + * Description: subtract vector to a vector of fixed polynomials of length k. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyfixveck *u: pointer to first summand + * - const polyfixveck *v: pointer to second summand + **************************************************/ +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixveck_double + * + * Description: Double vector of polynomials of length K. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixveck_double(polyfixveck *b, const polyfixveck *a) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; +} + +/************************************************* + * Name: polyfixveck_round + * + * Description: rounds a fixed polynomial vector of length K + * + * Arguments: - polyveck *a: output integer polynomial vector + * - polyfixveck *b: input fixed polynomial vector + **************************************************/ +void polyfixveck_round(polyveck *a, const polyfixveck *b) { + unsigned i; + + for (i = 0; i < K; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length L **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixvecl_add + * + * Description: Add vector to a vector of double polynomials of length L. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyvecl *v: pointer to second summand + **************************************************/ +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixvecl_sub + * + * Description: subtract vector to a vector of fixed polynomials of length l. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyfixvecl *v: pointer to second summand + **************************************************/ +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} +/************************************************* + * Name: polyfixvecl_double + * + * Description: Double vector of polynomials of length L. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) { + unsigned int i, j; + + for (i = 0; i < L; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; +} + +/************************************************* + * Name: polyfixvecl_round + * + * Description: rounds a fixed polynomial vector of length L + * + * Arguments: - polyvecl *a: output integer polynomial vector + * - polyfixvecl *b: input fixed polynomial vector + **************************************************/ +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) { + unsigned i; + + for (i = 0; i < L; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + +/************************************************* + * Name: polyfixveclk_norm2 + * + * Description: Calculates L2 norm of a fixed point polynomial vector with + *length L + K The result is L2 norm * LN similar to the way polynomial is + *usually stored + * + * Arguments: - polyfixvecl *a: polynomial vector with length L to calculate + * norm + * - polyfixveck *a: polynomial vector with length K to calculate + * norm + **************************************************/ +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + for (j = 0; j < N; ++j) + ret += (int64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; + } + + for (i = 0; i < K; ++i) { + for (j = 0; j < N; ++j) + ret += (int64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; + } + + return ret; +} + +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, + const uint8_t seed[CRHBYTES], + const uint16_t nonce) { + uint16_t ni = nonce; + uint64_t samples[N * (L + K)]; + fp96_76 sqsum, invsqrt; + unsigned int i, j; + uint8_t signs[N * (L + K) / 8]; + + do { + sqsum.limb48[0] = 0; + sqsum.limb48[1] = 0; + + sample_gauss_N(&samples[0], &signs[0], &sqsum, seed, ni++, N + 1); + sample_gauss_N(&samples[N], &signs[N / 8], &sqsum, seed, ni++, N + 1); + + for (i = 2; i < L + K; i++) + sample_gauss_N(&samples[N * i], &signs[N / 8 * i], &sqsum, seed, + ni++, N); + + // divide sqsum by 2 and approximate inverse square root + sqsum.limb48[0] += 1; // rounding + sqsum.limb48[0] >>= 1; + sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; + sqsum.limb48[1] >>= 1; + sqsum.limb48[1] += sqsum.limb48[0] >> 48; + sqsum.limb48[0] &= (1ULL << 48) - 1; + fixpoint_newton_invsqrt(&invsqrt, &sqsum); + fixpoint_mul_high(&sqsum, &invsqrt, + (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); + + for (i = 0; i < L; i++) { + for (j = 0; j < N; j++) + y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + for (i = L; i < K + L; i++) { + for (j = 0; j < N; j++) + y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); + + return ni; +} diff --git a/crypto_sign/haetae2/clean/polyfix.h b/crypto_sign/haetae2/clean/polyfix.h new file mode 100644 index 00000000..9a4945c2 --- /dev/null +++ b/crypto_sign/haetae2/clean/polyfix.h @@ -0,0 +1,61 @@ +// clang-format off +#ifndef HAETAE_POLYFIX_H +#define HAETAE_POLYFIX_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include "reduce.h" +#include + +typedef struct { + int32_t coeffs[N]; +} polyfix; + +#define polyfix_norm2 HAETAE_NAMESPACE(polyfix_norm2) +double polyfix_norm2(const polyfix *a); + +#define polyfix_round HAETAE_NAMESPACE(polyfix_round) +void polyfix_round(poly *a, const polyfix *b); + +#define polyfix_add HAETAE_NAMESPACE(polyfix_add) +void polyfix_add(polyfix *c, const polyfix *a, const poly *b); + +typedef struct { + polyfix vec[K]; +} polyfixveck; + +#define polyfixveck_add HAETAE_NAMESPACE(polyfixveck_add) +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v); +#define polyfixfixveck_sub HAETAE_NAMESPACE(polyfixfixveck_sub) +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v); +#define polyfixveck_double HAETAE_NAMESPACE(polyfixveck_double) +void polyfixveck_double(polyfixveck *b, const polyfixveck *a); + +#define polyfixveck_round HAETAE_NAMESPACE(polyfixveck_round) +void polyfixveck_round(polyveck *a, const polyfixveck *b); + +typedef struct { + polyfix vec[L]; +} polyfixvecl; + +#define polyfixvecl_add HAETAE_NAMESPACE(polyfixvecl_add) +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v); +#define polyfixfixvecl_sub HAETAE_NAMESPACE(polyfixfixvecl_sub) +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v); +#define polyfixvecl_double HAETAE_NAMESPACE(polyfixvecl_double) +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a); + +#define polyfixvecl_round HAETAE_NAMESPACE(polyfixvecl_round) +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); + +#define polyfixveclk_sqnorm2 HAETAE_NAMESPACE(polyfixveclk_sqnorm2) +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); + +#define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/clean/polymat.c b/crypto_sign/haetae2/clean/polymat.c new file mode 100644 index 00000000..c97f4dfb --- /dev/null +++ b/crypto_sign/haetae2/clean/polymat.c @@ -0,0 +1,73 @@ +#include "polymat.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); +} + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); +} + +// doubles k * m sub-matrix of k * l mat +void polymatkl_double(polyvecl mat[K]) { + unsigned int i, j, k; + for (i = 0; i < K; ++i) { + for (j = 1; j < L; ++j) { + for (k = 0; k < N; ++k) { + mat[i].vec[j].coeffs[k] *= 2; + } + } + } +} + +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} + +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} diff --git a/crypto_sign/haetae2/clean/polymat.h b/crypto_sign/haetae2/clean/polymat.h new file mode 100644 index 00000000..c12bc28a --- /dev/null +++ b/crypto_sign/haetae2/clean/polymat.h @@ -0,0 +1,28 @@ +#ifndef HAETAE_POLYMAT_H +#define HAETAE_POLYMAT_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +#define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkm_pointwise_montgomery) +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v); + +#define polymatkl_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkl_pointwise_montgomery) +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v); + +#define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) +void polymatkl_double(polyvecl mat[K]); + +#endif diff --git a/crypto_sign/haetae2/clean/polyvec.c b/crypto_sign/haetae2/clean/polyvec.c new file mode 100644 index 00000000..3b8b0336 --- /dev/null +++ b/crypto_sign/haetae2/clean/polyvec.c @@ -0,0 +1,543 @@ +#include + +#include "decompose.h" +#include "fft.h" +#include "math.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +/************************************************* + * Name: polyveck_add + * + * Description: Add vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_sub + * + * Description: Subtract vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first input vector + * - const polyveck *v: pointer to second input vector to be + * subtracted from first input vector + **************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_double + * + * Description: Double vector of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + **************************************************/ +void polyveck_double(polyveck *b) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] *= 2; +} + +/************************************************* + * Name: polyveck_reduce2q + * + * Description: Reduce coefficients to 2q + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_reduce2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_reduce2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze2q + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ 2Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_expand + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in Zq by rejection sampling on the + * output stream from SHAKE128(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + **************************************************/ +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]) { + unsigned int i, nonce = (K << 8) + M; + for (i = 0; i < K; ++i) + poly_uniform(&v->vec[i], seed, nonce++); +} + +/************************************************* + * Name: polyvecmk_uniform_eta + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in [-ETA,ETA] by rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i, n = nonce; + for (i = 0; i < M; i++) + poly_uniform_eta(&u->vec[i], seed, n++); + for (i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, n++); +} + +/************************************************* + * Name: polyveck_double_negate + * + * Description: multiply each coefficient with -2 + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_double_negate(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2); +} + +/************************************************* + * Name: polyveck_frommont + * + * Description: multiply each coefficient with MONT + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_frommont(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ); +} + +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, + const poly *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v); + } +} + +/************************************************* + * Name: polyveck_poly_fromcrt + * + * Description: recover polynomials from CRT domain, where all "mod q" + * polynomials are known and only the uppermost "mod 2" polynomial + * is non-zero + * + * Arguments: - polyveck *w: pointer to output vector of polynomials of + * length K + * - const polyveck *u: pointer to the input vector of polynomials + * of length K + * - const poly *v: pointer to the input polynomial ("mod 2") + **************************************************/ +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) { + unsigned int i; + + poly_fromcrt(&w->vec[0], &u->vec[0], v); + + for (i = 1; i < K; i++) { + poly_fromcrt0(&w->vec[i], &u->vec[i]); + } +} + +void polyveck_highbits_hint(polyveck *w, const polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pack_highbits(buf + i * POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]); + } +} + +void polyveck_cneg(polyveck *v, const uint8_t b) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] *= 1 - 2 * b; + } + } +} + +void polyveck_caddDQ2ALPHA(polyveck *h) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + h->vec[i].coeffs[j] += + (h->vec[i].coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_csubDQ2ALPHA(polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] -= + ~((v->vec[i].coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & + ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_mul_alpha(polyveck *v, const polyveck *u) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * ALPHA_HINT; + } + } +} + +void polyveck_div2(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] >>= 1; +} + +void polyveck_caddq(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]); +} + +void polyveck_decompose_vk(polyveck *v0, polyveck *v) { + for (int i = 0; i < K; i++) { + for (int j = 0; j < N; j++) { + v->vec[i].coeffs[j] = + decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_ntt(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_ntt(&x->vec[i]); + } +} + +void polyveck_invntt_tomont(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_invntt_tomont(&x->vec[i]); + } +} + +/************************************************* + * Name: polyveck_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length k + * + * Arguments: - polyveck *b: polynomial vector with length k to calculate + *norm + **************************************************/ +uint64_t polyveck_sqnorm2(const polyveck *b) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < K; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; + } + } + return ret; +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecl_highbits + * + * Description: Compute HighBits of a vector of polynomials + * + * Arguments: - polyvecl *v2: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_highbits(polyvecl *v2, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_highbits(&v2->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyvecl_lowbits + * + * Description: Compute LowBits of a vector of polynomials + * + * Arguments: - polyvecl *v1: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_lowbits(&v1->vec[i], &v->vec[i]); +} + +void polyvecl_cneg(polyvecl *v, const uint8_t b) { + unsigned int i, j; + for (i = 0; i < L; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] *= 1 - 2 * b; + } + } +} + +/************************************************* + * Name: polyvecl_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length l + * + * Arguments: - polyvecl *a: polynomial vector with length l to calculate + *norm + **************************************************/ +uint64_t polyvecl_sqnorm2(const polyvecl *a) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; + } + } + + return ret; +} + +/************************************************* + * Name: polyvecl_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecl *u: pointer to first input vector + * - const polyvecl *v: pointer to second input vector + **************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, + const polyvecl *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecl_ntt(polyvecl *x) { + unsigned int i; + for (i = 0; i < L; i++) { + poly_ntt(&x->vec[i]); + } +} + +/**************************************************************/ +/************ Vectors of polynomials of length M **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecm_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecm *u: pointer to first input vector + * - const polyvecm *v: pointer to second input vector + **************************************************/ +void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u, + const polyvecm *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < M; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecm_ntt(polyvecm *x) { + unsigned int i; + for (i = 0; i < M; i++) { + poly_ntt(&x->vec[i]); + } +} + +static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort +{ + int32_t a = *x; + int32_t b = *y; + int32_t ab = b ^ a; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} +static inline void minmaxmask(int32_t *x, int32_t *y, + int32_t *mask) // adapted from djbsort +{ + // If mask is -1, we perform the operation, else we do basically nothing. + // mask truth table: + // mask = 0 -> mask = 0, no swap is performed + // mask = -1, swap performed -> mask = 0 + // mask = -1, swap not performed -> mask = -1 + int32_t a = *x; + int32_t b = *y; + int32_t ab = (b ^ a) & *mask; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + *mask &= ~c; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} + +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2) { + int32_t res = 0; + complex_fp32_16 input[FFT_N] = {0}; + int32_t sum[N] = {0}, bestm[N / TAU + 1] = {0}, min = 0; + + for (size_t i = 0; i < M; ++i) { + fft_bitrev(input, &s1->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + for (size_t i = 0; i < K; ++i) { + fft_bitrev(input, &s2->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + // compute max m + for (size_t i = 0; i < N / TAU + 1; ++i) { + bestm[i] = sum[i]; + } + for (size_t i = N / TAU + 1; i < N; i++) { + int32_t mask = -1; + for (size_t j = 0; j < N / TAU + 1; j++) { + minmaxmask(&sum[i], &bestm[j], &mask); + } + } + // find minimum in bestm + min = bestm[0]; + for (size_t i = 1; i < N / TAU + 1; i++) { + int32_t tmp = bestm[i]; + minmax(&min, &tmp); + } + // multiply all but the minimum by N mod TAU + for (size_t i = 0; i < N / TAU + 1; i++) { + int32_t fac = ((min - bestm[i]) >> 31); // all-ones if bestm[i] != min (TODO: impl specific behaviour) + fac = + (fac & (TAU)) ^ + ((~fac) & (N % TAU)); // fac = TAU for all != min and N%TAU for min + bestm[i] += + 0x10200; // add 1 for the "1 poly" in S, and prepare rounding + bestm[i] >>= 10; // round off 10 bits + bestm[i] *= fac; + res += bestm[i]; + } + + return (res + (1 << 5)) >> 6; // return rounded, squared value +} diff --git a/crypto_sign/haetae2/clean/polyvec.h b/crypto_sign/haetae2/clean/polyvec.h new file mode 100644 index 00000000..8d48aa40 --- /dev/null +++ b/crypto_sign/haetae2/clean/polyvec.h @@ -0,0 +1,129 @@ +// clang-format off +#ifndef HAETAE_POLYVEC_H +#define HAETAE_POLYVEC_H + +#include "params.h" +#include "poly.h" +#include + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +#define polyveck_add HAETAE_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub HAETAE_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_double HAETAE_NAMESPACE(polyveck_double) +void polyveck_double(polyveck *b); + +#define polyveck_reduce2q HAETAE_NAMESPACE(polyveck_reduce2q) +void polyveck_reduce2q(polyveck *v); +#define polyveck_freeze2q HAETAE_NAMESPACE(polyveck_freeze2q) +void polyveck_freeze2q(polyveck *v); +#define polyveck_freeze HAETAE_NAMESPACE(polyveck_freeze) +void polyveck_freeze(polyveck *v); + +#define polyveck_uniform_eta HAETAE_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define polyveck_expand HAETAE_NAMESPACE(polyveck_expand) +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]); + +#define polyveck_ntt HAETAE_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *x); + +#define polyveck_invntt_tomont HAETAE_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *x); + +#define polyveck_double_negate HAETAE_NAMESPACE(polyveck_double_negate) +void polyveck_double_negate(polyveck *x); + +#define polyveck_frommont HAETAE_NAMESPACE(polyveck_frommont) +void polyveck_frommont(polyveck *x); + +#define polyveck_poly_pointwise_montgomery HAETAE_NAMESPACE(polyveck_poly_pointwise_montgomery) +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_poly_fromcrt HAETAE_NAMESPACE(polyveck_poly_fromcrt) +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_highbits_hint HAETAE_NAMESPACE(polyveck_highbits_hint) +void polyveck_highbits_hint(polyveck *w, const polyveck *v); + +#define polyveck_pack_highbits HAETAE_NAMESPACE(polyveck_pack_highbits) +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v); + +#define polyveck_cneg HAETAE_NAMESPACE(polyveck_cneg) +void polyveck_cneg(polyveck *v, const uint8_t b); + +#define polyveck_caddDQ2ALPHA HAETAE_NAMESPACE(polyveck_caddDQ2ALPHA) +void polyveck_caddDQ2ALPHA(polyveck *h); + +#define polyveck_csubDQ2ALPHA HAETAE_NAMESPACE(polyveck_csubDQ2ALPHA) +void polyveck_csubDQ2ALPHA(polyveck *v); + +#define polyveck_mul_alpha HAETAE_NAMESPACE(polyveck_mul_alpha) +void polyveck_mul_alpha(polyveck *v, const polyveck *u); + +#define polyveck_div2 HAETAE_NAMESPACE(polyveck_div2) +void polyveck_div2(polyveck *v); + +#define polyveck_caddq HAETAE_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); + +#define polyveck_decompose_vk HAETAE_NAMESPACE(polyveck_decompose_vk) +void polyveck_decompose_vk(polyveck *v0, polyveck *v); + +#define polyveck_sqnorm2 HAETAE_NAMESPACE(polyveck_sqnorm2) +uint64_t polyveck_sqnorm2(const polyveck *b); + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +#define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) +void polyvecl_cneg(polyvecl *v, const uint8_t b); + +#define polyvecl_sqnorm2 HAETAE_NAMESPACE(polyvecl_sqnorm2) +uint64_t polyvecl_sqnorm2(const polyvecl *a); + +#define polyvecl_ntt HAETAE_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *x); + +#define polyvecl_highbits HAETAE_NAMESPACE(polyvecl_highbits) +void polyvecl_highbits(polyvecl *v2, const polyvecl *v); +#define polyvecl_lowbits HAETAE_NAMESPACE(polyvecl_lowbits) +void polyvecl_lowbits(polyvecl *v2, const polyvecl *v); + +#define polyvecl_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + + +/* Vectors of polynomials of length M */ +typedef struct { + poly vec[M]; +} polyvecm; + +#define polyvecm_ntt HAETAE_NAMESPACE(polyvecm_ntt) +void polyvecm_ntt(polyvecm *x); + +#define polyvecmk_uniform_eta HAETAE_NAMESPACE(polyvecmk_uniform_eta) +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecm_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecm_pointwise_acc_montgomery) +void polyvecm_pointwise_acc_montgomery(poly *w, + const polyvecm *u, + const polyvecm *v); + +#define polyvecmk_sqsing_value HAETAE_NAMESPACE(polyvecmk_sqsing_value) +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2); + +#define polyvecmk_sing_value HAETAE_NAMESPACE(polyvecmk_sing_value) +int64_t polyvecmk_sing_value(const polyvecm *s1, const polyveck *s2); + +#endif +//clang-format on diff --git a/crypto_sign/haetae2/clean/rans_byte.h b/crypto_sign/haetae2/clean/rans_byte.h new file mode 100644 index 00000000..403ce20e --- /dev/null +++ b/crypto_sign/haetae2/clean/rans_byte.h @@ -0,0 +1,333 @@ +// Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014 +// +// Not intended to be "industrial strength"; just meant to illustrate the general +// idea. + +#ifndef RANS_BYTE_HEADER +#define RANS_BYTE_HEADER + +#include + +#ifdef assert +#define RansAssert assert +#else +#define RansAssert(x) +#endif + +// READ ME FIRST: +// +// This is designed like a typical arithmetic coder API, but there's three +// twists you absolutely should be aware of before you start hacking: +// +// 1. You need to encode data in *reverse* - last symbol first. rANS works +// like a stack: last in, first out. +// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give +// it a pointer to the *end* of your buffer (exclusive), and it will +// slowly move towards the beginning as more bytes are emitted. +// 3. Unlike basically any other entropy coder implementation you might +// have used, you can interleave data from multiple independent rANS +// encoders into the same bytestream without any extra signaling; +// you can also just write some bytes by yourself in the middle if +// you want to. This is in addition to the usual arithmetic encoder +// property of being able to switch models on the fly. Writing raw +// bytes can be useful when you have some data that you know is +// incompressible, and is cheaper than going through the rANS encode +// function. Using multiple rANS coders on the same byte stream wastes +// a few bytes compared to using just one, but execution of two +// independent encoders can happen in parallel on superscalar and +// Out-of-Order CPUs, so this can be *much* faster in tight decoding +// loops. +// +// This is why all the rANS functions take the write pointer as an +// argument instead of just storing it in some context struct. + +// -------------------------------------------------------------------------- + +// L ('l' in the paper) is the lower bound of our normalization interval. +// Between this and our byte-aligned emission, we use 31 (not 32!) bits. +// This is done intentionally because exact reciprocals for 31-bit uints +// fit in 32-bit uints: this permits some optimizations during encoding. +#define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval + +// State for a rANS encoder. Yep, that's all there is to it. +typedef uint32_t RansState; + +// Initialize a rANS encoder. +static inline void RansEncInit(RansState* r) +{ + *r = RANS_BYTE_L; +} + +// Renormalize the encoder. Internal function. +static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits) +{ + uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift. + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + return x; +} + +// Encodes a single symbol with range start "start" and frequency "freq". +// All frequencies are assumed to sum to "1 << scale_bits", and the +// resulting bytes get written to ptr (which is updated). +// +// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from +// beginning to end! Likewise, the output bytestream is written *backwards*: +// ptr starts pointing at the end of the output buffer and keeps decrementing. +static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + // renormalize + RansState x = RansEncRenorm(*r, pptr, freq, scale_bits); + + // x = C(s,x) + *r = ((x / freq) << scale_bits) + (x % freq) + start; +} + +// Flushes the rANS encoder. +static inline void RansEncFlush(RansState* r, uint8_t** pptr) +{ + uint32_t x = *r; + uint8_t* ptr = *pptr; + + ptr -= 4; + ptr[0] = (uint8_t) (x >> 0); + ptr[1] = (uint8_t) (x >> 8); + ptr[2] = (uint8_t) (x >> 16); + ptr[3] = (uint8_t) (x >> 24); + + *pptr = ptr; +} + +// Initializes a rANS decoder. +// Unlike the encoder, the decoder works forwards as you'd expect. +static inline int RansDecInit(RansState* r, uint8_t** pptr) +{ + uint32_t x; + uint8_t* ptr = *pptr; + + x = ptr[0] << 0; + x |= ptr[1] << 8; + x |= ptr[2] << 16; + x |= ptr[3] << 24; + if (x < RANS_BYTE_L || (RANS_BYTE_L << 8) <= x ) + return 1; // initial state out of range + + ptr += 4; + *pptr = ptr; + *r = x; + return 0; +} + +// Returns the current cumulative frequency (map it to a symbol yourself!) +static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits) +{ + return *r & ((1u << scale_bits) - 1); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", +// and the resulting bytes get written to ptr (which is updated). +static inline void RansDecAdvance(RansState* r, uint8_t** pptr, const uint8_t* end, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + x = freq * (x >> scale_bits) + (x & mask) - start; + + // renormalize + if (x < RANS_BYTE_L && *pptr < end) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L && ptr < end); + *pptr = ptr; + } + + *r = x; +} + +// -------------------------------------------------------------------------- + +// That's all you need for a full encoder; below here are some utility +// functions with extra convenience or optimizations. + +// Encoder symbol description +// This (admittedly odd) selection of parameters was chosen to make +// RansEncPutSymbol as cheap as possible. +typedef struct { + uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval + uint32_t rcp_freq; // Fixed-point reciprocal frequency + uint32_t bias; // Bias + uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq + uint16_t rcp_shift; // Reciprocal shift +} RansEncSymbol; + +// Decoder symbols are straightforward. +typedef struct { + uint16_t start; // Start of range. + uint16_t freq; // Symbol frequency. +} RansDecSymbol; + +// Initializes an encoder symbol to start "start" and frequency "freq" +static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + RansAssert(scale_bits <= 16); + RansAssert(start <= (1u << scale_bits)); + RansAssert(freq <= (1u << scale_bits) - start); + + // Say M := 1 << scale_bits. + // + // The original encoder does: + // x_new = (x/freq)*M + start + (x%freq) + // + // The fast encoder does (schematically): + // q = mul_hi(x, rcp_freq) >> rcp_shift (division) + // r = x - q*freq (remainder) + // x_new = q*M + bias + r (new x) + // plugging in r into x_new yields: + // x_new = bias + x + q*(M - freq) + // =: bias + x + q*cmpl_freq (*) + // + // and we can just precompute cmpl_freq. Now we just need to + // set up our parameters such that the original encoder and + // the fast encoder agree. + + s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; + s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq); + if (freq < 2) { + // freq=0 symbols are never valid to encode, so it doesn't matter what + // we set our values to. + // + // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately, + // our fixed-point reciprocal approximation can only multiply by values + // smaller than 1. + // + // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0. + // This gives: + // q = mul_hi(x, rcp_freq) >> rcp_shift + // = mul_hi(x, (1<<32) - 1)) >> 0 + // = floor(x - x/(2^32)) + // = x - 1 if 1 <= x < 2^32 + // and we know that x>0 (x=0 is never in a valid normalization interval). + // + // So we now need to choose the other parameters such that + // x_new = x*M + start + // plug it in: + // x*M + start (desired result) + // = bias + x + q*cmpl_freq (*) + // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq) + // = bias + 1 + (x - 1)*M + // = x*M + (bias + 1 - M) + // + // so we have start = bias + 1 - M, or equivalently + // bias = start + M - 1. + s->rcp_freq = ~0u; + s->rcp_shift = 0; + s->bias = start + (1 << scale_bits) - 1; + } else { + // Alverson, "Integer Division using reciprocals" + // shift=ceil(log2(freq)) + uint32_t shift = 0; + while (freq > (1u << shift)) + shift++; + + s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq); + s->rcp_shift = shift - 1; + + // With these values, 'q' is the correct quotient, so we + // have bias=start. + s->bias = start; + } +} + +// Initialize a decoder symbol to start "start" and frequency "freq" +static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq) +{ + RansAssert(start <= (1 << 16)); + RansAssert(freq <= (1 << 16) - start); + s->start = (uint16_t) start; + s->freq = (uint16_t) freq; +} + +// Encodes a given symbol. This is faster than straight RansEnc since we can do +// multiplications instead of a divide. +// +// See RansEncSymbolInit for a description of how this works. +static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym) +{ + RansAssert(sym->x_max != 0); // can't encode symbol with freq=0 + + // renormalize + uint32_t x = *r; + uint32_t x_max = sym->x_max; + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + + // x = C(s,x) + // NOTE: written this way so we get a 32-bit "multiply high" when + // available. If you're on a 64-bit platform with cheap multiplies + // (e.g. x64), just bake the +32 into rcp_shift. + uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift; + *r = x + sym->bias + q * sym->cmpl_freq; +} + +// Equivalent to RansDecAdvance that takes a symbol. +static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, const uint8_t* end, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvance(r, pptr, end, sym->start, sym->freq, scale_bits); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". +// No renormalization or output happens. +static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + *r = freq * (x >> scale_bits) + (x & mask) - start; +} + +// Equivalent to RansDecAdvanceStep that takes a symbol. +static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits); +} + +// Renormalize. +static inline void RansDecRenorm(RansState* r, uint8_t** pptr) +{ + // renormalize + uint32_t x = *r; + if (x < RANS_BYTE_L) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L); + *pptr = ptr; + } + + *r = x; +} + +// Verify final state +static inline int RansDecVerify(const RansState* const r) +{ + if (*r != RANS_BYTE_L) + { + return 1; // the final state is inconsistent with the initial state + } + return 0; +} + +#endif // RANS_BYTE_HEADER \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/reduce.c b/crypto_sign/haetae2/clean/reduce.c new file mode 100644 index 00000000..55623734 --- /dev/null +++ b/crypto_sign/haetae2/clean/reduce.c @@ -0,0 +1,92 @@ +#include "reduce.h" +#include "params.h" +#include + +/************************************************* + * Name: montgomery_reduce + * + * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, + * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. + * + * Arguments: - int64_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a * QINV; + t = (a - (int64_t)t * Q) >> 32; + return t; +} + +/************************************************* + * Name: caddq + * + * Description: Add Q if input coefficient is negative. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* + * Name: freeze + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze(int32_t a) { + int64_t t = (int64_t)a * QREC; + t = t >> 32; + t = a - t * Q; // -2Q < t < 2Q + t += (t >> 31) & DQ; // 0 <= t < 2Q + t -= ~((t - Q) >> 31) & Q; // 0 <= t < Q + return t; +} + +/************************************************* + * Name: reduce32_2q + * + * Description: compute reduction with 2Q + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t reduce32_2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + t -= ~((t - Q) >> 31) & DQ; // centered representation + return (int32_t)t; +} + +/************************************************* + * Name: freeze2q + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ 2Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + return (int32_t)t; +} diff --git a/crypto_sign/haetae2/clean/reduce.h b/crypto_sign/haetae2/clean/reduce.h new file mode 100644 index 00000000..6f4a3a76 --- /dev/null +++ b/crypto_sign/haetae2/clean/reduce.h @@ -0,0 +1,28 @@ +#ifndef HAETAE_REDUCE_H +#define HAETAE_REDUCE_H + +#include "params.h" +#include + +#define MONT 14321 // 2^32 % Q +#define MONTSQ 4214 // 2^64 % Q +#define QINV 940508161 // q^(-1) mod 2^32 +#define QREC 66575 // 2^32 / Q for Barrett +#define DQREC 33287 // 2^32 / DQ for Barrett + +#define montgomery_reduce HAETAE_NAMESPACE(montgomery_reduce) +int32_t montgomery_reduce(int64_t a); + +#define caddq HAETAE_NAMESPACE(caddq) +int32_t caddq(int32_t a); + +#define freeze HAETAE_NAMESPACE(freeze) +int32_t freeze(int32_t a); + +#define reduce32_2q HAETAE_NAMESPACE(reduce32_2q) +int32_t reduce32_2q(int32_t a); + +#define freeze2q HAETAE_NAMESPACE(freeze2q) +int32_t freeze2q(int32_t a); + +#endif diff --git a/crypto_sign/haetae2/clean/sampler.c b/crypto_sign/haetae2/clean/sampler.c new file mode 100644 index 00000000..4bb546b3 --- /dev/null +++ b/crypto_sign/haetae2/clean/sampler.c @@ -0,0 +1,272 @@ +#include "sampler.h" +#include "fixpoint.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: rej_uniform + * + * Description: Sample uniformly random coefficients in [0, Q-1] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + uint32_t t; + + ctr = pos = 0; + while (ctr < len && pos + 2 <= buflen) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + + if (t < Q) + a[ctr++] = t; + } + return ctr; +} + +/************************************************* + * Name: rej_eta + * + * Description: Sample uniformly random coefficients in [-ETA, ETA] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +static int32_t mod3(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq26(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq8(uint8_t t) { + int32_t r; + r = (t >> 2) + (t & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + + ctr = pos = 0; + while (ctr < len && pos < buflen) { +#if ETA == 1 + uint32_t t = buf[pos++]; + if (t < 243) { + // reduce mod 3 + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; // 171*3 = 1 mod 256 + t >>= 9; + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq26(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq8(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = (int32_t)t - (int32_t)3 * (t >> 1); + } +#elif ETA == 2 + uint32_t t0, t1; + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + if (t0 < 15) { + t0 = t0 - (205 * t0 >> 10) * 5; + a[ctr++] = 2 - t0; + } + if (t1 < 15 && ctr < len) { + t1 = t1 - (205 * t1 >> 10) * 5; + a[ctr++] = 2 - t1; + } +#endif + } + return ctr; +} + +static uint64_t approx_exp(const uint64_t x) { + int64_t result; + result = -0x0000B6C6340925AELL; + result = ((smulh48(result, x) + (1LL << 2)) >> 3) + 0x0000B4BD4DF85227LL; + result = ((smulh48(result, x) + (1LL << 2)) >> 3) - 0x0000887F727491E2LL; + result = ((smulh48(result, x) + (1LL << 1)) >> 2) + 0x0000AAAA643C7E8DLL; + result = ((smulh48(result, x) + (1LL << 1)) >> 2) - 0x0000AAAAA98179E6LL; + result = ((smulh48(result, x) + 1LL) >> 1) + 0x0000FFFFFFFB2E7ALL; + result = ((smulh48(result, x) + 1LL) >> 1) - 0x0000FFFFFFFFF85FLL; + result = ((smulh48(result, x))) + 0x0000FFFFFFFFFFFCLL; + return result; +} + +#define CDTLEN 64 +static const uint32_t CDT[CDTLEN] = { + 3266, 6520, 9748, 12938, 16079, 19159, 22168, 25096, +27934, 30674, 33309, 35833, 38241, 40531, 42698, 44742, +46663, 48460, 50135, 51690, 53128, 54454, 55670, 56781, +57794, 58712, 59541, 60287, 60956, 61554, 62085, 62556, +62972, 63337, 63657, 63936, 64178, 64388, 64569, 64724, +64857, 64970, 65066, 65148, 65216, 65273, 65321, 65361, +65394, 65422, 65444, 65463, 65478, 65490, 65500, 65508, +65514, 65519, 65523, 65527, 65529, 65531, 65533, 65534 +}; + + +static uint64_t sample_gauss16(const uint64_t rand16) { + unsigned int i; + uint64_t r = 0; + for (i = 0; i < CDTLEN; i++) { + r += (((uint64_t)CDT[i] - rand16) >> 63) & 1; + } + return r; +} + +#define GAUSS_RAND (72 + 16 + 48) +#define GAUSS_RAND_BYTES ((GAUSS_RAND + 7) / 8) +static int sample_gauss_sigma76(uint64_t *r, fp96_76 *sqr, + const uint8_t rand[GAUSS_RAND_BYTES]) { + const uint64_t *rand_gauss16_ptr = (uint64_t *)rand, + *rand_rej_ptr = (uint64_t *)(&rand[2]); + const uint64_t rand_gauss16 = (*rand_gauss16_ptr) & ((1ULL << 16) - 1); + const uint64_t rand_rej = (*rand_rej_ptr) & ((1ULL << 48) - 1); + uint64_t x, exp_in; + fp96_76 y; + + // sample x + x = sample_gauss16(rand_gauss16); + + // y := append x to y + // leave 16 bit for carries + y.limb48[0] = rand[8] | ((uint64_t)rand[9] << 8) | + ((uint64_t)rand[10] << 16) | ((uint64_t)rand[11] << 24) | + ((uint64_t)rand[12] << 32) | ((uint64_t)rand[13] << 40); + y.limb48[1] = + rand[14] | ((uint64_t)rand[15] << 8) | ((uint64_t)rand[16] << 16) | + (x << 24); + + // r := round y + *r = (y.limb48[0] >> 15) ^ (y.limb48[1] << 33); + *r += 1; // rounding + *r >>= 1; + + // sqr := y*y + fixpoint_square(sqr, &y); + + // sqr[1] = y^2 >> (76+48) // 34 bit + // sqr[0] = (y^2 >> 76) & ((1UL<<48)-1) // 48 bit + // exp_in := sqr - ((x*x) << 68) + exp_in = sqr->limb48[1] - ((x*x) << (68 - 48)); + exp_in <<= 20; + exp_in |= sqr->limb48[0] >> 28; + exp_in += 1; // rounding + exp_in >>= 1; + + return ((((int64_t)(rand_rej ^ + (rand_rej & 1)) // set lowest bit to zero in order to + // use it for rejection if sample==0 + - (int64_t)approx_exp(exp_in)) >> + 63) // reject with prob 1-approx_exp(exp_in) + & (((*r | -*r) >> 63) | rand_rej)) & + 1; // if the sample is zero, clear the return value with prob 1/2 +} + +int sample_gauss(uint64_t *r, fp96_76 *sqsum, const uint8_t *buf, const size_t buflen, const size_t len, const int dont_write_last) +{ + const uint8_t *pos = buf; + fp96_76 sqr; + size_t bytecnt = buflen, coefcnt = 0, cnt = 0; + int accepted; + uint64_t dummy; + + while (coefcnt < len) { + if (bytecnt < GAUSS_RAND_BYTES) { + renormalize(sqsum); + return coefcnt; + } + + if (dont_write_last && coefcnt == len-1) + { + accepted = sample_gauss_sigma76(&dummy, &sqr, pos); + } else { + accepted = sample_gauss_sigma76(&r[coefcnt], &sqr, pos); + } + cnt += 1; + coefcnt += accepted; + pos += GAUSS_RAND_BYTES; + bytecnt -= GAUSS_RAND_BYTES; + + sqsum->limb48[0] += sqr.limb48[0] & -(int64_t)accepted; + sqsum->limb48[1] += sqr.limb48[1] & -(int64_t)accepted; + } + + renormalize(sqsum); + return len; +} + +#define POLY_HYPERBALL_BUFLEN (GAUSS_RAND_BYTES * N) +#define POLY_HYPERBALL_NBLOCKS ((POLY_HYPERBALL_BUFLEN + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len) { + uint8_t buf[POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES]; + size_t bytecnt, coefcnt, firstflag = 1; + stream256_state state; + stream256_init(&state, seed, nonce); + + stream256_squeezeblocks(buf, POLY_HYPERBALL_NBLOCKS, &state); + for (size_t i = 0; i < len / 8; i++) { + signs[i] = buf[i]; + } + bytecnt = POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES - len / 8; + coefcnt = sample_gauss(r, sqsum, buf + len / 8, bytecnt, len, len%N); + while (coefcnt < len) { + size_t off = bytecnt % GAUSS_RAND_BYTES; + for (size_t i = 0; i < off; i++) { + buf[i] = buf[bytecnt + len/8*firstflag - off + i]; + } + stream256_squeezeblocks(buf + off, 1, &state); + bytecnt = STREAM256_BLOCKBYTES + off; + + coefcnt += sample_gauss(r + coefcnt, sqsum, buf, bytecnt, len - coefcnt, len%N); + firstflag = 0; + } +} diff --git a/crypto_sign/haetae2/clean/sampler.h b/crypto_sign/haetae2/clean/sampler.h new file mode 100644 index 00000000..adb71bfd --- /dev/null +++ b/crypto_sign/haetae2/clean/sampler.h @@ -0,0 +1,21 @@ +#ifndef HAETAE_SAMPLER_H +#define HAETAE_SAMPLER_H + +#include "fixpoint.h" +#include "params.h" +#include "reduce.h" +#include + +#define rej_uniform HAETAE_NAMESPACE(rej_uniform) +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); +#define rej_eta HAETAE_NAMESPACE(rej_eta) +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); + +#define sample_gauss_N HAETAE_NAMESPACE(sample_gauss_N) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len); + +#endif diff --git a/crypto_sign/haetae2/clean/sign.c b/crypto_sign/haetae2/clean/sign.c new file mode 100644 index 00000000..6088c90a --- /dev/null +++ b/crypto_sign/haetae2/clean/sign.c @@ -0,0 +1,467 @@ +#include "sign.h" +#include "packing.h" +#include "params.h" +#include "poly.h" +#include "polyfix.h" +#include "polymat.h" +#include "polyvec.h" +#include "randombytes.h" +#include "symmetric.h" +#include +#include +#include +#include + +/************************************************* + * Name: crypto_sign_keypair + * + * Description: Generates public and private key. + * + * Arguments: - uint8_t *pk: pointer to output public key (allocated + * array of CRYPTO_PUBLICKEYBYTES bytes) + * - uint8_t *sk: pointer to output private key (allocated + * array of CRYPTO_SECRETKEYBYTES bytes) + * + * Returns 0 (success) + **************************************************/ + +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES] = {0}; + uint16_t nonce = 0; + const uint8_t *rhoprime, *sigma, *key; + polyvecm A[K], s1, s1hat; + polyveck b, s2; +#if D > 0 + polyveck a, b0; +#else + polyveck s2hat; +#endif + xof256_state state; + + // Get entropy \rho + randombytes(seedbuf, SEEDBYTES); + + // Sample seeds with entropy \rho + xof256_absorbe_once(&state, seedbuf, SEEDBYTES); + xof256_squeeze(seedbuf, 2 * SEEDBYTES + CRHBYTES, &state); + + rhoprime = seedbuf; + sigma = rhoprime + SEEDBYTES; + key = sigma + CRHBYTES; + + // Expand Matrix A0 and vector a + polymatkm_expand(A, rhoprime); + +#if D > 0 + /********************************************** + * If there is rounding (D > 0), we need another polyveck a. + * Then, b = a + A0 * s1 + s2 and the lower D bits are + * rounded from b. The lower D bits are subsequently + * subtracted from s2. + **********************************************/ + polyveck_expand(&a, rhoprime); + +reject: + // Sample secret vectors s1 and s2 + polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); + nonce += M + K; + + // b = a + A0 * s1 + s2 mod q + s1hat = s1; + polyvecm_ntt(&s1hat); + polymatkm_pointwise_montgomery(&b, A, &s1hat); + polyveck_invntt_tomont(&b); + polyveck_add(&b, &b, &s2); + polyveck_add(&b, &b, &a); + polyveck_freeze(&b); + + // round off D bits + polyveck_decompose_vk(&b0, &b); + polyveck_sub(&s2, &s2, &b0); + + int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } +#else + /********************************************** + * If there is no rounding (D == 0), we store + * -2b directly in NTT domain into the public key. + **********************************************/ +reject: + // Sample secret vectors s1 and s2 + polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); + nonce += M + K; + int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } + + // b = A0 * s1 + s2 mod q + s1hat = s1; + s2hat = s2; + polyvecm_ntt(&s1hat); + polyveck_ntt(&s2hat); + polymatkm_pointwise_montgomery(&b, A, &s1hat); + polyveck_frommont(&b); + polyveck_add(&b, &b, &s2hat); + polyveck_double_negate(&b); + polyveck_caddq(&b); // directly compute and store NTT(-2b) +#endif + + pack_pk(pk, &b, rhoprime); + pack_sk(sk, pk, &s1, &s2, key); + + return 0; +} + +/************************************************* + * Name: crypto_sign_signature + * + * Description: Computes signature. + * + * Arguments: - uint8_t *sig: pointer to output signature (of length + * CRYPTO_BYTES) + * - size_t *siglen: pointer to output length of signature + * - uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk) { + + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; + uint8_t mu[SEEDBYTES] = {0}; + uint8_t cseed[SEEDBYTES] = {0}; // seed of a challenge polynomial c + uint8_t b = 0; // one bit + uint16_t counter = 0; + uint64_t reject1, reject2; + + polyvecm s1; + polyvecl A1[K], cs1; + polyveck s2, cs2, highbits, Ay; + polyfixvecl y1, z1, z1tmp; + polyfixveck y2, z2, z2tmp; + polyvecl z1rnd; // round of z1 + polyvecl hb_z1, lb_z1; + polyveck z2rnd, h, htmp; // round of z2 + poly c, z1rnd0, lsb; + + xof256_state state; + + unsigned int i; + + // Unpack secret key + unpack_sk(A1, &s1, &s2, key, sk); + + xof256_absorbe_twice(&state, sk, CRYPTO_PUBLICKEYBYTES, m, mlen); + xof256_squeeze(mu, SEEDBYTES, &state); + xof256_absorbe_twice(&state, key, SEEDBYTES, mu, SEEDBYTES); + xof256_squeeze(seedbuf, CRHBYTES, &state); + + polyvecm_ntt(&s1); + polyveck_ntt(&s2); + +reject: + + /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ + randombytes(&b, sizeof(uint8_t)); + counter = polyfixveclk_sample_hyperball(&y1, &y2, seedbuf, counter); + + /*------------------- 2. Compute a chanllenge c --------------------------*/ + // Round y1 and y2 + polyfixvecl_round(&z1rnd, &y1); + polyfixveck_round(&z2rnd, &y2); + + // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q + z1rnd0 = z1rnd.vec[0]; + polyvecl_ntt(&z1rnd); + polymatkl_pointwise_montgomery(&Ay, A1, &z1rnd); + polyveck_invntt_tomont(&Ay); + polyveck_double(&z2rnd); + polyveck_add(&Ay, &Ay, &z2rnd); + + // recover A * round(y) mod 2q + polyveck_poly_fromcrt(&Ay, &Ay, &z1rnd0); + polyveck_freeze2q(&Ay); + + // HighBits of (A * round(y) mod 2q) + polyveck_highbits_hint(&highbits, &Ay); + + // LSB(round(y_0) * j) + poly_lsb(&lsb, &z1rnd0); + + // Pack HighBits of A * round(y) mod 2q and LSB of round(y0) + polyveck_pack_highbits(buf, &highbits); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); + + // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, buf, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, + SEEDBYTES); + xof256_squeeze(cseed, SEEDBYTES, &state); + + // c = challenge(c_seed) + poly_challenge(&c, cseed); + + /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ + // cs = c * s = c * (si1 || s2) + cs1.vec[0] = c; + poly_ntt(&c); + + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery(&cs1.vec[i], &c, &s1.vec[i - 1]); + poly_invntt_tomont(&cs1.vec[i]); + } + polyveck_poly_pointwise_montgomery(&cs2, &s2, &c); + polyveck_invntt_tomont(&cs2); + + // z = y + (-1)^b cs = z1 + z2 + polyvecl_cneg(&cs1, b & 1); + polyveck_cneg(&cs2, b & 1); + polyfixvecl_add(&z1, &y1, &cs1); + polyfixveck_add(&z2, &y2, &cs2); + + // reject if norm(z) >= B' + reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&z1, &z2)) >> 63; + reject1 &= 1; + + polyfixvecl_double(&z1tmp, &z1); + polyfixveck_double(&z2tmp, &z2); + + polyfixfixvecl_sub(&z1tmp, &z1tmp, &y1); + polyfixfixveck_sub(&z2tmp, &z2tmp, &y2); + + // reject if norm(2z-y) < B and b' = 0 + reject2 = + (polyfixveclk_sqnorm2(&z1tmp, &z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; + reject2 &= 1; + reject2 &= (b & 0x2) >> 1; + + if (reject1 | reject2) { + goto reject; + } + + /*------------------- 4. Make a hint -------------------------------------*/ + // Round z1 and z2 + polyfixvecl_round(&z1rnd, &z1); + polyfixveck_round(&z2rnd, &z2); + + // recover A1 * round(z1) - qcj mod 2q + polyveck_double(&z2rnd); + polyveck_sub(&htmp, &Ay, &z2rnd); + polyveck_freeze2q(&htmp); + + // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) + polyveck_highbits_hint(&htmp, &htmp); + polyveck_sub(&h, &highbits, &htmp); + polyveck_caddDQ2ALPHA(&h); + + /*------------------ Decompose(z1) and Pack signature -------------------*/ + polyvecl_lowbits(&lb_z1, &z1rnd); // TODO do this in one function together! + polyvecl_highbits(&hb_z1, &z1rnd); + + if (pack_sig(sig, cseed, &lb_z1, &hb_z1, + &h)) { // reject if signature is too big + goto reject; + } + *siglen = CRYPTO_BYTES; + + return 0; +} + +/************************************************* + * Name: crypto_sign + * + * Description: Compute signed message. + * + * Arguments: - uint8_t *sm: pointer to output signed message (allocated + * array with CRYPTO_BYTES + mlen bytes), + * can be equal to m + * - size_t *smlen: pointer to output length of signed + * message + * - const uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - const uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t i; + + for (i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + *smlen += mlen; + return 0; +} + +/************************************************* + * Name: crypto_sign_verify + * + * Description: Verifies signature. + * + * Arguments: - uint8_t *m: pointer to input signature + * - size_t siglen: length of signature + * - const uint8_t *m: pointer to message + * - size_t mlen: length of message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signature could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk) { + unsigned int i; + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + uint8_t c_seed[SEEDBYTES] = {0}, c_seed2[SEEDBYTES] = {0}; + uint8_t rhoprime[SEEDBYTES] = {0}; + uint64_t sqnorm2; + polyvecl A1[K], z1; + polyveck b, highbits, h, z2, w; +#if D > 0 + polyveck a; +#endif + poly c, wprime; + + xof256_state state; + + // Check signature length + if (siglen != CRYPTO_BYTES) { + return -1; + } + + // Unpack public key + unpack_pk(&b, rhoprime, pk); + + // Unpack signature and Check conditions -- A1 is used only as intermediate + // buffer for the low bits + if (unpack_sig(c_seed, A1, &z1, &h, sig)) { + return -1; + } + + // Compose z1 out of HighBits(z1) and LowBits(z1) + for (i = 0; i < L; ++i) { + poly_compose(&z1.vec[i], &z1.vec[i], &A1[0].vec[i]); + } + + /*------------------- 1. Recover A1 --------------------------------------*/ + // A1 = (-2b + qj || 2 * A0) + polymatkl_expand(A1, rhoprime); + polymatkl_double(A1); +#if D == 1 + polyveck_expand(&a, rhoprime); + polyveck_double(&b); + polyveck_sub(&b, &a, &b); + polyveck_double(&b); + polyveck_ntt(&b); +#elif D == 0 + // no action required as b already contains -2b in NTT domain +#else +#error "Not yet implemented." +#endif + + for (i = 0; i < K; ++i) { + A1[i].vec[0] = b.vec[i]; + } + + /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ + // c = challenge(c_seed) + poly_challenge(&c, c_seed); + + // compute squared norm of z1 and w' before NTT + sqnorm2 = polyvecl_sqnorm2(&z1); + poly_sub(&wprime, &z1.vec[0], &c); + poly_lsb(&wprime, &wprime); + + // A1 * round(z1) - qcj mod q + polyvecl_ntt(&z1); + polymatkl_pointwise_montgomery(&highbits, A1, &z1); + polyveck_invntt_tomont(&highbits); + + // recover A1 * round(z1) - qcj mod 2q + polyveck_poly_fromcrt(&highbits, &highbits, &wprime); + polyveck_freeze2q(&highbits); + + // recover w1 + polyveck_highbits_hint(&w, &highbits); + polyveck_add(&w, &w, &h); + polyveck_csubDQ2ALPHA(&w); + + // recover \tilde{z}_2 mod q + polyveck_mul_alpha(&z2, &w); + polyveck_sub(&z2, &z2, &highbits); + poly_add(&z2.vec[0], &z2.vec[0], &wprime); + polyveck_reduce2q(&z2); + polyveck_div2(&z2); + + // check final norm of \tilde{z} + if (sqnorm2 + polyveck_sqnorm2(&z2) > B2SQ) { + return -1; + } + + /*------------------- 3. Compute c_seed' and Compare ---------------------*/ + + // Pack highBits(A * round(z) - qcj mod 2q) and h' + polyveck_pack_highbits(buf, &w); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); + + xof256_absorbe_twice(&state, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); + xof256_squeeze(c_seed2, SEEDBYTES, &state); + + // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, buf, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, + c_seed2, SEEDBYTES); + xof256_squeeze(c_seed2, SEEDBYTES, &state); + + for (i = 0; i < SEEDBYTES; ++i) { + if (c_seed[i] != c_seed2[i]) { + return -1; + } + } + return 0; +} + +/************************************************* + * Name: crypto_sign_open + * + * Description: Verify signed message. + * + * Arguments: - uint8_t *m: pointer to output message (allocated + * array with smlen bytes), can be equal to sm + * - size_t *mlen: pointer to output length of message + * - const uint8_t *sm: pointer to signed message + * - size_t smlen: length of signed message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signed message could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + size_t i; + + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if (crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for (i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + for (i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/crypto_sign/haetae2/clean/sign.h b/crypto_sign/haetae2/clean/sign.h new file mode 100644 index 00000000..0515cab0 --- /dev/null +++ b/crypto_sign/haetae2/clean/sign.h @@ -0,0 +1,30 @@ +#ifndef HAETAE_SIGN_H +#define HAETAE_SIGN_H + +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include +#include + +#define crypto_sign_keypair HAETAE_NAMESPACE(keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature HAETAE_NAMESPACE(signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk); + +#define crypto_sign HAETAE_NAMESPACE(sign) +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify HAETAE_NAMESPACE(verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk); + +#define crypto_sign_open HAETAE_NAMESPACE(open) +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif // HAETAE_SIGN_H \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/symmetric-shake.c b/crypto_sign/haetae2/clean/symmetric-shake.c new file mode 100644 index 00000000..c9aeadd3 --- /dev/null +++ b/crypto_sign/haetae2/clean/symmetric-shake.c @@ -0,0 +1,38 @@ +#include "fips202.h" +#include "params.h" +#include "symmetric.h" +#include + +void haetae_shake128_stream_init(keccak_state *state, + const uint8_t seed[SEEDBYTES], + uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake128_init(state); + shake128_absorb(state, seed, SEEDBYTES); + shake128_absorb(state, t, 2); + shake128_finalize(state); +} + +void haetae_shake256_stream_init(keccak_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake256_init(state); + shake256_absorb(state, seed, CRHBYTES); + shake256_absorb(state, t, 2); + shake256_finalize(state); +} + +void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, + size_t in2len) { + shake256_init(state); + shake256_absorb(state, in1, in1len); + shake256_absorb(state, in2, in2len); + shake256_finalize(state); +} diff --git a/crypto_sign/haetae2/clean/symmetric.h b/crypto_sign/haetae2/clean/symmetric.h new file mode 100644 index 00000000..b3b9c37d --- /dev/null +++ b/crypto_sign/haetae2/clean/symmetric.h @@ -0,0 +1,78 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include "params.h" +#include +#include "fips202.h" + +// Cryptographic XOF function: shake256 +typedef keccak_state xof256_state; + +#define haetae_shake256_absorb_twice \ + HAETAE_NAMESPACE(haetae_shake256_absorb_twice) +void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, size_t in2len); + +#define XOF256_BLOCKBYTES SHAKE256_RATE + +#define xof256_absorbe_once(STATE, IN, IN_LEN) \ + shake256_absorb_once(STATE, IN, IN_LEN) +#define xof256_absorbe_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) \ + haetae_shake256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) +#define xof256_squeeze(OUT, OUT_LEN, STATE) \ + shake256_squeeze(OUT, OUT_LEN, STATE) +#define xof256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + + +// Stream function: aes256 or shake128|256 +#ifdef HAETAE_USE_AES // stream: aes256 + +#include "aes256ctr.h" + +typedef aes256ctr_ctx stream128_state; +typedef aes256ctr_ctx stream256_state; + +#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES +#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES + +#define stream128_init(STATE, SEED, NONCE) \ + aes256ctr_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + aes256ctr_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#else // stream: shake128 and shake256 + +typedef keccak_state stream128_state; +typedef keccak_state stream256_state; + +#define haetae_shake128_stream_init \ + HAETAE_NAMESPACE(haetae_shake128_stream_init) +void haetae_shake128_stream_init(keccak_state *state, + const uint8_t seed[SEEDBYTES], uint16_t nonce); + +#define haetae_shake256_stream_init \ + HAETAE_NAMESPACE(haetae_shake256_stream_init) +void haetae_shake256_stream_init(keccak_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) \ + haetae_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + haetae_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#endif // stream + +#endif //SYMMETRIC_H + From b48968eb11f49d58ae3bf3213c697c0d1c43a6f6 Mon Sep 17 00:00:00 2001 From: Marc Date: Wed, 22 Nov 2023 17:28:46 +0100 Subject: [PATCH 032/107] Update HAETAE This commit implements the post-quantum signature scheme HAETAE from https://eprint.iacr.org/2023/624 https://kpqc.cryptolab.co.kr/haetae The stack strategy can be chosen config.h by setting STACK_STRATEGY to the appropriate value (run "make clean" when changing it). * 0 or undefined: Optimized for speed (default). * 1: Disable buffers for the polynomials of the verification key in crypto_sign_keypair() and crypto_sign(). This reduces speed, as the key needs to be recomputed after each rejection. * 2: In addition to 1, sample the hyperball in multiple passes, such that some intermediate values are computed on demand, rather than being buffered. This roughly doubles the runtime of crypto_sign(). The scheme HAETAE2 contains a reference implementation, which has been renamed from "clean" in previous commits to "ref". The reference implementation would run out of memory for schemes HAETAE3 and HAETAE5 and is therefore not included for these schemes. --- crypto_sign/haetae2/{clean => ref}/api.h | 0 crypto_sign/haetae2/{clean => ref}/config.h | 2 +- .../haetae2/{clean => ref}/decompose.c | 0 .../haetae2/{clean => ref}/decompose.h | 0 crypto_sign/haetae2/{clean => ref}/encoding.c | 0 crypto_sign/haetae2/{clean => ref}/encoding.h | 0 crypto_sign/haetae2/{clean => ref}/fft.c | 0 crypto_sign/haetae2/{clean => ref}/fft.h | 0 crypto_sign/haetae2/{clean => ref}/fips202.c | 0 crypto_sign/haetae2/{clean => ref}/fips202.h | 0 crypto_sign/haetae2/{clean => ref}/fixpoint.c | 0 crypto_sign/haetae2/{clean => ref}/fixpoint.h | 0 crypto_sign/haetae2/{clean => ref}/ntt.c | 0 crypto_sign/haetae2/{clean => ref}/ntt.h | 0 crypto_sign/haetae2/{clean => ref}/packing.c | 40 +++++++++------- crypto_sign/haetae2/{clean => ref}/packing.h | 4 +- crypto_sign/haetae2/{clean => ref}/params.h | 0 crypto_sign/haetae2/{clean => ref}/poly.c | 16 +++++-- crypto_sign/haetae2/{clean => ref}/poly.h | 2 +- crypto_sign/haetae2/{clean => ref}/polyfix.c | 13 +++++- crypto_sign/haetae2/{clean => ref}/polyfix.h | 2 +- crypto_sign/haetae2/{clean => ref}/polymat.c | 0 crypto_sign/haetae2/{clean => ref}/polymat.h | 0 crypto_sign/haetae2/{clean => ref}/polyvec.c | 0 crypto_sign/haetae2/{clean => ref}/polyvec.h | 0 .../haetae2/{clean => ref}/rans_byte.h | 0 crypto_sign/haetae2/{clean => ref}/reduce.c | 0 crypto_sign/haetae2/{clean => ref}/reduce.h | 0 crypto_sign/haetae2/{clean => ref}/sampler.c | 0 crypto_sign/haetae2/{clean => ref}/sampler.h | 0 crypto_sign/haetae2/{clean => ref}/sign.c | 46 +++++++------------ crypto_sign/haetae2/{clean => ref}/sign.h | 2 +- .../haetae2/{clean => ref}/symmetric-shake.c | 0 .../haetae2/{clean => ref}/symmetric.h | 0 34 files changed, 69 insertions(+), 58 deletions(-) rename crypto_sign/haetae2/{clean => ref}/api.h (100%) rename crypto_sign/haetae2/{clean => ref}/config.h (98%) rename crypto_sign/haetae2/{clean => ref}/decompose.c (100%) rename crypto_sign/haetae2/{clean => ref}/decompose.h (100%) rename crypto_sign/haetae2/{clean => ref}/encoding.c (100%) rename crypto_sign/haetae2/{clean => ref}/encoding.h (100%) rename crypto_sign/haetae2/{clean => ref}/fft.c (100%) rename crypto_sign/haetae2/{clean => ref}/fft.h (100%) rename crypto_sign/haetae2/{clean => ref}/fips202.c (100%) rename crypto_sign/haetae2/{clean => ref}/fips202.h (100%) rename crypto_sign/haetae2/{clean => ref}/fixpoint.c (100%) rename crypto_sign/haetae2/{clean => ref}/fixpoint.h (100%) rename crypto_sign/haetae2/{clean => ref}/ntt.c (100%) rename crypto_sign/haetae2/{clean => ref}/ntt.h (100%) rename crypto_sign/haetae2/{clean => ref}/packing.c (93%) rename crypto_sign/haetae2/{clean => ref}/packing.h (76%) rename crypto_sign/haetae2/{clean => ref}/params.h (100%) rename crypto_sign/haetae2/{clean => ref}/poly.c (96%) rename crypto_sign/haetae2/{clean => ref}/poly.h (95%) rename crypto_sign/haetae2/{clean => ref}/polyfix.c (97%) rename crypto_sign/haetae2/{clean => ref}/polyfix.h (96%) rename crypto_sign/haetae2/{clean => ref}/polymat.c (100%) rename crypto_sign/haetae2/{clean => ref}/polymat.h (100%) rename crypto_sign/haetae2/{clean => ref}/polyvec.c (100%) rename crypto_sign/haetae2/{clean => ref}/polyvec.h (100%) rename crypto_sign/haetae2/{clean => ref}/rans_byte.h (100%) rename crypto_sign/haetae2/{clean => ref}/reduce.c (100%) rename crypto_sign/haetae2/{clean => ref}/reduce.h (100%) rename crypto_sign/haetae2/{clean => ref}/sampler.c (100%) rename crypto_sign/haetae2/{clean => ref}/sampler.h (100%) rename crypto_sign/haetae2/{clean => ref}/sign.c (91%) rename crypto_sign/haetae2/{clean => ref}/sign.h (97%) rename crypto_sign/haetae2/{clean => ref}/symmetric-shake.c (100%) rename crypto_sign/haetae2/{clean => ref}/symmetric.h (100%) diff --git a/crypto_sign/haetae2/clean/api.h b/crypto_sign/haetae2/ref/api.h similarity index 100% rename from crypto_sign/haetae2/clean/api.h rename to crypto_sign/haetae2/ref/api.h diff --git a/crypto_sign/haetae2/clean/config.h b/crypto_sign/haetae2/ref/config.h similarity index 98% rename from crypto_sign/haetae2/clean/config.h rename to crypto_sign/haetae2/ref/config.h index 983cd91b..52c9e87b 100644 --- a/crypto_sign/haetae2/clean/config.h +++ b/crypto_sign/haetae2/ref/config.h @@ -16,4 +16,4 @@ #define HAETAE_NAMESPACETOP haetae5 #define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s #endif -#endif \ No newline at end of file +#endif diff --git a/crypto_sign/haetae2/clean/decompose.c b/crypto_sign/haetae2/ref/decompose.c similarity index 100% rename from crypto_sign/haetae2/clean/decompose.c rename to crypto_sign/haetae2/ref/decompose.c diff --git a/crypto_sign/haetae2/clean/decompose.h b/crypto_sign/haetae2/ref/decompose.h similarity index 100% rename from crypto_sign/haetae2/clean/decompose.h rename to crypto_sign/haetae2/ref/decompose.h diff --git a/crypto_sign/haetae2/clean/encoding.c b/crypto_sign/haetae2/ref/encoding.c similarity index 100% rename from crypto_sign/haetae2/clean/encoding.c rename to crypto_sign/haetae2/ref/encoding.c diff --git a/crypto_sign/haetae2/clean/encoding.h b/crypto_sign/haetae2/ref/encoding.h similarity index 100% rename from crypto_sign/haetae2/clean/encoding.h rename to crypto_sign/haetae2/ref/encoding.h diff --git a/crypto_sign/haetae2/clean/fft.c b/crypto_sign/haetae2/ref/fft.c similarity index 100% rename from crypto_sign/haetae2/clean/fft.c rename to crypto_sign/haetae2/ref/fft.c diff --git a/crypto_sign/haetae2/clean/fft.h b/crypto_sign/haetae2/ref/fft.h similarity index 100% rename from crypto_sign/haetae2/clean/fft.h rename to crypto_sign/haetae2/ref/fft.h diff --git a/crypto_sign/haetae2/clean/fips202.c b/crypto_sign/haetae2/ref/fips202.c similarity index 100% rename from crypto_sign/haetae2/clean/fips202.c rename to crypto_sign/haetae2/ref/fips202.c diff --git a/crypto_sign/haetae2/clean/fips202.h b/crypto_sign/haetae2/ref/fips202.h similarity index 100% rename from crypto_sign/haetae2/clean/fips202.h rename to crypto_sign/haetae2/ref/fips202.h diff --git a/crypto_sign/haetae2/clean/fixpoint.c b/crypto_sign/haetae2/ref/fixpoint.c similarity index 100% rename from crypto_sign/haetae2/clean/fixpoint.c rename to crypto_sign/haetae2/ref/fixpoint.c diff --git a/crypto_sign/haetae2/clean/fixpoint.h b/crypto_sign/haetae2/ref/fixpoint.h similarity index 100% rename from crypto_sign/haetae2/clean/fixpoint.h rename to crypto_sign/haetae2/ref/fixpoint.h diff --git a/crypto_sign/haetae2/clean/ntt.c b/crypto_sign/haetae2/ref/ntt.c similarity index 100% rename from crypto_sign/haetae2/clean/ntt.c rename to crypto_sign/haetae2/ref/ntt.c diff --git a/crypto_sign/haetae2/clean/ntt.h b/crypto_sign/haetae2/ref/ntt.h similarity index 100% rename from crypto_sign/haetae2/clean/ntt.h rename to crypto_sign/haetae2/ref/ntt.h diff --git a/crypto_sign/haetae2/clean/packing.c b/crypto_sign/haetae2/ref/packing.c similarity index 93% rename from crypto_sign/haetae2/clean/packing.c rename to crypto_sign/haetae2/ref/packing.c index 261d3628..4fd76e2f 100644 --- a/crypto_sign/haetae2/clean/packing.c +++ b/crypto_sign/haetae2/ref/packing.c @@ -155,7 +155,7 @@ void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, *Enc(h)). * * Arguments: - uint8_t sig[]: output byte array - * - const uint8_t c_seed[]: pointer to seed of challenge + * - const poly *c: pointer to challenge polynomial * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of *length L * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of @@ -163,7 +163,7 @@ void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, * - const polyveck *h: pointer t vector h of length K * Returns 1 in case the signature size is above the threshold; otherwise 0. **************************************************/ -int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h) { @@ -174,9 +174,13 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], // init/padding with zeros: memset(sig, 0, CRYPTO_BYTES); - - memcpy(sig, c_seed, SEEDBYTES); - sig += SEEDBYTES; + + // encode challenge + for (size_t i = 0; i < N; i++) + { + sig[i/8] |= c->coeffs[i] << (i%8); + } + sig += N / 8; for (int i = 0; i < L; ++i) poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); @@ -196,13 +200,13 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { return 1; // encoding size offset out of range } - + offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; offset_enc_h = size_enc_h - BASE_ENC_H; if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > CRYPTO_BYTES) { - return 1; // signature too big + return 1; // signature too big } sig[0] = offset_enc_hb_z1; @@ -214,7 +218,7 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], memcpy(sig, encoded_h, size_enc_h); sig += size_enc_h; - + return 0; } @@ -224,7 +228,7 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), *Enc(h)). * - * Arguments: - uint8_t c_seed[]: pointer to output seed of challenge + * Arguments: - poly *c: pointer to challenge polynomial * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) * - polyveck *h: pointer to output vector h @@ -233,16 +237,20 @@ int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], * * Returns 1 in case of malformed signature; otherwise 0. **************************************************/ -int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, +int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]) { + unsigned int i; uint16_t size_enc_hb_z1, size_enc_h; - memcpy(c_seed, sig, SEEDBYTES); - sig += SEEDBYTES; + for (i = 0; i < N; i++) + { + c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; + } + sig += N / 8; - for (int i = 0; i < L; ++i) + for (i = 0; i < L; ++i) poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); sig += L * N; @@ -256,17 +264,17 @@ int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { return 1; // decoding failed } - + sig += size_enc_hb_z1; if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { return 1; // decoding failed } - + sig += size_enc_h; for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) if(sig[i] != 0) return 1; // verify zero padding return 0; -} +} \ No newline at end of file diff --git a/crypto_sign/haetae2/clean/packing.h b/crypto_sign/haetae2/ref/packing.h similarity index 76% rename from crypto_sign/haetae2/clean/packing.h rename to crypto_sign/haetae2/ref/packing.h index 1188d089..ff9eb03b 100644 --- a/crypto_sign/haetae2/clean/packing.h +++ b/crypto_sign/haetae2/ref/packing.h @@ -17,9 +17,9 @@ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKE void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); #define pack_sig HAETAE_NAMESPACE(pack_sig) -int pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c_seed[SEEDBYTES], const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); #define unpack_sig HAETAE_NAMESPACE(unpack_sig) -int unpack_sig(uint8_t c_seed[SEEDBYTES], polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); +int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); #endif //HAETAE_PACKING_H // clang-format on diff --git a/crypto_sign/haetae2/clean/params.h b/crypto_sign/haetae2/ref/params.h similarity index 100% rename from crypto_sign/haetae2/clean/params.h rename to crypto_sign/haetae2/ref/params.h diff --git a/crypto_sign/haetae2/clean/poly.c b/crypto_sign/haetae2/ref/poly.c similarity index 96% rename from crypto_sign/haetae2/clean/poly.c rename to crypto_sign/haetae2/ref/poly.c index 411b9d3e..70ebe816 100644 --- a/crypto_sign/haetae2/clean/poly.c +++ b/crypto_sign/haetae2/ref/poly.c @@ -253,16 +253,19 @@ uint8_t hammingWeight_8(uint8_t x) { * coefficients using the output stream of SHAKE256(seed). * * Arguments: - poly *c: pointer to output polynomial - * - const uint8_t seed[]: byte array containing seed of length - * SEEDBYTES + * - const uint8_t highbits_lsb[]: packed highbits and lsb + * - const uint8_t mu[]: hash of pk and message **************************************************/ -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]) { #if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) unsigned int i, b, pos = 0; uint8_t buf[XOF256_BLOCKBYTES]; xof256_state state; - xof256_absorbe_once(&state, seed, SEEDBYTES); + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, highbits_lsb, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, + SEEDBYTES); xof256_squeezeblocks(buf, 1, &state); for (i = 0; i < N; ++i) @@ -286,7 +289,10 @@ void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { uint8_t buf[32] = {0}; xof256_state state; - xof256_absorbe_once(&state, seed, SEEDBYTES); + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, highbits_lsb, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, + SEEDBYTES); xof256_squeeze(buf, 32, &state); for (i = 0; i < 32; ++i) diff --git a/crypto_sign/haetae2/clean/poly.h b/crypto_sign/haetae2/ref/poly.h similarity index 95% rename from crypto_sign/haetae2/clean/poly.h rename to crypto_sign/haetae2/ref/poly.h index e264bb55..3c801b3b 100644 --- a/crypto_sign/haetae2/clean/poly.h +++ b/crypto_sign/haetae2/ref/poly.h @@ -39,7 +39,7 @@ void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); #define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); #define poly_challenge HAETAE_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]); #define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) void poly_decomposed_pack(uint8_t *buf, const poly *a); diff --git a/crypto_sign/haetae2/clean/polyfix.c b/crypto_sign/haetae2/ref/polyfix.c similarity index 97% rename from crypto_sign/haetae2/clean/polyfix.c rename to crypto_sign/haetae2/ref/polyfix.c index 65612e90..c453d293 100644 --- a/crypto_sign/haetae2/clean/polyfix.c +++ b/crypto_sign/haetae2/ref/polyfix.c @@ -232,7 +232,7 @@ uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { return ret; } -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce) { uint16_t ni = nonce; @@ -277,5 +277,16 @@ uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, } } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); + { + uint8_t tmp[CRHBYTES + 2]; + for (i = 0; i < CRHBYTES; i++) + { + tmp[i] = seed[i]; + } + tmp[CRHBYTES + 0] = ni >> 0; + tmp[CRHBYTES + 1] = ni >> 8; + shake256(b, 1, tmp, CRHBYTES+2); + } + return ni; } diff --git a/crypto_sign/haetae2/clean/polyfix.h b/crypto_sign/haetae2/ref/polyfix.h similarity index 96% rename from crypto_sign/haetae2/clean/polyfix.h rename to crypto_sign/haetae2/ref/polyfix.h index 9a4945c2..6177319c 100644 --- a/crypto_sign/haetae2/clean/polyfix.h +++ b/crypto_sign/haetae2/ref/polyfix.h @@ -55,7 +55,7 @@ void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); #define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, const uint8_t seed[CRHBYTES], const uint16_t nonce); +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); #endif // clang-format on diff --git a/crypto_sign/haetae2/clean/polymat.c b/crypto_sign/haetae2/ref/polymat.c similarity index 100% rename from crypto_sign/haetae2/clean/polymat.c rename to crypto_sign/haetae2/ref/polymat.c diff --git a/crypto_sign/haetae2/clean/polymat.h b/crypto_sign/haetae2/ref/polymat.h similarity index 100% rename from crypto_sign/haetae2/clean/polymat.h rename to crypto_sign/haetae2/ref/polymat.h diff --git a/crypto_sign/haetae2/clean/polyvec.c b/crypto_sign/haetae2/ref/polyvec.c similarity index 100% rename from crypto_sign/haetae2/clean/polyvec.c rename to crypto_sign/haetae2/ref/polyvec.c diff --git a/crypto_sign/haetae2/clean/polyvec.h b/crypto_sign/haetae2/ref/polyvec.h similarity index 100% rename from crypto_sign/haetae2/clean/polyvec.h rename to crypto_sign/haetae2/ref/polyvec.h diff --git a/crypto_sign/haetae2/clean/rans_byte.h b/crypto_sign/haetae2/ref/rans_byte.h similarity index 100% rename from crypto_sign/haetae2/clean/rans_byte.h rename to crypto_sign/haetae2/ref/rans_byte.h diff --git a/crypto_sign/haetae2/clean/reduce.c b/crypto_sign/haetae2/ref/reduce.c similarity index 100% rename from crypto_sign/haetae2/clean/reduce.c rename to crypto_sign/haetae2/ref/reduce.c diff --git a/crypto_sign/haetae2/clean/reduce.h b/crypto_sign/haetae2/ref/reduce.h similarity index 100% rename from crypto_sign/haetae2/clean/reduce.h rename to crypto_sign/haetae2/ref/reduce.h diff --git a/crypto_sign/haetae2/clean/sampler.c b/crypto_sign/haetae2/ref/sampler.c similarity index 100% rename from crypto_sign/haetae2/clean/sampler.c rename to crypto_sign/haetae2/ref/sampler.c diff --git a/crypto_sign/haetae2/clean/sampler.h b/crypto_sign/haetae2/ref/sampler.h similarity index 100% rename from crypto_sign/haetae2/clean/sampler.h rename to crypto_sign/haetae2/ref/sampler.h diff --git a/crypto_sign/haetae2/clean/sign.c b/crypto_sign/haetae2/ref/sign.c similarity index 91% rename from crypto_sign/haetae2/clean/sign.c rename to crypto_sign/haetae2/ref/sign.c index 6088c90a..a53cac2b 100644 --- a/crypto_sign/haetae2/clean/sign.c +++ b/crypto_sign/haetae2/ref/sign.c @@ -135,7 +135,6 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; uint8_t mu[SEEDBYTES] = {0}; - uint8_t cseed[SEEDBYTES] = {0}; // seed of a challenge polynomial c uint8_t b = 0; // one bit uint16_t counter = 0; uint64_t reject1, reject2; @@ -148,7 +147,7 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, polyvecl z1rnd; // round of z1 polyvecl hb_z1, lb_z1; polyveck z2rnd, h, htmp; // round of z2 - poly c, z1rnd0, lsb; + poly c, chat, z1rnd0, lsb; xof256_state state; @@ -168,8 +167,7 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, reject: /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ - randombytes(&b, sizeof(uint8_t)); - counter = polyfixveclk_sample_hyperball(&y1, &y2, seedbuf, counter); + counter = polyfixveclk_sample_hyperball(&y1, &y2, &b, seedbuf, counter); /*------------------- 2. Compute a chanllenge c --------------------------*/ // Round y1 and y2 @@ -198,25 +196,20 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, polyveck_pack_highbits(buf, &highbits); poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); - // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, buf, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, - SEEDBYTES); - xof256_squeeze(cseed, SEEDBYTES, &state); - - // c = challenge(c_seed) - poly_challenge(&c, cseed); + // c = challenge(highbits, lsb, mu) + poly_challenge(&c, buf, mu); /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ // cs = c * s = c * (si1 || s2) cs1.vec[0] = c; - poly_ntt(&c); + chat = c; + poly_ntt(&chat); for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&cs1.vec[i], &c, &s1.vec[i - 1]); + poly_pointwise_montgomery(&cs1.vec[i], &chat, &s1.vec[i - 1]); poly_invntt_tomont(&cs1.vec[i]); } - polyveck_poly_pointwise_montgomery(&cs2, &s2, &c); + polyveck_poly_pointwise_montgomery(&cs2, &s2, &chat); polyveck_invntt_tomont(&cs2); // z = y + (-1)^b cs = z1 + z2 @@ -264,7 +257,7 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, polyvecl_lowbits(&lb_z1, &z1rnd); // TODO do this in one function together! polyvecl_highbits(&hb_z1, &z1rnd); - if (pack_sig(sig, cseed, &lb_z1, &hb_z1, + if (pack_sig(sig, &c, &lb_z1, &hb_z1, &h)) { // reject if signature is too big goto reject; } @@ -317,15 +310,14 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) { unsigned int i; uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t c_seed[SEEDBYTES] = {0}, c_seed2[SEEDBYTES] = {0}; - uint8_t rhoprime[SEEDBYTES] = {0}; + uint8_t rhoprime[SEEDBYTES] = {0}, mu[SEEDBYTES]; uint64_t sqnorm2; polyvecl A1[K], z1; polyveck b, highbits, h, z2, w; #if D > 0 polyveck a; #endif - poly c, wprime; + poly c, cprime, wprime; xof256_state state; @@ -339,7 +331,7 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, // Unpack signature and Check conditions -- A1 is used only as intermediate // buffer for the low bits - if (unpack_sig(c_seed, A1, &z1, &h, sig)) { + if (unpack_sig(&c, A1, &z1, &h, sig)) { return -1; } @@ -369,9 +361,6 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, } /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ - // c = challenge(c_seed) - poly_challenge(&c, c_seed); - // compute squared norm of z1 and w' before NTT sqnorm2 = polyvecl_sqnorm2(&z1); poly_sub(&wprime, &z1.vec[0], &c); @@ -410,16 +399,13 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); xof256_absorbe_twice(&state, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); - xof256_squeeze(c_seed2, SEEDBYTES, &state); + xof256_squeeze(mu, SEEDBYTES, &state); // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, buf, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, - c_seed2, SEEDBYTES); - xof256_squeeze(c_seed2, SEEDBYTES, &state); + poly_challenge(&cprime, buf, mu); - for (i = 0; i < SEEDBYTES; ++i) { - if (c_seed[i] != c_seed2[i]) { + for (i = 0; i < N; ++i) { + if (c.coeffs[i] != cprime.coeffs[i]) { return -1; } } diff --git a/crypto_sign/haetae2/clean/sign.h b/crypto_sign/haetae2/ref/sign.h similarity index 97% rename from crypto_sign/haetae2/clean/sign.h rename to crypto_sign/haetae2/ref/sign.h index 0515cab0..edfc0e80 100644 --- a/crypto_sign/haetae2/clean/sign.h +++ b/crypto_sign/haetae2/ref/sign.h @@ -27,4 +27,4 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, const uint8_t *pk); -#endif // HAETAE_SIGN_H \ No newline at end of file +#endif // HAETAE_SIGN_H diff --git a/crypto_sign/haetae2/clean/symmetric-shake.c b/crypto_sign/haetae2/ref/symmetric-shake.c similarity index 100% rename from crypto_sign/haetae2/clean/symmetric-shake.c rename to crypto_sign/haetae2/ref/symmetric-shake.c diff --git a/crypto_sign/haetae2/clean/symmetric.h b/crypto_sign/haetae2/ref/symmetric.h similarity index 100% rename from crypto_sign/haetae2/clean/symmetric.h rename to crypto_sign/haetae2/ref/symmetric.h From 8e19ad73264946ee99ba32be6c9c8e05b04eaacd Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 23 Nov 2023 17:07:07 +0800 Subject: [PATCH 033/107] add SPHINCS-alpha --- mupq | 2 +- skiplist.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 0abc3dfa..94cf8339 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 0abc3dfa42e966ebbd674da9db5967e7ca64f506 +Subproject commit 94cf833955d5687ca7b45b822a8fee8fc0dae27f diff --git a/skiplist.py b/skiplist.py index e6a81bce..0774ccf4 100644 --- a/skiplist.py +++ b/skiplist.py @@ -176,4 +176,16 @@ {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, + {'scheme': 'sphincs-a-shake-192s', 'implementation': 'ref', 'estmemory': 1306624}, + {'scheme': 'sphincs-a-sha2-256f', 'implementation': 'ref', 'estmemory': 1124352}, + {'scheme': 'sphincs-a-sha2-128s', 'implementation': 'ref', 'estmemory': 595968}, + {'scheme': 'sphincs-a-shake-256s', 'implementation': 'ref', 'estmemory': 2291712}, + {'scheme': 'sphincs-a-shake-128f', 'implementation': 'ref', 'estmemory': 301056}, + {'scheme': 'sphincs-a-sha2-192f', 'implementation': 'ref', 'estmemory': 542720}, + {'scheme': 'sphincs-a-sha2-192s', 'implementation': 'ref', 'estmemory': 1307648}, + {'scheme': 'sphincs-a-shake-128s', 'implementation': 'ref', 'estmemory': 595968}, + {'scheme': 'sphincs-a-shake-192f', 'implementation': 'ref', 'estmemory': 541696}, + {'scheme': 'sphincs-a-sha2-256s', 'implementation': 'ref', 'estmemory': 2291712}, + {'scheme': 'sphincs-a-shake-256f', 'implementation': 'ref', 'estmemory': 1124352}, + {'scheme': 'sphincs-a-sha2-128f', 'implementation': 'ref', 'estmemory': 301056}, ] From 3bac10636cb49f80eecbe9e24dae813b6ea6d7ea Mon Sep 17 00:00:00 2001 From: Marc Date: Thu, 23 Nov 2023 10:44:48 +0100 Subject: [PATCH 034/107] Adds HAETAE This commit implements the post-quantum signature scheme HAETAE from https://eprint.iacr.org/2023/624 https://kpqc.cryptolab.co.kr/haetae The stack strategy can be selected in config.h by setting STACK_STRATEGY to the appropriate value (run "make clean" after the change). * 0 or undefined: Optimized for speed (default). * 1: Disable buffers for the polynomials of the verification key in crypto_sign_keypair() and crypto_sign(). This reduces speed, as the key needs to be recomputed after each rejection. * 2: In addition to 1, sample the hyperball in multiple passes, such that some intermediate values are computed on demand, rather than being buffered. This roughly doubles the runtime of crypto_sign(). --- crypto_sign/haetae2/ref/api.h | 6 - crypto_sign/haetae2/ref/config.h | 19 - crypto_sign/haetae2/ref/decompose.c | 69 -- crypto_sign/haetae2/ref/decompose.h | 16 - crypto_sign/haetae2/ref/encoding.c | 227 ------- crypto_sign/haetae2/ref/encoding.h | 17 - crypto_sign/haetae2/ref/fft.c | 231 ------- crypto_sign/haetae2/ref/fft.h | 19 - crypto_sign/haetae2/ref/fips202.c | 746 ---------------------- crypto_sign/haetae2/ref/fips202.h | 57 -- crypto_sign/haetae2/ref/fixpoint.c | 140 ---- crypto_sign/haetae2/ref/fixpoint.h | 126 ---- crypto_sign/haetae2/ref/ntt.c | 95 --- crypto_sign/haetae2/ref/ntt.h | 13 - crypto_sign/haetae2/ref/packing.c | 280 -------- crypto_sign/haetae2/ref/packing.h | 25 - crypto_sign/haetae2/ref/params.h | 116 ---- crypto_sign/haetae2/ref/poly.c | 659 ------------------- crypto_sign/haetae2/ref/poly.h | 80 --- crypto_sign/haetae2/ref/polyfix.c | 292 --------- crypto_sign/haetae2/ref/polyfix.h | 61 -- crypto_sign/haetae2/ref/polymat.c | 73 --- crypto_sign/haetae2/ref/polymat.h | 28 - crypto_sign/haetae2/ref/polyvec.c | 543 ---------------- crypto_sign/haetae2/ref/polyvec.h | 129 ---- crypto_sign/haetae2/ref/rans_byte.h | 333 ---------- crypto_sign/haetae2/ref/reduce.c | 92 --- crypto_sign/haetae2/ref/reduce.h | 28 - crypto_sign/haetae2/ref/sampler.c | 272 -------- crypto_sign/haetae2/ref/sampler.h | 21 - crypto_sign/haetae2/ref/sign.c | 453 ------------- crypto_sign/haetae2/ref/sign.h | 30 - crypto_sign/haetae2/ref/symmetric-shake.c | 38 -- crypto_sign/haetae2/ref/symmetric.h | 78 --- 34 files changed, 5412 deletions(-) delete mode 100644 crypto_sign/haetae2/ref/api.h delete mode 100644 crypto_sign/haetae2/ref/config.h delete mode 100644 crypto_sign/haetae2/ref/decompose.c delete mode 100644 crypto_sign/haetae2/ref/decompose.h delete mode 100644 crypto_sign/haetae2/ref/encoding.c delete mode 100644 crypto_sign/haetae2/ref/encoding.h delete mode 100644 crypto_sign/haetae2/ref/fft.c delete mode 100644 crypto_sign/haetae2/ref/fft.h delete mode 100644 crypto_sign/haetae2/ref/fips202.c delete mode 100644 crypto_sign/haetae2/ref/fips202.h delete mode 100644 crypto_sign/haetae2/ref/fixpoint.c delete mode 100644 crypto_sign/haetae2/ref/fixpoint.h delete mode 100644 crypto_sign/haetae2/ref/ntt.c delete mode 100644 crypto_sign/haetae2/ref/ntt.h delete mode 100644 crypto_sign/haetae2/ref/packing.c delete mode 100644 crypto_sign/haetae2/ref/packing.h delete mode 100644 crypto_sign/haetae2/ref/params.h delete mode 100644 crypto_sign/haetae2/ref/poly.c delete mode 100644 crypto_sign/haetae2/ref/poly.h delete mode 100644 crypto_sign/haetae2/ref/polyfix.c delete mode 100644 crypto_sign/haetae2/ref/polyfix.h delete mode 100644 crypto_sign/haetae2/ref/polymat.c delete mode 100644 crypto_sign/haetae2/ref/polymat.h delete mode 100644 crypto_sign/haetae2/ref/polyvec.c delete mode 100644 crypto_sign/haetae2/ref/polyvec.h delete mode 100644 crypto_sign/haetae2/ref/rans_byte.h delete mode 100644 crypto_sign/haetae2/ref/reduce.c delete mode 100644 crypto_sign/haetae2/ref/reduce.h delete mode 100644 crypto_sign/haetae2/ref/sampler.c delete mode 100644 crypto_sign/haetae2/ref/sampler.h delete mode 100644 crypto_sign/haetae2/ref/sign.c delete mode 100644 crypto_sign/haetae2/ref/sign.h delete mode 100644 crypto_sign/haetae2/ref/symmetric-shake.c delete mode 100644 crypto_sign/haetae2/ref/symmetric.h diff --git a/crypto_sign/haetae2/ref/api.h b/crypto_sign/haetae2/ref/api.h deleted file mode 100644 index 28d58fca..00000000 --- a/crypto_sign/haetae2/ref/api.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef API_H -#define API_H - -#include "sign.h" - -#endif diff --git a/crypto_sign/haetae2/ref/config.h b/crypto_sign/haetae2/ref/config.h deleted file mode 100644 index 52c9e87b..00000000 --- a/crypto_sign/haetae2/ref/config.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define HAETAE_MODE 2 - -#if HAETAE_MODE == 2 -#define CRYPTO_ALGNAME "HAETAE2" -#define HAETAE_NAMESPACETOP haetae2 -#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s -#elif HAETAE_MODE == 3 -#define CRYPTO_ALGNAME "HAETAE3" -#define HAETAE_NAMESPACETOP haetae3 -#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s -#elif HAETAE_MODE == 5 -#define CRYPTO_ALGNAME "HAETAE5" -#define HAETAE_NAMESPACETOP haetae5 -#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s -#endif -#endif diff --git a/crypto_sign/haetae2/ref/decompose.c b/crypto_sign/haetae2/ref/decompose.c deleted file mode 100644 index 467767e5..00000000 --- a/crypto_sign/haetae2/ref/decompose.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "decompose.h" -#include "params.h" -#include - -/************************************************* - * Name: decompose_z1 - * - * Description: For finite field element r, compute high and lowbits - * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. - * - * Arguments: - int32_t r: input element - * - int32_t *lowbits: pointer to output element lb - * - int32_t *highbits: pointer to output element hb - **************************************************/ -void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r) { - const int alpha = 256; // TODO magic numbers! - const int log_alpha = 8; - - int32_t lb, center; - uint32_t alpha_mask = alpha - 1; - - lb = r & alpha_mask; - center = ((alpha >> 1) - (lb + 1)) >> 31; // if lb >= HALF_ALPHA - lb -= alpha & center; - *lowbits = lb; - *highbits = (r + (alpha >> 1)) >> log_alpha; -} - -/************************************************* - * Name: decompose_hint - * - * Description: For finite field element r, compute highbits - * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. - * - * Arguments: - int32_t r: input element - * - int32_t *highbits: pointer to output element hb - **************************************************/ - -void decompose_hint(int32_t *highbits, const int32_t r) { - int32_t hb, edgecase; - - hb = (r + HALF_ALPHA_HINT) >> LOG_ALPHA_HINT; - edgecase = - ((DQ - 2) / ALPHA_HINT - (hb + 1)) >> 31; // if hb == (DQ-2)/ALPHA - hb -= (DQ - 2) / ALPHA_HINT & edgecase; // hb = 0 - - *highbits = hb; -} - -/************************************************* - * Name: decompose_vk - * - * Description: For finite field element a, compute a0, a1 such that - * a mod^+ Q = a1*2^D + a0 with -2^{D-1} <= a0 < 2^{D-1}. - * Assumes a to be standard representative. - * - * Arguments: - int32_t a: input element - * - int32_t *a0: pointer to output element a0 - * - * Returns a1 - **************************************************/ -int32_t decompose_vk(int32_t *a0, const int32_t a) { -#if D > 1 -#error "Only implemented for D = 1" -#endif - *a0 = a & 1; - *a0 -= ((a >> 1) & *a0) << 1; - return (a - *a0) >> 1; -} diff --git a/crypto_sign/haetae2/ref/decompose.h b/crypto_sign/haetae2/ref/decompose.h deleted file mode 100644 index 67146cf1..00000000 --- a/crypto_sign/haetae2/ref/decompose.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef HAETAE_ROUNDING_H -#define HAETAE_ROUNDING_H - -#include "params.h" -#include - -#define decompose_z1 HAETAE_NAMESPACE(decompose_z1) -void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r); - -#define decompose_hint HAETAE_NAMESPACE(decompose_hint) -void decompose_hint(int32_t *highbits, const int32_t r); - -#define decompose_vk HAETAE_NAMESPACE(decompose_vk) -int32_t decompose_vk(int32_t *a0, const int32_t a); - -#endif diff --git a/crypto_sign/haetae2/ref/encoding.c b/crypto_sign/haetae2/ref/encoding.c deleted file mode 100644 index ca6a182f..00000000 --- a/crypto_sign/haetae2/ref/encoding.c +++ /dev/null @@ -1,227 +0,0 @@ -#include "encoding.h" -#include "params.h" -#include "rans_byte.h" - -#include -#include -#include - -#define SCALE_BITS 10 -#define SCALE (1u << SCALE_BITS) - -#if HAETAE_MODE == 2 -#define M_H 13 -#define OFFSET_H 239 -#define M_HB_Z1 13 -#define OFFSET_HB_Z1 6 -static RansEncSymbol esyms_h[M_H] = {{801112064, -1416664605, 0, 642, 8}, {515899392, -2060187564, 382, 778, 7}, {136314880, -66076419, 628, 959, 6}, {14680064, -1840700269, 693, 1017, 2}, {2097152, -1, 1723, 1023, 0}, {2097152, -1, 1724, 1023, 0}, {2097152, -1, 1725, 1023, 0}, {2097152, -1, 1726, 1023, 0}, {2097152, -1, 1727, 1023, 0}, {2097152, -1, 1728, 1023, 0}, {14680064, -1840700269, 706, 1017, 2}, {136314880, -66076419, 713, 959, 6}, {515899392, -2060187564, 778, 778, 7}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 382}, {382, 246}, {628, 65}, {693, 7}, {700, 1}, {701, 1}, {702, 1}, {703, 1}, {704, 1}, {705, 1}, {706, 7}, {713, 65}, {778, 246}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {10485760, -858993459, 3, 1019, 2}, {121634816, -1925330167, 8, 966, 5}, {515899392, -2060187564, 66, 778, 7}, {834666496, -1532375266, 312, 626, 8}, {517996544, -2069235255, 710, 777, 7}, {123731968, -1965493508, 957, 965, 5}, {10485760, -858993459, 1016, 1019, 2}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 5}, {8, 58}, {66, 246}, {312, 398}, {710, 247}, {957, 59}, {1016, 5}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 11, 12, }; - -#elif HAETAE_MODE == 3 -#define M_H 17 -#define OFFSET_H 235 -#define M_HB_Z1 17 -#define OFFSET_HB_Z1 8 -static RansEncSymbol esyms_h[M_H] = {{557842432, -161464935, 0, 758, 8}, {446693376, -1713954085, 266, 811, 7}, {236978176, -1862419446, 479, 911, 6}, {83886080, -858993459, 592, 984, 5}, {18874368, -477218588, 632, 1015, 3}, {2097152, -1, 1664, 1023, 0}, {2097152, -1, 1665, 1023, 0}, {2097152, -1, 1666, 1023, 0}, {2097152, -1, 1667, 1023, 0}, {2097152, -1, 1668, 1023, 0}, {2097152, -1, 1669, 1023, 0}, {2097152, -1, 1670, 1023, 0}, {2097152, -1, 1671, 1023, 0}, {18874368, -477218588, 649, 1015, 3}, {83886080, -858993459, 658, 984, 5}, {236978176, -1862419446, 698, 911, 6}, {446693376, -1713954085, 811, 811, 7}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 266}, {266, 213}, {479, 113}, {592, 40}, {632, 9}, {641, 1}, {642, 1}, {643, 1}, {644, 1}, {645, 1}, {646, 1}, {647, 1}, {648, 1}, {649, 9}, {658, 40}, {698, 113}, {811, 213}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {16777216, -2147483648, 4, 1016, 2}, {77594624, -580400985, 12, 987, 5}, {234881024, -1840700269, 49, 912, 6}, {452984832, -1749801490, 161, 808, 7}, {564133888, -207563475, 377, 755, 8}, {452984832, -1749801490, 646, 808, 7}, {234881024, -1840700269, 862, 912, 6}, {79691776, -678152730, 974, 986, 5}, {16777216, -2147483648, 1012, 1016, 2}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 8}, {12, 37}, {49, 112}, {161, 216}, {377, 269}, {646, 216}, {862, 112}, {974, 38}, {1012, 8}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, }; - -#elif HAETAE_MODE == 5 -#define M_H 33 -#define OFFSET_H 471 -#define M_HB_Z1 19 -#define OFFSET_HB_Z1 9 -static RansEncSymbol esyms_h[M_H] = {{255852544, -2041869698, 0, 902, 6}, {245366784, -1945583475, 122, 907, 6}, {213909504, -1600085855, 239, 922, 6}, {169869312, -901412889, 341, 943, 6}, {123731968, -1965493508, 422, 965, 5}, {81788928, -770891565, 481, 985, 5}, {48234496, -1307163959, 520, 1001, 4}, {27262976, -1651910498, 543, 1011, 3}, {12582912, -1431655765, 556, 1018, 2}, {6291456, -1431655765, 562, 1021, 1}, {2097152, -1, 1588, 1023, 0}, {2097152, -1, 1589, 1023, 0}, {2097152, -1, 1590, 1023, 0}, {2097152, -1, 1591, 1023, 0}, {2097152, -1, 1592, 1023, 0}, {2097152, -1, 1593, 1023, 0}, {2097152, -1, 1594, 1023, 0}, {2097152, -1, 1595, 1023, 0}, {2097152, -1, 1596, 1023, 0}, {2097152, -1, 1597, 1023, 0}, {2097152, -1, 1598, 1023, 0}, {2097152, -1, 1599, 1023, 0}, {2097152, -1, 1600, 1023, 0}, {2097152, -1, 1601, 1023, 0}, {6291456, -1431655765, 579, 1021, 1}, {12582912, -1431655765, 582, 1018, 2}, {27262976, -1651910498, 588, 1011, 3}, {50331648, -1431655765, 601, 1000, 4}, {81788928, -770891565, 625, 985, 5}, {123731968, -1965493508, 664, 965, 5}, {169869312, -901412889, 723, 943, 6}, {213909504, -1600085855, 804, 922, 6}, {247463936, -1965493508, 906, 906, 6}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 122}, {122, 117}, {239, 102}, {341, 81}, {422, 59}, {481, 39}, {520, 23}, {543, 13}, {556, 6}, {562, 3}, {565, 1}, {566, 1}, {567, 1}, {568, 1}, {569, 1}, {570, 1}, {571, 1}, {572, 1}, {573, 1}, {574, 1}, {575, 1}, {576, 1}, {577, 1}, {578, 1}, {579, 3}, {582, 6}, {588, 13}, {601, 24}, {625, 39}, {664, 59}, {723, 81}, {804, 102}, {906, 118}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {4194304, -2147483648, 4, 1022, 0}, {27262976, -1651910498, 6, 1011, 3}, {100663296, -1431655765, 19, 976, 5}, {247463936, -1965493508, 67, 906, 6}, {427819008, -1600085855, 185, 820, 7}, {513802240, -2051066014, 389, 779, 7}, {427819008, -1600085855, 634, 820, 7}, {247463936, -1965493508, 838, 906, 6}, {100663296, -1431655765, 956, 976, 5}, {29360128, -1840700269, 1004, 1010, 3}, {4194304, -2147483648, 1018, 1022, 0}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 2}, {6, 13}, {19, 48}, {67, 118}, {185, 204}, {389, 245}, {634, 204}, {838, 118}, {956, 48}, {1004, 14}, {1018, 2}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 15, 16, 17, 18, }; - -#endif // HAETAE_MODE -#define H_CUT ((M_H -1) >>1) - -/************************************************* - * Name: encode_h - * - * Description: rANS encode polynomial vector h - * - * Arguments: - uint8_t *buf: pointer to output buffer - * - const int32_t *h: pointer to polynomial vector h - **************************************************/ -uint16_t encode_h(uint8_t *buf, const int32_t *h) { - size_t size_encoded; - RansState rans; - uint8_t *ptr; - size_t size_h = N * K; - uint32_t tmp; - uint8_t s; - uint8_t encoding[size_h]; // size_h is a loose upper bound - - RansEncInit(&rans); - ptr = encoding + size_h; // end of encoding buffer - - for (size_t i = size_h; i > 0; i--) { - tmp = h[i - 1]; - // check for very unlikely values that we do not encode - // to make the encoding cheaper : - if(H_CUT < tmp && tmp <= H_CUT + OFFSET_H) { - return 0; - } - // map the upper likely part of symbols next to the lower part - // to have a dense and compact distribution: - tmp = (tmp > (H_CUT + OFFSET_H)) ? tmp - OFFSET_H : tmp; - s = (uint8_t) tmp; - - RansEncPutSymbol(&rans, &ptr, &esyms_h[s]); - // check that at least 4 byte remain for memory safety: - if (ptr < encoding + 4) - { - return 0; - } - } - - RansEncFlush(&rans, &ptr); - - size_encoded = encoding + size_h - ptr; - memcpy(buf, ptr, size_encoded); - return size_encoded; -} - -/************************************************* - * Name: decode_h - * - * Description: rANS decode polynomial vector h - * - * Arguments: - int32_t *h: pointer to polynomial vector h - * - uint8_t *buf: pointer to output buffer - **************************************************/ -uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in) { - size_t size_used; - RansState rans; - size_t size_h = N * K; - uint32_t tmp; - uint8_t s; - const uint8_t *buf_start = buf; - const uint8_t *buf_end = buf + size_in; - - if(RansDecInit(&rans, (uint8_t **) &buf)) { - return 1; // corrupted initial state - } - - for (size_t i = 0; i < size_h; i++) { - s = symbol_h[RansDecGet(&rans, SCALE_BITS)]; - tmp = (uint32_t) s; - if(tmp >= M_H) { - return 1; // invalid symbol - } - tmp = (H_CUT < tmp) ? (tmp + OFFSET_H) : tmp; - h[i] = tmp; - RansDecAdvanceSymbol(&rans, (uint8_t **) &buf, buf_end, &dsyms_h[s], SCALE_BITS); - } - - if(RansDecVerify(&rans)) { - return 1; // final state not correct - } - - size_used = buf - buf_start; - if(size_used != size_in) { - return 1; // size does not match - } - return 0; -} - -/************************************************* - * Name: encode_hb_z1 - * - * Description: rANS encode polynomial vector HighBits(z1) - * - * Arguments: - uint8_t *buf: pointer to output buffer - * - const int32_t *hb_z1: pointer to polynomial vector - *HighBits(z1) - **************************************************/ -uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1) { - size_t size_encoded; - RansState rans; - uint8_t *ptr; - size_t size_hb_z1 = N * L; - int8_t s; - int32_t tmp; - uint8_t encoding[size_hb_z1]; // size_hb_z1 is a loose upper bound - - RansEncInit(&rans); - ptr = encoding + size_hb_z1; // end of output buffer - - for (size_t i = size_hb_z1; i > 0; i--) { - // from centered to positive representation: - tmp = hb_z1[i - 1] + OFFSET_HB_Z1; - // check for very unlikely values that we do not encode - // to make the encoding cheaper : - if(tmp < 0 || M_HB_Z1 <= tmp) { - return 0; - } - s = (uint8_t) tmp; - - RansEncPutSymbol(&rans, &ptr, &esyms_hb_z1[s]); - // check that at least 4 byte remain for memory safety: - if (ptr < encoding + 4) - { - return 0; - } - } - RansEncFlush(&rans, &ptr); - - size_encoded = encoding + size_hb_z1 - ptr; - memcpy(buf, ptr, size_encoded); - return size_encoded; -} - -/************************************************* - * Name: decode_hb_z1 - * - * Description: rANS decode polynomial vector HighBits(z1) - * - * Arguments: - int32_t *hb_z1: pointer to polynomial vector HighBits(z1) - * - uint8_t *buf: pointer to output buffer - **************************************************/ -uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in) { - size_t size_used; - RansState rans; - size_t size_hb_z1 = N * L; - uint32_t tmp; - uint8_t s; - const uint8_t *buf_start = buf; - const uint8_t *buf_end = buf + size_in; - - if(RansDecInit(&rans, (uint8_t **) &buf)) { - return 1; // corrupted initial state - } - - for (size_t i = 0; i < size_hb_z1; i++) { - s = symbol_hb_z1[RansDecGet(&rans, SCALE_BITS)]; - tmp = (uint32_t) s; - if(tmp >= M_HB_Z1) { - return 1; // invalid symbol - } - // from positive to centered representation: - hb_z1[i] = tmp - OFFSET_HB_Z1; - RansDecAdvanceSymbol(&rans, (uint8_t **)&buf, buf_end, &dsyms_hb_z1[s], SCALE_BITS); - } - - if(RansDecVerify(&rans)) { - return 1; // final state not correct - } - - size_used = buf - buf_start; - if(size_used != size_in) { - return 1; // size does not match - } - return 0; -} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/encoding.h b/crypto_sign/haetae2/ref/encoding.h deleted file mode 100644 index b1e6239d..00000000 --- a/crypto_sign/haetae2/ref/encoding.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HAETAE_ENCODING_H -#define HAETAE_ENCODING_H - -#include "params.h" -#include -#include - -#define encode_h HAETAE_NAMESPACE(encode_h) -uint16_t encode_h(uint8_t *buf, const int32_t *h); -#define decode_h HAETAE_NAMESPACE(decode_h) -uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in); -#define encode_hb_z1 HAETAE_NAMESPACE(encode_hb_z1) -uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1); -#define decode_hb_z1 HAETAE_NAMESPACE(decode_hb_z1) -uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in); - -#endif // HAETAE_ENCODING_H diff --git a/crypto_sign/haetae2/ref/fft.c b/crypto_sign/haetae2/ref/fft.c deleted file mode 100644 index f625ad79..00000000 --- a/crypto_sign/haetae2/ref/fft.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "fft.h" - -static const complex_fp32_16 roots[] = { - {.real = +65536L, .imag = +0L}, {.real = +65531L, .imag = -804L}, - {.real = +65516L, .imag = -1608L}, {.real = +65492L, .imag = -2412L}, - {.real = +65457L, .imag = -3216L}, {.real = +65413L, .imag = -4019L}, - {.real = +65358L, .imag = -4821L}, {.real = +65294L, .imag = -5623L}, - {.real = +65220L, .imag = -6424L}, {.real = +65137L, .imag = -7224L}, - {.real = +65043L, .imag = -8022L}, {.real = +64940L, .imag = -8820L}, - {.real = +64827L, .imag = -9616L}, {.real = +64704L, .imag = -10411L}, - {.real = +64571L, .imag = -11204L}, {.real = +64429L, .imag = -11996L}, - {.real = +64277L, .imag = -12785L}, {.real = +64115L, .imag = -13573L}, - {.real = +63944L, .imag = -14359L}, {.real = +63763L, .imag = -15143L}, - {.real = +63572L, .imag = -15924L}, {.real = +63372L, .imag = -16703L}, - {.real = +63162L, .imag = -17479L}, {.real = +62943L, .imag = -18253L}, - {.real = +62714L, .imag = -19024L}, {.real = +62476L, .imag = -19792L}, - {.real = +62228L, .imag = -20557L}, {.real = +61971L, .imag = -21320L}, - {.real = +61705L, .imag = -22078L}, {.real = +61429L, .imag = -22834L}, - {.real = +61145L, .imag = -23586L}, {.real = +60851L, .imag = -24335L}, - {.real = +60547L, .imag = -25080L}, {.real = +60235L, .imag = -25821L}, - {.real = +59914L, .imag = -26558L}, {.real = +59583L, .imag = -27291L}, - {.real = +59244L, .imag = -28020L}, {.real = +58896L, .imag = -28745L}, - {.real = +58538L, .imag = -29466L}, {.real = +58172L, .imag = -30182L}, - {.real = +57798L, .imag = -30893L}, {.real = +57414L, .imag = -31600L}, - {.real = +57022L, .imag = -32303L}, {.real = +56621L, .imag = -33000L}, - {.real = +56212L, .imag = -33692L}, {.real = +55794L, .imag = -34380L}, - {.real = +55368L, .imag = -35062L}, {.real = +54934L, .imag = -35738L}, - {.real = +54491L, .imag = -36410L}, {.real = +54040L, .imag = -37076L}, - {.real = +53581L, .imag = -37736L}, {.real = +53114L, .imag = -38391L}, - {.real = +52639L, .imag = -39040L}, {.real = +52156L, .imag = -39683L}, - {.real = +51665L, .imag = -40320L}, {.real = +51166L, .imag = -40951L}, - {.real = +50660L, .imag = -41576L}, {.real = +50146L, .imag = -42194L}, - {.real = +49624L, .imag = -42806L}, {.real = +49095L, .imag = -43412L}, - {.real = +48559L, .imag = -44011L}, {.real = +48015L, .imag = -44604L}, - {.real = +47464L, .imag = -45190L}, {.real = +46906L, .imag = -45769L}, - {.real = +46341L, .imag = -46341L}, {.real = +45769L, .imag = -46906L}, - {.real = +45190L, .imag = -47464L}, {.real = +44604L, .imag = -48015L}, - {.real = +44011L, .imag = -48559L}, {.real = +43412L, .imag = -49095L}, - {.real = +42806L, .imag = -49624L}, {.real = +42194L, .imag = -50146L}, - {.real = +41576L, .imag = -50660L}, {.real = +40951L, .imag = -51166L}, - {.real = +40320L, .imag = -51665L}, {.real = +39683L, .imag = -52156L}, - {.real = +39040L, .imag = -52639L}, {.real = +38391L, .imag = -53114L}, - {.real = +37736L, .imag = -53581L}, {.real = +37076L, .imag = -54040L}, - {.real = +36410L, .imag = -54491L}, {.real = +35738L, .imag = -54934L}, - {.real = +35062L, .imag = -55368L}, {.real = +34380L, .imag = -55794L}, - {.real = +33692L, .imag = -56212L}, {.real = +33000L, .imag = -56621L}, - {.real = +32303L, .imag = -57022L}, {.real = +31600L, .imag = -57414L}, - {.real = +30893L, .imag = -57798L}, {.real = +30182L, .imag = -58172L}, - {.real = +29466L, .imag = -58538L}, {.real = +28745L, .imag = -58896L}, - {.real = +28020L, .imag = -59244L}, {.real = +27291L, .imag = -59583L}, - {.real = +26558L, .imag = -59914L}, {.real = +25821L, .imag = -60235L}, - {.real = +25080L, .imag = -60547L}, {.real = +24335L, .imag = -60851L}, - {.real = +23586L, .imag = -61145L}, {.real = +22834L, .imag = -61429L}, - {.real = +22078L, .imag = -61705L}, {.real = +21320L, .imag = -61971L}, - {.real = +20557L, .imag = -62228L}, {.real = +19792L, .imag = -62476L}, - {.real = +19024L, .imag = -62714L}, {.real = +18253L, .imag = -62943L}, - {.real = +17479L, .imag = -63162L}, {.real = +16703L, .imag = -63372L}, - {.real = +15924L, .imag = -63572L}, {.real = +15143L, .imag = -63763L}, - {.real = +14359L, .imag = -63944L}, {.real = +13573L, .imag = -64115L}, - {.real = +12785L, .imag = -64277L}, {.real = +11996L, .imag = -64429L}, - {.real = +11204L, .imag = -64571L}, {.real = +10411L, .imag = -64704L}, - {.real = +9616L, .imag = -64827L}, {.real = +8820L, .imag = -64940L}, - {.real = +8022L, .imag = -65043L}, {.real = +7224L, .imag = -65137L}, - {.real = +6424L, .imag = -65220L}, {.real = +5623L, .imag = -65294L}, - {.real = +4821L, .imag = -65358L}, {.real = +4019L, .imag = -65413L}, - {.real = +3216L, .imag = -65457L}, {.real = +2412L, .imag = -65492L}, - {.real = +1608L, .imag = -65516L}, {.real = +804L, .imag = -65531L}, - {.real = +0L, .imag = -65536L}, {.real = -804L, .imag = -65531L}, - {.real = -1608L, .imag = -65516L}, {.real = -2412L, .imag = -65492L}, - {.real = -3216L, .imag = -65457L}, {.real = -4019L, .imag = -65413L}, - {.real = -4821L, .imag = -65358L}, {.real = -5623L, .imag = -65294L}, - {.real = -6424L, .imag = -65220L}, {.real = -7224L, .imag = -65137L}, - {.real = -8022L, .imag = -65043L}, {.real = -8820L, .imag = -64940L}, - {.real = -9616L, .imag = -64827L}, {.real = -10411L, .imag = -64704L}, - {.real = -11204L, .imag = -64571L}, {.real = -11996L, .imag = -64429L}, - {.real = -12785L, .imag = -64277L}, {.real = -13573L, .imag = -64115L}, - {.real = -14359L, .imag = -63944L}, {.real = -15143L, .imag = -63763L}, - {.real = -15924L, .imag = -63572L}, {.real = -16703L, .imag = -63372L}, - {.real = -17479L, .imag = -63162L}, {.real = -18253L, .imag = -62943L}, - {.real = -19024L, .imag = -62714L}, {.real = -19792L, .imag = -62476L}, - {.real = -20557L, .imag = -62228L}, {.real = -21320L, .imag = -61971L}, - {.real = -22078L, .imag = -61705L}, {.real = -22834L, .imag = -61429L}, - {.real = -23586L, .imag = -61145L}, {.real = -24335L, .imag = -60851L}, - {.real = -25080L, .imag = -60547L}, {.real = -25821L, .imag = -60235L}, - {.real = -26558L, .imag = -59914L}, {.real = -27291L, .imag = -59583L}, - {.real = -28020L, .imag = -59244L}, {.real = -28745L, .imag = -58896L}, - {.real = -29466L, .imag = -58538L}, {.real = -30182L, .imag = -58172L}, - {.real = -30893L, .imag = -57798L}, {.real = -31600L, .imag = -57414L}, - {.real = -32303L, .imag = -57022L}, {.real = -33000L, .imag = -56621L}, - {.real = -33692L, .imag = -56212L}, {.real = -34380L, .imag = -55794L}, - {.real = -35062L, .imag = -55368L}, {.real = -35738L, .imag = -54934L}, - {.real = -36410L, .imag = -54491L}, {.real = -37076L, .imag = -54040L}, - {.real = -37736L, .imag = -53581L}, {.real = -38391L, .imag = -53114L}, - {.real = -39040L, .imag = -52639L}, {.real = -39683L, .imag = -52156L}, - {.real = -40320L, .imag = -51665L}, {.real = -40951L, .imag = -51166L}, - {.real = -41576L, .imag = -50660L}, {.real = -42194L, .imag = -50146L}, - {.real = -42806L, .imag = -49624L}, {.real = -43412L, .imag = -49095L}, - {.real = -44011L, .imag = -48559L}, {.real = -44604L, .imag = -48015L}, - {.real = -45190L, .imag = -47464L}, {.real = -45769L, .imag = -46906L}, - {.real = -46341L, .imag = -46341L}, {.real = -46906L, .imag = -45769L}, - {.real = -47464L, .imag = -45190L}, {.real = -48015L, .imag = -44604L}, - {.real = -48559L, .imag = -44011L}, {.real = -49095L, .imag = -43412L}, - {.real = -49624L, .imag = -42806L}, {.real = -50146L, .imag = -42194L}, - {.real = -50660L, .imag = -41576L}, {.real = -51166L, .imag = -40951L}, - {.real = -51665L, .imag = -40320L}, {.real = -52156L, .imag = -39683L}, - {.real = -52639L, .imag = -39040L}, {.real = -53114L, .imag = -38391L}, - {.real = -53581L, .imag = -37736L}, {.real = -54040L, .imag = -37076L}, - {.real = -54491L, .imag = -36410L}, {.real = -54934L, .imag = -35738L}, - {.real = -55368L, .imag = -35062L}, {.real = -55794L, .imag = -34380L}, - {.real = -56212L, .imag = -33692L}, {.real = -56621L, .imag = -33000L}, - {.real = -57022L, .imag = -32303L}, {.real = -57414L, .imag = -31600L}, - {.real = -57798L, .imag = -30893L}, {.real = -58172L, .imag = -30182L}, - {.real = -58538L, .imag = -29466L}, {.real = -58896L, .imag = -28745L}, - {.real = -59244L, .imag = -28020L}, {.real = -59583L, .imag = -27291L}, - {.real = -59914L, .imag = -26558L}, {.real = -60235L, .imag = -25821L}, - {.real = -60547L, .imag = -25080L}, {.real = -60851L, .imag = -24335L}, - {.real = -61145L, .imag = -23586L}, {.real = -61429L, .imag = -22834L}, - {.real = -61705L, .imag = -22078L}, {.real = -61971L, .imag = -21320L}, - {.real = -62228L, .imag = -20557L}, {.real = -62476L, .imag = -19792L}, - {.real = -62714L, .imag = -19024L}, {.real = -62943L, .imag = -18253L}, - {.real = -63162L, .imag = -17479L}, {.real = -63372L, .imag = -16703L}, - {.real = -63572L, .imag = -15924L}, {.real = -63763L, .imag = -15143L}, - {.real = -63944L, .imag = -14359L}, {.real = -64115L, .imag = -13573L}, - {.real = -64277L, .imag = -12785L}, {.real = -64429L, .imag = -11996L}, - {.real = -64571L, .imag = -11204L}, {.real = -64704L, .imag = -10411L}, - {.real = -64827L, .imag = -9616L}, {.real = -64940L, .imag = -8820L}, - {.real = -65043L, .imag = -8022L}, {.real = -65137L, .imag = -7224L}, - {.real = -65220L, .imag = -6424L}, {.real = -65294L, .imag = -5623L}, - {.real = -65358L, .imag = -4821L}, {.real = -65413L, .imag = -4019L}, - {.real = -65457L, .imag = -3216L}, {.real = -65492L, .imag = -2412L}, - {.real = -65516L, .imag = -1608L}, {.real = -65531L, .imag = -804L}}; - -static inline int32_t _mulrnd16(const int32_t x, const int32_t y) { - int64_t r = ((int64_t)x * (int64_t)y) + (1 << 15); - return r >> 16; -} - -static inline int32_t _complex_mul_real(const complex_fp32_16 x, - const complex_fp32_16 y) { - return _mulrnd16(x.real, y.real) - _mulrnd16(x.imag, y.imag); -} - -static inline int32_t _complex_mul_imag(const complex_fp32_16 x, - const complex_fp32_16 y) { - return _mulrnd16(x.real, y.imag) + _mulrnd16(x.imag, y.real); -} - -static void _complex_mul(complex_fp32_16 *r, const complex_fp32_16 x, - const complex_fp32_16 y) { - r->real = _complex_mul_real(x, y); - r->imag = _complex_mul_imag(x, y); -} - -const uint16_t brv9[] = { - 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, - 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, - 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, - 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, - 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, - 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, - 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, - 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, - 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, - 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, - 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, - 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, - 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, - 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, - 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, - 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, - 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, - 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, - 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, - 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, - 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, - 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, - 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, - 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, - 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, - 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, - 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, - 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, - 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, - 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 263, - 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, - 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, - 15, 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, - 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, - 255, 511}; - -void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x) { - int i, inv_i; - for (i = 0; i < N; i++) { - inv_i = brv9[i]; - r[inv_i].imag = 0; - r[inv_i].real = x->coeffs[i] << 16; - } - for (i = N; i < FFT_N; i++) { - inv_i = brv9[i]; - r[inv_i].imag = 0; - r[inv_i].real = 0; - } -} - -int32_t complex_fp_sqabs(complex_fp32_16 x) { - return _mulrnd16(x.real, x.real) + _mulrnd16(x.imag, x.imag); -} - -void fft(complex_fp32_16 data[FFT_N]) { - unsigned int r, m, md2, n, k, even, odd, twid; - complex_fp32_16 u, t; - - for (r = 1; r <= FFT_LOGN; r++) { - m = 1 << r; - md2 = m >> 1; - for (n = 0; n < FFT_N; n += m) { - for (k = 0; k < md2; k++) { - even = n + k; - odd = even + md2; - twid = k << (FFT_LOGN - r); - - u = data[even]; - _complex_mul(&t, roots[twid], data[odd]); - data[even].real = u.real + t.real; - data[even].imag = u.imag + t.imag; - data[odd].real = u.real - t.real; - data[odd].imag = u.imag - t.imag; - } - } - } -} diff --git a/crypto_sign/haetae2/ref/fft.h b/crypto_sign/haetae2/ref/fft.h deleted file mode 100644 index 46a365ce..00000000 --- a/crypto_sign/haetae2/ref/fft.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FFT__H -#define FFT__H - -#include "poly.h" -#include - -#define FFT_N 512 -#define FFT_LOGN 9 - -typedef struct { - int32_t real; - int32_t imag; -} complex_fp32_16; - -void fft(complex_fp32_16 data[FFT_N]); -void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x); -int32_t complex_fp_sqabs(complex_fp32_16 x); - -#endif diff --git a/crypto_sign/haetae2/ref/fips202.c b/crypto_sign/haetae2/ref/fips202.c deleted file mode 100644 index e0ec2668..00000000 --- a/crypto_sign/haetae2/ref/fips202.c +++ /dev/null @@ -1,746 +0,0 @@ -/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ - * from http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public - * domain "TweetFips202" implementation from https://twitter.com/tweetfips202 by - * Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ - -#include "fips202.h" -#include -#include - -#define NROUNDS 24 -#define ROL(a, offset) ((a << offset) ^ (a >> (64 - offset))) - -/************************************************* - * Name: load64 - * - * Description: Load 8 bytes into uint64_t in little-endian order - * - * Arguments: - const uint8_t *x: pointer to input byte array - * - * Returns the loaded 64-bit unsigned integer - **************************************************/ -static uint64_t load64(const uint8_t x[8]) { - unsigned int i; - uint64_t r = 0; - - for (i = 0; i < 8; ++i) - r |= (uint64_t)x[i] << 8 * i; - - return r; -} - -/************************************************* - * Name: store64 - * - * Description: Store a 64-bit integer to array of 8 bytes in little-endian - *order - * - * Arguments: - uint8_t *x: pointer to the output byte array (allocated) - * - uint64_t u: input 64-bit unsigned integer - **************************************************/ -static void store64(uint8_t x[8], uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) - x[i] = u >> 8 * i; -} - -/* Keccak round constants */ -const uint64_t KeccakF_RoundConstants[NROUNDS] = { - (uint64_t)0x0000000000000001ULL, (uint64_t)0x0000000000008082ULL, - (uint64_t)0x800000000000808aULL, (uint64_t)0x8000000080008000ULL, - (uint64_t)0x000000000000808bULL, (uint64_t)0x0000000080000001ULL, - (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008009ULL, - (uint64_t)0x000000000000008aULL, (uint64_t)0x0000000000000088ULL, - (uint64_t)0x0000000080008009ULL, (uint64_t)0x000000008000000aULL, - (uint64_t)0x000000008000808bULL, (uint64_t)0x800000000000008bULL, - (uint64_t)0x8000000000008089ULL, (uint64_t)0x8000000000008003ULL, - (uint64_t)0x8000000000008002ULL, (uint64_t)0x8000000000000080ULL, - (uint64_t)0x000000000000800aULL, (uint64_t)0x800000008000000aULL, - (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008080ULL, - (uint64_t)0x0000000080000001ULL, (uint64_t)0x8000000080008008ULL}; - -/************************************************* - * Name: KeccakF1600_StatePermute - * - * Description: The Keccak F1600 Permutation - * - * Arguments: - uint64_t *state: pointer to input/output Keccak state - **************************************************/ -static void KeccakF1600_StatePermute(uint64_t state[25]) { - int round; - - uint64_t Aba, Abe, Abi, Abo, Abu; - uint64_t Aga, Age, Agi, Ago, Agu; - uint64_t Aka, Ake, Aki, Ako, Aku; - uint64_t Ama, Ame, Ami, Amo, Amu; - uint64_t Asa, Ase, Asi, Aso, Asu; - uint64_t BCa, BCe, BCi, BCo, BCu; - uint64_t Da, De, Di, Do, Du; - uint64_t Eba, Ebe, Ebi, Ebo, Ebu; - uint64_t Ega, Ege, Egi, Ego, Egu; - uint64_t Eka, Eke, Eki, Eko, Eku; - uint64_t Ema, Eme, Emi, Emo, Emu; - uint64_t Esa, Ese, Esi, Eso, Esu; - - // copyFromState(A, state) - Aba = state[0]; - Abe = state[1]; - Abi = state[2]; - Abo = state[3]; - Abu = state[4]; - Aga = state[5]; - Age = state[6]; - Agi = state[7]; - Ago = state[8]; - Agu = state[9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for (round = 0; round < NROUNDS; round += 2) { - // prepareTheta - BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; - BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; - BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; - BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; - BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; - - // thetaRhoPiChiIotaPrepareTheta(round, A, E) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Aba ^= Da; - BCa = Aba; - Age ^= De; - BCe = ROL(Age, 44); - Aki ^= Di; - BCi = ROL(Aki, 43); - Amo ^= Do; - BCo = ROL(Amo, 21); - Asu ^= Du; - BCu = ROL(Asu, 14); - Eba = BCa ^ ((~BCe) & BCi); - Eba ^= (uint64_t)KeccakF_RoundConstants[round]; - Ebe = BCe ^ ((~BCi) & BCo); - Ebi = BCi ^ ((~BCo) & BCu); - Ebo = BCo ^ ((~BCu) & BCa); - Ebu = BCu ^ ((~BCa) & BCe); - - Abo ^= Do; - BCa = ROL(Abo, 28); - Agu ^= Du; - BCe = ROL(Agu, 20); - Aka ^= Da; - BCi = ROL(Aka, 3); - Ame ^= De; - BCo = ROL(Ame, 45); - Asi ^= Di; - BCu = ROL(Asi, 61); - Ega = BCa ^ ((~BCe) & BCi); - Ege = BCe ^ ((~BCi) & BCo); - Egi = BCi ^ ((~BCo) & BCu); - Ego = BCo ^ ((~BCu) & BCa); - Egu = BCu ^ ((~BCa) & BCe); - - Abe ^= De; - BCa = ROL(Abe, 1); - Agi ^= Di; - BCe = ROL(Agi, 6); - Ako ^= Do; - BCi = ROL(Ako, 25); - Amu ^= Du; - BCo = ROL(Amu, 8); - Asa ^= Da; - BCu = ROL(Asa, 18); - Eka = BCa ^ ((~BCe) & BCi); - Eke = BCe ^ ((~BCi) & BCo); - Eki = BCi ^ ((~BCo) & BCu); - Eko = BCo ^ ((~BCu) & BCa); - Eku = BCu ^ ((~BCa) & BCe); - - Abu ^= Du; - BCa = ROL(Abu, 27); - Aga ^= Da; - BCe = ROL(Aga, 36); - Ake ^= De; - BCi = ROL(Ake, 10); - Ami ^= Di; - BCo = ROL(Ami, 15); - Aso ^= Do; - BCu = ROL(Aso, 56); - Ema = BCa ^ ((~BCe) & BCi); - Eme = BCe ^ ((~BCi) & BCo); - Emi = BCi ^ ((~BCo) & BCu); - Emo = BCo ^ ((~BCu) & BCa); - Emu = BCu ^ ((~BCa) & BCe); - - Abi ^= Di; - BCa = ROL(Abi, 62); - Ago ^= Do; - BCe = ROL(Ago, 55); - Aku ^= Du; - BCi = ROL(Aku, 39); - Ama ^= Da; - BCo = ROL(Ama, 41); - Ase ^= De; - BCu = ROL(Ase, 2); - Esa = BCa ^ ((~BCe) & BCi); - Ese = BCe ^ ((~BCi) & BCo); - Esi = BCi ^ ((~BCo) & BCu); - Eso = BCo ^ ((~BCu) & BCa); - Esu = BCu ^ ((~BCa) & BCe); - - // prepareTheta - BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; - BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; - BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; - BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; - BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; - - // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Eba ^= Da; - BCa = Eba; - Ege ^= De; - BCe = ROL(Ege, 44); - Eki ^= Di; - BCi = ROL(Eki, 43); - Emo ^= Do; - BCo = ROL(Emo, 21); - Esu ^= Du; - BCu = ROL(Esu, 14); - Aba = BCa ^ ((~BCe) & BCi); - Aba ^= (uint64_t)KeccakF_RoundConstants[round + 1]; - Abe = BCe ^ ((~BCi) & BCo); - Abi = BCi ^ ((~BCo) & BCu); - Abo = BCo ^ ((~BCu) & BCa); - Abu = BCu ^ ((~BCa) & BCe); - - Ebo ^= Do; - BCa = ROL(Ebo, 28); - Egu ^= Du; - BCe = ROL(Egu, 20); - Eka ^= Da; - BCi = ROL(Eka, 3); - Eme ^= De; - BCo = ROL(Eme, 45); - Esi ^= Di; - BCu = ROL(Esi, 61); - Aga = BCa ^ ((~BCe) & BCi); - Age = BCe ^ ((~BCi) & BCo); - Agi = BCi ^ ((~BCo) & BCu); - Ago = BCo ^ ((~BCu) & BCa); - Agu = BCu ^ ((~BCa) & BCe); - - Ebe ^= De; - BCa = ROL(Ebe, 1); - Egi ^= Di; - BCe = ROL(Egi, 6); - Eko ^= Do; - BCi = ROL(Eko, 25); - Emu ^= Du; - BCo = ROL(Emu, 8); - Esa ^= Da; - BCu = ROL(Esa, 18); - Aka = BCa ^ ((~BCe) & BCi); - Ake = BCe ^ ((~BCi) & BCo); - Aki = BCi ^ ((~BCo) & BCu); - Ako = BCo ^ ((~BCu) & BCa); - Aku = BCu ^ ((~BCa) & BCe); - - Ebu ^= Du; - BCa = ROL(Ebu, 27); - Ega ^= Da; - BCe = ROL(Ega, 36); - Eke ^= De; - BCi = ROL(Eke, 10); - Emi ^= Di; - BCo = ROL(Emi, 15); - Eso ^= Do; - BCu = ROL(Eso, 56); - Ama = BCa ^ ((~BCe) & BCi); - Ame = BCe ^ ((~BCi) & BCo); - Ami = BCi ^ ((~BCo) & BCu); - Amo = BCo ^ ((~BCu) & BCa); - Amu = BCu ^ ((~BCa) & BCe); - - Ebi ^= Di; - BCa = ROL(Ebi, 62); - Ego ^= Do; - BCe = ROL(Ego, 55); - Eku ^= Du; - BCi = ROL(Eku, 39); - Ema ^= Da; - BCo = ROL(Ema, 41); - Ese ^= De; - BCu = ROL(Ese, 2); - Asa = BCa ^ ((~BCe) & BCi); - Ase = BCe ^ ((~BCi) & BCo); - Asi = BCi ^ ((~BCo) & BCu); - Aso = BCo ^ ((~BCu) & BCa); - Asu = BCu ^ ((~BCa) & BCe); - } - - // copyToState(state, A) - state[0] = Aba; - state[1] = Abe; - state[2] = Abi; - state[3] = Abo; - state[4] = Abu; - state[5] = Aga; - state[6] = Age; - state[7] = Agi; - state[8] = Ago; - state[9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} - -/************************************************* - * Name: keccak_init - * - * Description: Initializes the Keccak state. - * - * Arguments: - uint64_t *s: pointer to Keccak state - **************************************************/ -static void keccak_init(uint64_t s[25]) { - unsigned int i; - for (i = 0; i < 25; ++i) - s[i] = 0; -} - -/************************************************* - * Name: keccak_absorb - * - * Description: Absorb step of Keccak; incremental. - * - * Arguments: - uint64_t *s: pointer to Keccak state - * - unsigned int pos: position in current block to be absorbed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - * - * Returns new position pos in current block - **************************************************/ -static unsigned int keccak_absorb(uint64_t s[25], unsigned int pos, - unsigned int r, const uint8_t *in, - size_t inlen) { - unsigned int i; - - while (pos + inlen >= r) { - for (i = pos; i < r; ++i) - s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); - inlen -= r - pos; - KeccakF1600_StatePermute(s); - pos = 0; - } - - for (i = pos; i < pos + inlen; ++i) - s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); - - return i; -} - -/************************************************* - * Name: keccak_finalize - * - * Description: Finalize absorb step. - * - * Arguments: - uint64_t *s: pointer to Keccak state - * - unsigned int pos: position in current block to be absorbed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - uint8_t p: domain separation byte - **************************************************/ -static void keccak_finalize(uint64_t s[25], unsigned int pos, unsigned int r, - uint8_t p) { - s[pos / 8] ^= (uint64_t)p << 8 * (pos % 8); - s[r / 8 - 1] ^= 1ULL << 63; -} - -/************************************************* - * Name: keccak_squeeze - * - * Description: Squeeze step of Keccak. Squeezes arbitratrily many bytes. - * Modifies the state. Can be called multiple times to keep - * squeezing, i.e., is incremental. - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: number of bytes to be squeezed (written to out) - * - uint64_t *s: pointer to input/output Keccak state - * - unsigned int pos: number of bytes in current block already - *squeezed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - * Returns new position pos in current block - **************************************************/ -static unsigned int keccak_squeeze(uint8_t *out, size_t outlen, uint64_t s[25], - unsigned int pos, unsigned int r) { - unsigned int i; - - while (outlen) { - if (pos == r) { - KeccakF1600_StatePermute(s); - pos = 0; - } - for (i = pos; i < r && i < pos + outlen; ++i) - *out++ = s[i / 8] >> 8 * (i % 8); - outlen -= i - pos; - pos = i; - } - - return pos; -} - -/************************************************* - * Name: keccak_absorb_once - * - * Description: Absorb step of Keccak; - * non-incremental, starts by zeroeing the state. - * - * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - * - uint8_t p: domain-separation byte for different Keccak-derived - *functions - **************************************************/ -static void keccak_absorb_once(uint64_t s[25], unsigned int r, - const uint8_t *in, size_t inlen, uint8_t p) { - unsigned int i; - - for (i = 0; i < 25; ++i) - s[i] = 0; - - while (inlen >= r) { - for (i = 0; i < r / 8; ++i) - s[i] ^= load64(in + 8 * i); - in += r; - inlen -= r; - KeccakF1600_StatePermute(s); - } - - for (i = 0; i < inlen; ++i) - s[i / 8] ^= (uint64_t)in[i] << 8 * (i % 8); - - s[i / 8] ^= (uint64_t)p << 8 * (i % 8); - s[(r - 1) / 8] ^= 1ULL << 63; -} - -/************************************************* - * Name: keccak_squeezeblocks - * - * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. - * Modifies the state. Can be called multiple times to keep - * squeezing, i.e., is incremental. Assumes zero bytes of current - * block have already been squeezed. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *out) - * - uint64_t *s: pointer to input/output Keccak state - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - **************************************************/ -static void keccak_squeezeblocks(uint8_t *out, size_t nblocks, uint64_t s[25], - unsigned int r) { - unsigned int i; - - while (nblocks) { - KeccakF1600_StatePermute(s); - for (i = 0; i < r / 8; ++i) - store64(out + 8 * i, s[i]); - out += r; - nblocks -= 1; - } -} - -/************************************************* - * Name: shake128_init - * - * Description: Initilizes Keccak state for use as SHAKE128 XOF - * - * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state - **************************************************/ -void shake128_init(keccak_state *state) { - keccak_init(state->s); - state->pos = 0; -} - -/************************************************* - * Name: shake128_absorb - * - * Description: Absorb step of the SHAKE128 XOF; incremental. - * - * Arguments: - keccak_state *state: pointer to (initialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { - state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); -} - -/************************************************* - * Name: shake128_finalize - * - * Description: Finalize absorb step of the SHAKE128 XOF. - * - * Arguments: - keccak_state *state: pointer to Keccak state - **************************************************/ -void shake128_finalize(keccak_state *state) { - keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* - * Name: shake128_squeeze - * - * Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many - * bytes. Can be called multiple times to keep squeezing. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t outlen : number of bytes to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { - state->pos = - keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); -} - -/************************************************* - * Name: shake128_absorb_once - * - * Description: Initialize, absorb into and finalize SHAKE128 XOF; - *non-incremental. - * - * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128_absorb_once(keccak_state *state, const uint8_t *in, - size_t inlen) { - keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* - * Name: shake128_squeezeblocks - * - * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of - * SHAKE128_RATE bytes each. Can be called multiple times - * to keep squeezing. Assumes new block has not yet been - * started (state->pos = SHAKE128_RATE). - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { - keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); -} - -/************************************************* - * Name: shake256_init - * - * Description: Initilizes Keccak state for use as SHAKE256 XOF - * - * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state - **************************************************/ -void shake256_init(keccak_state *state) { - keccak_init(state->s); - state->pos = 0; -} - -/************************************************* - * Name: shake256_absorb - * - * Description: Absorb step of the SHAKE256 XOF; incremental. - * - * Arguments: - keccak_state *state: pointer to (initialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { - state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); -} - -/************************************************* - * Name: shake256_finalize - * - * Description: Finalize absorb step of the SHAKE256 XOF. - * - * Arguments: - keccak_state *state: pointer to Keccak state - **************************************************/ -void shake256_finalize(keccak_state *state) { - keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* - * Name: shake256_squeeze - * - * Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many - * bytes. Can be called multiple times to keep squeezing. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t outlen : number of bytes to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { - state->pos = - keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); -} - -/************************************************* - * Name: shake256_absorb_once - * - * Description: Initialize, absorb into and finalize SHAKE256 XOF; - *non-incremental. - * - * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256_absorb_once(keccak_state *state, const uint8_t *in, - size_t inlen) { - keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* - * Name: shake256_squeezeblocks - * - * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of - * SHAKE256_RATE bytes each. Can be called multiple times - * to keep squeezing. Assumes next block has not yet been - * started (state->pos = SHAKE256_RATE). - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { - keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); -} - -/************************************************* - * Name: shake128 - * - * Description: SHAKE128 XOF with non-incremental API - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: requested output length in bytes - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { - size_t nblocks; - keccak_state state; - - shake128_absorb_once(&state, in, inlen); - nblocks = outlen / SHAKE128_RATE; - shake128_squeezeblocks(out, nblocks, &state); - outlen -= nblocks * SHAKE128_RATE; - out += nblocks * SHAKE128_RATE; - shake128_squeeze(out, outlen, &state); -} - -/************************************************* - * Name: shake256 - * - * Description: SHAKE256 XOF with non-incremental API - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: requested output length in bytes - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { - size_t nblocks; - keccak_state state; - - shake256_absorb_once(&state, in, inlen); - nblocks = outlen / SHAKE256_RATE; - shake256_squeezeblocks(out, nblocks, &state); - outlen -= nblocks * SHAKE256_RATE; - out += nblocks * SHAKE256_RATE; - shake256_squeeze(out, outlen, &state); -} - -/************************************************* - * Name: sha3_256 - * - * Description: SHA3-256 with non-incremental API - * - * Arguments: - uint8_t *h: pointer to output (32 bytes) - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) { - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for (i = 0; i < 4; ++i) - store64(h + 8 * i, s[i]); -} - -/************************************************* - * Name: sha3_512 - * - * Description: SHA3-512 with non-incremental API - * - * Arguments: - uint8_t *h: pointer to output (64 bytes) - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) { - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for (i = 0; i < 8; ++i) - store64(h + 8 * i, s[i]); -} diff --git a/crypto_sign/haetae2/ref/fips202.h b/crypto_sign/haetae2/ref/fips202.h deleted file mode 100644 index 58aa8ff2..00000000 --- a/crypto_sign/haetae2/ref/fips202.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FIPS202_H -#define FIPS202_H - -#include -#include - -#define SHAKE128_RATE 168 -#define SHAKE256_RATE 136 -#define SHA3_256_RATE 136 -#define SHA3_512_RATE 72 - -#define FIPS202_NAMESPACE(s) haetae_fips202_##s - -typedef struct { - uint64_t s[25]; - unsigned int pos; -} keccak_state; - -#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) -extern const uint64_t KeccakF_RoundConstants[]; - -#define shake128_init FIPS202_NAMESPACE(shake128_init) -void shake128_init(keccak_state *state); -#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) -void shake128_finalize(keccak_state *state); -#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) -void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake256_init FIPS202_NAMESPACE(shake256_init) -void shake256_init(keccak_state *state); -#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) -void shake256_finalize(keccak_state *state); -#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) -void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake128 FIPS202_NAMESPACE(shake128) -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define shake256 FIPS202_NAMESPACE(shake256) -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define sha3_256 FIPS202_NAMESPACE(sha3_256) -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); -#define sha3_512 FIPS202_NAMESPACE(sha3_512) -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); - -#endif diff --git a/crypto_sign/haetae2/ref/fixpoint.c b/crypto_sign/haetae2/ref/fixpoint.c deleted file mode 100644 index 831f15ec..00000000 --- a/crypto_sign/haetae2/ref/fixpoint.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "fixpoint.h" -#include "params.h" -#include -#include - -static void __cneg(fp96_76 *x, const uint8_t sign) { - x->limb48[0] ^= (-(int64_t)sign) & ((1ULL << 48) - 1); - x->limb48[1] ^= -(int64_t)sign; - x->limb48[0] += sign; - renormalize(x); -} - -static void __copy_cneg(fp96_76 *y, const fp96_76 *x, const uint8_t sign) { - y->limb48[0] = ((-(int64_t)sign) & ((1ULL << 48) - 1)) ^ x->limb48[0]; - ; - y->limb48[1] = x->limb48[1] ^ (-(int64_t)sign); - y->limb48[0] += sign; - renormalize(y); -} - -static void fixpoint_mul(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { - uint64_t tmp[2]; - mul48(&xy->limb48[0], x->limb48[0], y->limb48[0]); - - // shift right by 48, rounding - xy->limb48[0] = xy->limb48[1] + (((xy->limb48[0] >> 47) + 1) >> 1); - - mul48(tmp, x->limb48[0], y->limb48[1]); - xy->limb48[0] += tmp[0]; - xy->limb48[1] = tmp[1]; - mulacc48(&xy->limb48[0], x->limb48[1], y->limb48[0]); - - // shift right by 28, rounding - xy->limb48[0] += 1UL << 27; - xy->limb48[0] >>= 28; - xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] >>= 28; - - mul64(tmp, x->limb48[1], y->limb48[1]); - xy->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); - - renormalize(xy); -} - -static void fixpoint_unsigned_signed_mul(fp96_76 *xy, const fp96_76 *y) { - fp96_76 x, z; - uint8_t sign = (y->limb48[1] >> 63) & 1; - __copy_cneg(&x, y, sign); - fixpoint_mul(&z, &x, xy); - __copy_cneg(xy, &z, sign); -} - -static void fixpoint_sub(fp96_76 *xminy, const fp96_76 *x, const fp96_76 *y) { - fp96_76 yneg; - __copy_cneg(&yneg, y, 1); - fixpoint_add(xminy, x, &yneg); -} - -static void fixpoint_sub_from_threehalves(fp96_76 *x) { - __cneg(x, 1); - x->limb48[1] += 3ULL << 27; // left shift by 28 would be "3" - renormalize(x); -} - -void fixpoint_square(fp96_76 *sqx, const fp96_76 *x) { - uint64_t tmp[2]; - sq48(&sqx->limb48[0], x->limb48[0]); - - // shift right by 48, rounding - //sqx->limb48[0] += 1ULL << 47; - sqx->limb48[0] >>= 48; - sqx->limb48[0] += sqx->limb48[1]; - - // mul - mul48(tmp, x->limb48[0], x->limb48[1]); - sqx->limb48[0] += tmp[0] << 1; - sqx->limb48[1] = tmp[1] << 1; - - // shift right by 28, rounding - //sqx->limb48[0] += 1ULL << 27; - sqx->limb48[0] >>= 28; - sqx->limb48[0] += (sqx->limb48[1] << 20) & ((1ULL << 48) - 1); - sqx->limb48[1] >>= 28; - - sq64(tmp, x->limb48[1]); - sqx->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); - sqx->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); - - renormalize(sqx); -} - -// start_cube = hex(round(2^64/(sqrt((K + L)*N + 2)^3))) -// start_times_threehalfs = hex(round(2^64 * 2/(3 * sqrt((K + L)*N + 2)))) -#if L == 4 -const fp96_76 start_cube = {.limb48 = {0x770077e2e41aULL, 0x1162ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x693861ad937bULL, 0x9caa56ULL}}; -#elif L == 6 -const fp96_76 start_cube = {.limb48 = {0x1a2935cfae68ULL, 0x978ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x7ad215218533ULL, 0x7ff1c9ULL}}; -#elif L == 7 -const fp96_76 start_cube = {.limb48 = {0x700ff3e8890dULL, 0x702ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x5768588eed31ULL, 0x73bd40ULL}}; -#endif - -// implements Newton's method -void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf) { - fp96_76 tmp, tmp2; - fixpoint_mul(&tmp, xhalf, &start_cube); // definitely two positive values - fixpoint_sub(invsqrtx, &start_times_threehalves, - &tmp); // first Newton iteration done, might be negative (very - // improbable) - - for (int i = 0; i < 6; i++) // 6 more iterations - { - fixpoint_square(&tmp, invsqrtx); // tmp = y^2, never negative - fixpoint_mul(&tmp2, xhalf, &tmp); // tmp2 = x/2 * y^2, never negative - fixpoint_sub_from_threehalves(&tmp2); // tmp = 3/2 - x/2 * y^2 - fixpoint_unsigned_signed_mul(invsqrtx, &tmp2); // y * (3/2 - x/2 * y^2) - } -} - -int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, - const uint8_t sign) { - int64_t res; - fp96_76 tmp, xx; - xx.limb48[1] = x >> 32; - xx.limb48[0] = (x & ((1ULL << 32) - 1)) << 16; - fixpoint_mul(&tmp, &xx, y); - res = (tmp.limb48[1] + (1UL << 14)) >> 15; // rounding - return (1 - 2 * (int32_t)sign) * res; -} - -void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { - xy->limb48[0] = x->limb48[0] + y->limb48[0]; - xy->limb48[1] = x->limb48[1] + y->limb48[1]; -} diff --git a/crypto_sign/haetae2/ref/fixpoint.h b/crypto_sign/haetae2/ref/fixpoint.h deleted file mode 100644 index 7e608aa0..00000000 --- a/crypto_sign/haetae2/ref/fixpoint.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef FP__H -#define FP__H - -#include "config.h" -#include -#include - -#ifdef __SIZEOF_INT128__ -__extension__ typedef __int128 int128; -__extension__ typedef unsigned __int128 uint128; -#endif - -typedef struct { - uint64_t limb48[2]; -} fp96_76; - -#define fixpoint_square HAETAE_NAMESPACE(fixpoint_square) -void fixpoint_square(fp96_76 *sqx, const fp96_76 *x); - -#define fixpoint_newton_invsqrt HAETAE_NAMESPACE(fixpoint_newton_invsqrt) -void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf); - -#define fixpoint_mul_rnd13 HAETAE_NAMESPACE(fixpoint_mul_rnd13) -int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, - const uint8_t sign); - -#define fixpoint_add HAETAE_NAMESPACE(fixpoint_add) -void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y); - -static inline void renormalize(fp96_76 *x) { - x->limb48[1] += x->limb48[0] >> 48; - x->limb48[0] &= (1ULL << 48) - 1; -} - -static inline int64_t smulh48(int64_t a, uint64_t b) { -#ifndef __SIZEOF_INT128__ - int64_t ah = a >> 24; - int64_t al = a - (ah << 24); - int64_t bl = b & ((1<<24)-1); - int64_t bh = b >> 24; - - int64_t res = (al*bl) >> 24; - res += al * bh + ah * bl + (1 << 23); // rounding - res >>= 24; - return res + (ah * bh); -#else - return ((int128)a * (int128)b + (1ULL << 47)) >> 48; // rounding -#endif -} - -static inline void mul64(uint64_t r[2], const uint64_t b, const uint64_t a) { -#ifndef __SIZEOF_INT128__ - uint64_t al = a & ((1ULL << 32) - 1), bl = b & ((1ULL << 32) - 1), - ah = a >> 32, bh = b >> 32; - r[0] = a * b; - r[1] = ah * bl + al * bh + ((al * bl) >> 32); - r[1] >>= 32; - r[1] += ah * bh; -#else - uint128 res = ((uint128)a * (uint128)b); - r[0] = res; - r[1] = res >> 64; -#endif -} - -static inline void sq64(uint64_t r[2], const uint64_t a) { -#ifndef __SIZEOF_INT128__ - uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; - r[0] = a * a; - r[1] = ah * al * 2; - r[1] >>= 32; - r[1] += ah * ah; -#else - uint128 res = ((uint128)a * (uint128)a); - r[0] = res; - r[1] = res >> 64; -#endif -} - -static inline void mul48(uint64_t r[2], const uint64_t b, const uint64_t a) { - mul64(r, b, a); - r[1] <<= 16; - r[1] ^= r[0] >> 48; - r[0] &= (1ULL << 48) - 1; -} - -static inline void mulacc48(uint64_t r[2], const uint64_t b, const uint64_t a) { - uint64_t tmp[2]; - mul48(tmp, b, a); - r[0] += tmp[0]; - r[1] += tmp[1]; -} - -// (a0 + a1*2^32)^2 = a0^2 + 2^33*a0*a1 + 2^64*a1^2 -static inline void sq48(uint64_t r[2], const uint64_t a) { - uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; - r[0] = a * a; - r[1] = al * ah << 1; - r[1] >>= 32; - r[1] += ah * ah; - - r[1] <<= 16; - r[1] ^= r[0] >> 48; - r[0] &= (1ULL << 48) - 1; -} - -static inline void fixpoint_mul_high(fp96_76 *xy, const fp96_76 *x, - const uint64_t y) { - uint64_t tmp[2]; - mul48(&xy->limb48[0], x->limb48[0], y); // implicitly shifted right by 48 - - mul48(tmp, x->limb48[1], y); - xy->limb48[1] += tmp[0]; - - // shift right by 28, rounding - xy->limb48[0] += 1UL << 27; - xy->limb48[0] >>= 28; - xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] >>= 28; - - xy->limb48[1] += tmp[1] << 20; - - renormalize(xy); -} - -#endif diff --git a/crypto_sign/haetae2/ref/ntt.c b/crypto_sign/haetae2/ref/ntt.c deleted file mode 100644 index 6b66d3f6..00000000 --- a/crypto_sign/haetae2/ref/ntt.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include - -static const int32_t zetas[N] = { - 0, 26964, -16505, 22229, 30746, 20243, 19064, -31218, 9395, - -30985, 22859, -8851, 32144, 13744, 21408, 17599, -16039, -22946, - 6241, -19553, 10681, 22935, 22431, -29104, 28147, -27527, -29133, - -20035, 20143, -11361, 30820, 25252, -22562, -6789, -10049, 9383, - 16304, -12296, 16446, 18239, -1296, -19725, -32076, 11782, -17941, - 29643, -8577, 7893, -21464, -19646, -15130, -2391, 30608, -23970, - -16608, 19616, -7941, 26533, -19129, 27690, 7597, -11459, 10615, - -9430, 11591, 7814, 12697, 32114, -3761, -9604, 19813, 20353, - 17456, -16267, -19555, 598, -29942, 4538, 835, 15546, 3970, - -27685, 1488, 8311, -12442, 31352, -17631, 1806, -5342, 9790, - 29068, 16507, -29051, 22131, 6759, 15510, -14941, 28710, 1160, - -31327, 24985, 11261, -10623, -27727, 21502, 18731, -16186, -4127, - -18832, 12050, -14501, 7929, 29563, -31064, 5913, 5322, -16405, - 2844, 29439, 5876, -9522, -18586, -9874, 23844, 30362, -21442, - 9560, 17671, -27989, 3350, 787, -13857, 1657, -21224, -7374, - -9190, 2464, 25555, -3529, -28772, 16588, -15739, 23475, 13666, - 5764, 30980, 13633, -7401, -30317, 28847, 7682, -11808, -8796, - 14864, -24162, -19194, 689, -1311, -31332, -16319, 1025, 10971, - -23016, -2648, -21900, -12543, -25921, 28254, 28521, -16160, 12380, - -12882, -30332, -16630, 23439, 7742, 17182, 17494, 5920, 13642, - 7382, -18166, 21422, -30274, -28190, 13283, -20316, -9939, 10672, - 21454, 6080, -17374, -29735, -25912, -10170, 3808, 10639, -26985, - -10865, 25636, 17261, -26851, -8253, -3304, 18282, -2202, -31368, - -22243, 13882, 12069, -11242, -7729, -10226, 1761, -27298, -4800, - -17737, -22805, -3528, 65, 10770, 8908, -23751, 26934, 21921, - -27010, -21944, 8889, -1035, 23224, -9488, -5823, -994, -20206, - 7655, -16251, -22820, -27740, 15822, 23078, 13803, -8099, 2931, - 9217, -21126, -14203, 25492, -12831, 7947, 17463, -12979, 29003, - 31612, 26554, 8241, -20175}; // q = 64513 - -/************************************************* - * Name: ntt - * - * Description: Forward NTT, in-place. No modular reduction is performed after - * additions or subtractions. Output vector is in bitreversed - *order. - * - * Arguments: - uint32_t p[N]: input/output coefficient array - **************************************************/ -void ntt(int32_t a[N]) { - unsigned int len, start, j, k; - int32_t zeta, t; - - k = 0; - for (len = 128; len > 0; len >>= 1) { - for (start = 0; start < N; start = j + len) { - zeta = zetas[++k]; - for (j = start; j < start + len; ++j) { - t = montgomery_reduce((int64_t)zeta * a[j + len]); - a[j + len] = a[j] - t; - a[j] = a[j] + t; - } - } - } -} - -/************************************************* - * Name: invntt_tomont - * - * Description: Inverse NTT and multiplication by Montgomery factor 2^32. - * In-place. No modular reductions after additions or - * subtractions; input coefficients need to be smaller than - * Q in absolute value. Output coefficient are smaller than Q in - * absolute value. - * - * Arguments: - uint32_t p[N]: input/output coefficient array - **************************************************/ -void invntt_tomont(int32_t a[N]) { - unsigned int start, len, j, k; - int32_t t, zeta; - const int32_t f = -29720; // mont^2/256 - - k = 256; - for (len = 1; len < N; len <<= 1) { - for (start = 0; start < N; start = j + len) { - zeta = -zetas[--k]; - for (j = start; j < start + len; ++j) { - t = a[j]; - a[j] = t + a[j + len]; - a[j + len] = t - a[j + len]; - a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); - } - } - } - - for (j = 0; j < N; ++j) { - a[j] = montgomery_reduce((int64_t)f * a[j]); - } -} diff --git a/crypto_sign/haetae2/ref/ntt.h b/crypto_sign/haetae2/ref/ntt.h deleted file mode 100644 index c7732a34..00000000 --- a/crypto_sign/haetae2/ref/ntt.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include "params.h" -#include - -#define ntt HAETAE_NAMESPACE(ntt) -void ntt(int32_t a[N]); - -#define invntt_tomont HAETAE_NAMESPACE(invntt_tomont) -void invntt_tomont(int32_t a[N]); - -#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.c b/crypto_sign/haetae2/ref/packing.c deleted file mode 100644 index 4fd76e2f..00000000 --- a/crypto_sign/haetae2/ref/packing.c +++ /dev/null @@ -1,280 +0,0 @@ -#include "packing.h" -#include "encoding.h" -#include "params.h" -#include "poly.h" -#include "polymat.h" -#include "polyvec.h" -#include - -/************************************************* - * Name: pack_pk - * - * Description: Bit-pack public key pk = (seed, b). - * - * Arguments: - uint8_t pk[]: output byte array - * - const polyveck *b: polynomial vector of length K containg b - * - const uint8_t seed[]: seed for A' - **************************************************/ -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, - const uint8_t seed[SEEDBYTES]) { - unsigned int i; - - memcpy(pk, seed, SEEDBYTES); - - pk += SEEDBYTES; - for (i = 0; i < K; ++i) { - polyq_pack(pk + i * POLYQ_PACKEDBYTES, &b->vec[i]); - } -} - -/************************************************* - * Name: unpack_pk - * - * Description: Unpack public key pk = (seed, b). - * - * Arguments: - uint8_t seed[]: seed for A' - * - polyveck *b: polynomial vector of length K containg b - * - const uint8_t pk[]: output byte array - **************************************************/ -void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], - const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) { - unsigned int i; - - memcpy(seed, pk, SEEDBYTES); - - pk += SEEDBYTES; - for (i = 0; i < K; ++i) { - polyq_unpack(&b->vec[i], pk + i * POLYQ_PACKEDBYTES); - } -} - -/************************************************* - * Name: pack_sk - * - * Description: Bit-pack secret key sk = (pk, s). - * - * Arguments: - uint8_t sk[]: output byte array - * - const uint8_t pk[PUBLICKEYBYTES]: packed pk - * - const polyvecl *s0: polyvecl pointer containing s0 (encoding - *starting at offset 1) - * - const polyveck *s1: polyveck pointer containing s1 - **************************************************/ -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, - const polyveck *s1, const uint8_t key[SEEDBYTES]) { - unsigned int i; - memcpy(sk, pk, CRYPTO_PUBLICKEYBYTES); - - sk += CRYPTO_PUBLICKEYBYTES; - for (i = 0; i < M; ++i) - polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s0->vec[i]); - - sk += (L - 1) * POLYETA_PACKEDBYTES; -#if D == 1 - for (i = 0; i < K; ++i) - poly2eta_pack(sk + i * POLY2ETA_PACKEDBYTES, &s1->vec[i]); - sk += K * POLY2ETA_PACKEDBYTES; -#elif D == 0 - for (i = 0; i < K; ++i) - polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s1->vec[i]); - sk += K * POLYETA_PACKEDBYTES; -#else -#error "Not yet implemented." -#endif - memcpy(sk, key, SEEDBYTES); -} - -/************************************************* - * Name: unpack_sk - * - * Description: Unpack secret key sk = (A, s). - * - * Arguments: - polyvecl A[K]: output polyvecl array for A - * - polyvecl s0: output polyvecl pointer for s0 - * - polyveck s1: output polyveck pointer for s1 - * - const uint8_t sk[]: byte array containing bit-packed sk - **************************************************/ -void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { - unsigned int i; - uint8_t rhoprime[SEEDBYTES]; - polyveck b1; -#if D > 0 - polyveck a; -#endif - - unpack_pk(&b1, rhoprime, sk); - - sk += CRYPTO_PUBLICKEYBYTES; - for (i = 0; i < M; ++i) - polyeta_unpack(&s0->vec[i], sk + i * POLYETA_PACKEDBYTES); - - sk += M * POLYETA_PACKEDBYTES; -#if D == 1 - for (i = 0; i < K; ++i) - poly2eta_unpack(&s1->vec[i], sk + i * POLY2ETA_PACKEDBYTES); - - sk += K * POLY2ETA_PACKEDBYTES; -#elif D == 0 - for (i = 0; i < K; ++i) - polyeta_unpack(&s1->vec[i], sk + i * POLYETA_PACKEDBYTES); - - sk += K * POLYETA_PACKEDBYTES; -#else -#error "Not yet implemented." -#endif - memcpy(key, sk, SEEDBYTES); - - // A' = PRG(rhoprime) - polymatkl_expand(A, rhoprime); - polymatkl_double(A); -#if D > 0 - polyveck_expand(&a, rhoprime); -#endif - -#if D == 1 - // first column of A = 2(a-b1*2^d) - polyveck_double(&b1); - polyveck_sub(&b1, &a, &b1); - polyveck_double(&b1); - polyveck_ntt(&b1); -#elif D == 0 -#else -#error "Not yet implemented." -#endif - // append b into A - for (i = 0; i < K; ++i) { - A[i].vec[0] = b1.vec[i]; - } -} - -/************************************************* - * Name: pack_sig - * - * Description: Bit-pack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), - *Enc(h)). - * - * Arguments: - uint8_t sig[]: output byte array - * - const poly *c: pointer to challenge polynomial - * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of - *length L - * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of - *length L - * - const polyveck *h: pointer t vector h of length K - * Returns 1 in case the signature size is above the threshold; otherwise 0. - **************************************************/ -int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, - const polyvecl *lowbits_z1, const polyvecl *highbits_z1, - const polyveck *h) { - - uint8_t encoded_h[N * K]; - uint8_t encoded_hb_z1[N * L]; - uint16_t size_enc_h, size_enc_hb_z1; - uint8_t offset_enc_h, offset_enc_hb_z1; - - // init/padding with zeros: - memset(sig, 0, CRYPTO_BYTES); - - // encode challenge - for (size_t i = 0; i < N; i++) - { - sig[i/8] |= c->coeffs[i] << (i%8); - } - sig += N / 8; - - for (int i = 0; i < L; ++i) - poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); - sig += L * N; - - size_enc_hb_z1 = - encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]); - size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]); - - if(size_enc_h == 0 || size_enc_hb_z1 == 0) { - return 1; // encoding failed - } - - // The size of the encoded h and HB(z1) does not always fit in one byte, - // thus we output a one byte offset to a fixed baseline - if(size_enc_h < BASE_ENC_H || size_enc_hb_z1 < BASE_ENC_HB_Z1 || - size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { - return 1; // encoding size offset out of range - } - - offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; - offset_enc_h = size_enc_h - BASE_ENC_H; - - if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > - CRYPTO_BYTES) { - return 1; // signature too big - } - - sig[0] = offset_enc_hb_z1; - sig[1] = offset_enc_h; - sig += 2; - - memcpy(sig, encoded_hb_z1, size_enc_hb_z1); - sig += size_enc_hb_z1; - - memcpy(sig, encoded_h, size_enc_h); - sig += size_enc_h; - - return 0; -} - -/************************************************* - * Name: unpack_sig - * - * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), - *Enc(h)). - * - * Arguments: - poly *c: pointer to challenge polynomial - * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) - * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) - * - polyveck *h: pointer to output vector h - * - const uint8_t sig[]: byte array containing - * bit-packed signature - * - * Returns 1 in case of malformed signature; otherwise 0. - **************************************************/ -int unpack_sig(poly *c, polyvecl *lowbits_z1, - polyvecl *highbits_z1, polyveck *h, - const uint8_t sig[CRYPTO_BYTES]) { - - unsigned int i; - uint16_t size_enc_hb_z1, size_enc_h; - - for (i = 0; i < N; i++) - { - c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; - } - sig += N / 8; - - for (i = 0; i < L; ++i) - poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); - sig += L * N; - - size_enc_hb_z1 = (uint16_t)sig[0] + BASE_ENC_HB_Z1; - size_enc_h = (uint16_t)sig[1] + BASE_ENC_H; - sig += 2; - - if(CRYPTO_BYTES < (2 + L*N + SEEDBYTES + size_enc_h + size_enc_hb_z1)) - return 1; // invalid size_enc_h and/or size_enc_hb_z1 - - if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { - return 1; // decoding failed - } - - sig += size_enc_hb_z1; - - if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { - return 1; // decoding failed - } - - sig += size_enc_h; - - for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) - if(sig[i] != 0) return 1; // verify zero padding - - return 0; -} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.h b/crypto_sign/haetae2/ref/packing.h deleted file mode 100644 index ff9eb03b..00000000 --- a/crypto_sign/haetae2/ref/packing.h +++ /dev/null @@ -1,25 +0,0 @@ -// clang-format off -#ifndef HAETAE_PACKING_H -#define HAETAE_PACKING_H - -#include "params.h" -#include "polyvec.h" -#include - -#define pack_pk HAETAE_NAMESPACE(pack_pk) -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, const uint8_t seed[SEEDBYTES]); -#define unpack_pk HAETAE_NAMESPACE(unpack_pk) -void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); - -#define pack_sk HAETAE_NAMESPACE(pack_sk) -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); -#define unpack_sk HAETAE_NAMESPACE(unpack_sk) -void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - -#define pack_sig HAETAE_NAMESPACE(pack_sig) -int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); -#define unpack_sig HAETAE_NAMESPACE(unpack_sig) -int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); - -#endif //HAETAE_PACKING_H -// clang-format on diff --git a/crypto_sign/haetae2/ref/params.h b/crypto_sign/haetae2/ref/params.h deleted file mode 100644 index c73e63f2..00000000 --- a/crypto_sign/haetae2/ref/params.h +++ /dev/null @@ -1,116 +0,0 @@ -// clang-format off -#ifndef HAETAE_PARAMS_H -#define HAETAE_PARAMS_H - -#include "config.h" - -#define SEEDBYTES 32 -#define CRHBYTES 64 -#define N 256 -#define ROOT_OF_UNITY 3 - -#define Q 64513 -#define DQ (Q << 1)// 2Q - -#if HAETAE_MODE == 2 -#define K 2 -#define L 4 -#define ETA 1 -#define TAU 58 -#define B0 9846.02 -#define B1 9838.99 -#define B2 12777.52 -#define GAMMA 48.858 -#define LN 8192 // Large N -#define SQNM 39.191835884530846 // \sqrt(n * m) -#define D 1 -#define CRYPTO_BYTES 1474 - -#define BASE_ENC_HB_Z1 132 -#define BASE_ENC_H 7 - -#define ALPHA_HINT 512 -#define LOG_ALPHA_HINT 9 - -#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits -#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits - -#elif HAETAE_MODE == 3 -#define K 3 -#define L 6 -#define ETA 1 -#define TAU 80 -#define B0 18314.98 -#define B1 18307.70 -#define B2 21906.65 -#define GAMMA 57.707 -#define LN 8192 // Large N -#define SQNM 48.0 -#define D 1 -#define CRYPTO_BYTES 2349 - -#define BASE_ENC_HB_Z1 376 -#define BASE_ENC_H 127 - -#define ALPHA_HINT 512 -#define LOG_ALPHA_HINT 9 - -#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits -#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits - -#elif HAETAE_MODE == 5 -#define K 4 -#define L 7 -#define ETA 1 -#define TAU 128 -#define B0 22343.66 -#define B1 22334.95 -#define B2 24441.49 -#define GAMMA 55.13 -#define LN 8192 // Large N -#define SQNM 53.0659966456864 -#define D 0 -#define CRYPTO_BYTES 2948 - -#define BASE_ENC_HB_Z1 501 -#define BASE_ENC_H 358 - -#define ALPHA_HINT 256 -#define LOG_ALPHA_HINT 8 - -#define POLYB1_PACKEDBYTES 512 // 16bits * N / 8bits -#define POLYQ_PACKEDBYTES 512 // 16bits * N / 8bits - -#endif // HAETAE_MODE - -#define HALF_ALPHA_HINT (ALPHA_HINT >> 1) // ALPHA / 2 - -#define B0SQ ((uint64_t)(B0*B0)) -#define B1SQ ((uint64_t)(B1*B1)) -#define B2SQ ((uint64_t)(B2*B2)) - -#define M (L-1) - -#if ETA == 1 -#define POLYETA_PACKEDBYTES 64 -#define POLY2ETA_PACKEDBYTES 96 -#elif ETA == 2 -#define POLYETA_PACKEDBYTES 96 -#endif - -#define POLYC_PACKEDBYTES 32 // 1bit * N / 8bits -#define POLY_HIGHBITS_PACKEDBYTES (N * 9 / 8) -#define POLYVECK_HIGHBITS_PACKEDBYTES (POLY_HIGHBITS_PACKEDBYTES * K) -#define POLYVECK_BYTES (K * N * sizeof(int32_t)) -#define POLYVECL_BYTES (L * N * sizeof(int32_t)) - -#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLYQ_PACKEDBYTES) // seed + b -#if D == 1 -#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + M * POLYETA_PACKEDBYTES + K * POLY2ETA_PACKEDBYTES + SEEDBYTES) // pk + s + K -#elif D == 0 -#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + (M + K) * POLYETA_PACKEDBYTES + SEEDBYTES) // pk + s + K -#else -#error -#endif -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/poly.c b/crypto_sign/haetae2/ref/poly.c deleted file mode 100644 index 70ebe816..00000000 --- a/crypto_sign/haetae2/ref/poly.c +++ /dev/null @@ -1,659 +0,0 @@ -#include "poly.h" -#include "decompose.h" -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: poly_add - * - * Description: Add polynomials. No modular reduction is performed. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first summand - * - const poly *b: pointer to second summand - **************************************************/ -void poly_add(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; -} - -/************************************************* - * Name: poly_sub - * - * Description: Subtract polynomials. No modular reduction is - * performed. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first input polynomial - * - const poly *b: pointer to second input polynomial to be - * subtraced from first input polynomial - **************************************************/ -void poly_sub(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; -} - -/************************************************* - * Name: poly_pointwise_montgomery - * - * Description: Pointwise multiplication of polynomials in NTT domain - * representation and multiplication of resulting polynomial - * by 2^{-32}. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first input polynomial - * - const poly *b: pointer to second input polynomial - **************************************************/ -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); -} - -/************************************************* - * Name: poly_reduce2q - * - * Description: Inplace reduction of all coefficients of polynomial to 2q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_reduce2q(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = reduce32_2q(a->coeffs[i]); -} - -/************************************************* - * Name: poly_freeze2q - * - * Description: For all coefficients of in/out polynomial compute standard - * representative r = a mod^+ 2Q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_freeze2q(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = freeze2q(a->coeffs[i]); -} - -/************************************************* - * Name: poly_freeze - * - * Description: For all coefficients of in/out polynomial compute standard - * representative r = a mod^+ Q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_freeze(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = freeze(a->coeffs[i]); -} - -/************************************************* - * Name: poly_highbits - * - * Description: Compute HighBits of polynomial - * - * Arguments: - poly *a2: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_highbits(poly *a2, const poly *a) { - unsigned int i; - int32_t a1tmp; - - for (i = 0; i < N; ++i) - decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]); -} - -/************************************************* - * Name: poly_lowbits - * - * Description: Compute LowBits of polynomial - * - * Arguments: - poly *a1: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_lowbits(poly *a1, const poly *a) { - unsigned int i = 0; - int32_t a2tmp = 0; - - for (i = 0; i < N; ++i) - decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]); -} - -/************************************************* - * Name: poly_compose - * - * Description: Compose HighBits and LowBits to recreate the polynomial - * - * Arguments: - poly *a3: pointer to output polynomial - * - const poly *ha: pointer to HighBits polynomial - * - const poly *la: pointer to HighBits polynomial - **************************************************/ -void poly_compose(poly *a, const poly *ha, const poly *la) { - unsigned int i = 0; - - for (i = 0; i < N; ++i) - a->coeffs[i] = (ha->coeffs[i] << 8) + la->coeffs[i]; -} - -/************************************************* - * Name: poly_lsb - * - * Description: Compute least significant bits of polynomial - * - * Arguments: - poly *a0: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_lsb(poly *a0, const poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a0->coeffs[i] = a->coeffs[i] & 1; -} - -/************************************************* - * Name: poly_uniform - * - * Description: Sample polynomial with uniformly random coefficients - * in [0,Q-1] by performing rejection sampling on the - * output stream of SHAKE256(seed|nonce) - * - * Arguments: - poly *a: pointer to output polynomial - * - const uint8_t seed[]: byte array with seed of length SEEDBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -#define POLY_UNIFORM_NBLOCKS \ - ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES) -// N * 2(random bytes for [0, Q - 1]) - -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { - unsigned int i, ctr, off; - unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; - stream128_state state; - - stream128_init(&state, seed, nonce); - stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); - - ctr = rej_uniform(a->coeffs, N, buf, buflen); - - while (ctr < N) { - off = buflen % 2; - for (i = 0; i < off; ++i) - buf[i] = buf[buflen - off + i]; - - stream128_squeezeblocks(buf + off, 1, &state); - buflen = STREAM128_BLOCKBYTES + off; - ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); - } -} - -/************************************************* - * Name: poly_uniform_eta - * - * Description: Sample polynomial with uniformly random coefficients - * in [-ETA,ETA] by performing rejection sampling on the - * output stream from SHAKE256(seed|nonce) - * - * Arguments: - poly *a: pointer to output polynomial - * - const uint8_t seed[]: byte array with seed of length CRHBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -#if ETA == 1 -#define POLY_UNIFORM_ETA_NBLOCKS \ - ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -#elif ETA == 2 -#define POLY_UNIFORM_ETA_NBLOCKS \ - ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -#endif - -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int ctr; - unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); - - ctr = rej_eta(a->coeffs, N, buf, buflen); - - while (ctr < N) { - stream256_squeezeblocks(buf, 1, &state); - ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); - } -} - -uint8_t hammingWeight_8(uint8_t x) { - x = (x & 0x55) + (x >> 1 & 0x55); - x = (x & 0x33) + (x >> 2 & 0x33); - x = (x & 0x0F) + (x >> 4 & 0x0F); - - return x; -} - -/************************************************* - * Name: poly_challenge - * - * Description: Implementation of challenge. Samples polynomial with TAU 1 - * coefficients using the output stream of SHAKE256(seed). - * - * Arguments: - poly *c: pointer to output polynomial - * - const uint8_t highbits_lsb[]: packed highbits and lsb - * - const uint8_t mu[]: hash of pk and message - **************************************************/ -void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]) { -#if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) - unsigned int i, b, pos = 0; - uint8_t buf[XOF256_BLOCKBYTES]; - xof256_state state; - - // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, highbits_lsb, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, - SEEDBYTES); - xof256_squeezeblocks(buf, 1, &state); - - for (i = 0; i < N; ++i) - c->coeffs[i] = 0; - for (i = N - TAU; i < N; ++i) { - do { - if (pos >= XOF256_BLOCKBYTES) { - xof256_squeezeblocks(buf, 1, &state); - pos = 0; - } - - b = buf[pos++]; - } while (b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1; - } -#elif HAETAE_MODE == 5 - unsigned int i, hwt = 0, cond = 0; - uint8_t mask = 0, w0 = 0; - uint8_t buf[32] = {0}; - xof256_state state; - - // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, highbits_lsb, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, - SEEDBYTES); - xof256_squeeze(buf, 32, &state); - - for (i = 0; i < 32; ++i) - hwt += hammingWeight_8(buf[i]); - - cond = (128 - hwt); - mask = 0xff & (cond >> 8); - w0 = -(buf[0] & 1); - mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0 - for (i = 0; i < 32; ++i) { - buf[i] ^= mask; - c->coeffs[8 * i] = buf[i] & 1; - c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1; - c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1; - c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1; - c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1; - c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1; - c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1; - c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1; - } -#endif -} - -void poly_decomposed_pack(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N; i++) { - buf[i] = a->coeffs[i]; - } -} - -void poly_decomposed_unpack(poly *a, const uint8_t *buf) { - unsigned int i; - for (i = 0; i < N; i++) { - a->coeffs[i] = (int8_t)buf[i]; - } -} - -void poly_pack_highbits(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N / 8; i++) { - buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff; - - buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01; - buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff; - - buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03; - buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff; - - buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07; - buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff; - - buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f; - buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff; - - buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f; - buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff; - - buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f; - buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff; - - buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f; - buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff; - - buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff; - } -} - -void poly_pack_lsb(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N; i++) { - if ((i % 8) == 0) { - buf[i / 8] = 0; - } - buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8); - } -} - -/************************************************* - * Name: polyq_pack - * - * Description: Bit-pack polynomial with coefficients in [0, Q - 1]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYQ_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void polyq_pack(uint8_t *r, const poly *a) { - unsigned int i; -#if D == 1 - int b_idx = 0, d_idx = 0; - - for (i = 0; i < (N >> 3); ++i) { - b_idx = 15 * i; - d_idx = 8 * i; - - r[b_idx] = (a->coeffs[d_idx] & 0xff); - r[b_idx + 1] = ((a->coeffs[d_idx] >> 8) & 0x7f) | - ((a->coeffs[d_idx + 1] & 0x1) << 7); - r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff); - r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) | - ((a->coeffs[d_idx + 2] & 0x3) << 6); - r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff); - r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) | - ((a->coeffs[d_idx + 3] & 0x7) << 5); - r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff); - r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) | - ((a->coeffs[d_idx + 4] & 0xf) << 4); - r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff); - r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) | - ((a->coeffs[d_idx + 5] & 0x1f) << 3); - r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff); - r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) | - ((a->coeffs[d_idx + 6] & 0x3f) << 2); - r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff); - r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) | - (a->coeffs[d_idx + 7] & 0x7f) << 1; - r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff); - } -#else - for (i = 0; i < N / 1; ++i) { - r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0; - r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8; - } -#endif -} - -/************************************************* - * Name: polyq_unpack - * - * Description: Unpack polynomial with coefficients in [0, Q - 1]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void polyq_unpack(poly *r, const uint8_t *a) { - unsigned int i; -#if D == 1 - int b_idx = 0, d_idx = 0; - - for (i = 0; i < (N >> 3); ++i) { - b_idx = 15 * i; - d_idx = 8 * i; - - r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8); - r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) | - ((a[b_idx + 2] & 0xff) << 1) | - ((a[b_idx + 3] & 0x3f) << 9); - r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) | - ((a[b_idx + 4] & 0xff) << 2) | - ((a[b_idx + 5] & 0x1f) << 10); - r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) | - ((a[b_idx + 6] & 0xff) << 3) | - ((a[b_idx + 7] & 0xf) << 11); - r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) | - ((a[b_idx + 8] & 0xff) << 4) | - ((a[b_idx + 9] & 0x7) << 12); - r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) | - ((a[b_idx + 10] & 0xff) << 5) | - ((a[b_idx + 11] & 0x3) << 13); - r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) | - ((a[b_idx + 12] & 0xff) << 6) | - ((a[b_idx + 13] & 0x1) << 14); - r->coeffs[d_idx + 7] = - ((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7); - } - -#else - for (i = 0; i < N / 1; ++i) { - r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0; - r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8; - r->coeffs[1 * i + 0] &= 0xffff; - } -#endif -} - -/************************************************* - * Name: polyeta_pack - * - * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYETA_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void polyeta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - -#if ETA == 1 - for (i = 0; i < N / 4; ++i) { - t[0] = ETA - a->coeffs[4 * i + 0]; - t[1] = ETA - a->coeffs[4 * i + 1]; - t[2] = ETA - a->coeffs[4 * i + 2]; - t[3] = ETA - a->coeffs[4 * i + 3]; - r[i] = t[0] >> 0; - r[i] |= t[1] << 2; - r[i] |= t[2] << 4; - r[i] |= t[3] << 6; - } -#elif ETA == 2 - for (i = 0; i < N / 8; ++i) { - t[0] = ETA - a->coeffs[8 * i + 0]; - t[1] = ETA - a->coeffs[8 * i + 1]; - t[2] = ETA - a->coeffs[8 * i + 2]; - t[3] = ETA - a->coeffs[8 * i + 3]; - t[4] = ETA - a->coeffs[8 * i + 4]; - t[5] = ETA - a->coeffs[8 * i + 5]; - t[6] = ETA - a->coeffs[8 * i + 6]; - t[7] = ETA - a->coeffs[8 * i + 7]; - - r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#endif -} - -/************************************************* - * Name: polyeta_unpack - * - * Description: Unpack polynomial with coefficients in [-ETA,ETA]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void polyeta_unpack(poly *r, const uint8_t *a) { - unsigned int i; - -#if ETA == 1 - for (i = 0; i < N / 4; ++i) { - r->coeffs[4 * i + 0] = a[i] >> 0; - r->coeffs[4 * i + 0] &= 0x3; - - r->coeffs[4 * i + 1] = a[i] >> 2; - r->coeffs[4 * i + 1] &= 0x3; - - r->coeffs[4 * i + 2] = a[i] >> 4; - r->coeffs[4 * i + 2] &= 0x3; - - r->coeffs[4 * i + 3] = a[i] >> 6; - r->coeffs[4 * i + 3] &= 0x3; - - r->coeffs[4 * i + 0] = ETA - r->coeffs[4 * i + 0]; - r->coeffs[4 * i + 1] = ETA - r->coeffs[4 * i + 1]; - r->coeffs[4 * i + 2] = ETA - r->coeffs[4 * i + 2]; - r->coeffs[4 * i + 3] = ETA - r->coeffs[4 * i + 3]; - } - -#elif ETA == 2 - for (i = 0; i < N / 8; ++i) { - r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; - r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; - r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; - r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; - r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; - r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; - r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; - r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; - - r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0]; - r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1]; - r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2]; - r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3]; - r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4]; - r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5]; - r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6]; - r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7]; - } -#endif -} - -/************************************************* - * Name: poly2eta_pack - * - * Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYETA_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly2eta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - -#if ETA == 1 - for (i = 0; i < N / 8; ++i) { - t[0] = 2 * ETA - a->coeffs[8 * i + 0]; - t[1] = 2 * ETA - a->coeffs[8 * i + 1]; - t[2] = 2 * ETA - a->coeffs[8 * i + 2]; - t[3] = 2 * ETA - a->coeffs[8 * i + 3]; - t[4] = 2 * ETA - a->coeffs[8 * i + 4]; - t[5] = 2 * ETA - a->coeffs[8 * i + 5]; - t[6] = 2 * ETA - a->coeffs[8 * i + 6]; - t[7] = 2 * ETA - a->coeffs[8 * i + 7]; - - r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#elif ETA == 2 -#error "not yet implemented" -#endif -} - -/************************************************* - * Name: poly2eta_unpack - * - * Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void poly2eta_unpack(poly *r, const uint8_t *a) { - unsigned int i; - -#if ETA == 1 - for (i = 0; i < N / 8; ++i) { - r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; - r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; - r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; - r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; - r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; - r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; - r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; - r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; - - r->coeffs[8 * i + 0] = 2 * ETA - r->coeffs[8 * i + 0]; - r->coeffs[8 * i + 1] = 2 * ETA - r->coeffs[8 * i + 1]; - r->coeffs[8 * i + 2] = 2 * ETA - r->coeffs[8 * i + 2]; - r->coeffs[8 * i + 3] = 2 * ETA - r->coeffs[8 * i + 3]; - r->coeffs[8 * i + 4] = 2 * ETA - r->coeffs[8 * i + 4]; - r->coeffs[8 * i + 5] = 2 * ETA - r->coeffs[8 * i + 5]; - r->coeffs[8 * i + 6] = 2 * ETA - r->coeffs[8 * i + 6]; - r->coeffs[8 * i + 7] = 2 * ETA - r->coeffs[8 * i + 7]; - } -#elif ETA == 2 -#error "not yet implemented" -#endif -} - -void poly_fromcrt(poly *w, const poly *u, const poly *v) { - unsigned int i; - int32_t xq, x2; - - for (i = 0; i < N; i++) { - xq = u->coeffs[i]; - x2 = v->coeffs[i]; - w->coeffs[i] = xq + (Q & -((xq ^ x2) & 1)); - } -} - -void poly_fromcrt0(poly *w, const poly *u) { - unsigned int i; - int32_t xq; - - for (i = 0; i < N; i++) { - xq = u->coeffs[i]; - w->coeffs[i] = xq + (Q & -(xq & 1)); - } -} - -void poly_ntt(poly *a) { ntt(&a->coeffs[0]); } - -void poly_invntt_tomont(poly *a) { invntt_tomont(&a->coeffs[0]); } diff --git a/crypto_sign/haetae2/ref/poly.h b/crypto_sign/haetae2/ref/poly.h deleted file mode 100644 index 3c801b3b..00000000 --- a/crypto_sign/haetae2/ref/poly.h +++ /dev/null @@ -1,80 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLY_H -#define HAETAE_POLY_H - -#include "params.h" -#include "reduce.h" -#include "sampler.h" -#include - -typedef struct { - int32_t coeffs[N]; -} poly; - -#define poly_add HAETAE_NAMESPACE(poly_add) -void poly_add(poly *c, const poly *a, const poly *b); -#define poly_sub HAETAE_NAMESPACE(poly_sub) -void poly_sub(poly *c, const poly *a, const poly *b); -#define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); - -#define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) -void poly_reduce2q(poly *a); -#define poly_freeze2q HAETAE_NAMESPACE(poly_freeze2q) -void poly_freeze2q(poly *a); -#define poly_freeze HAETAE_NAMESPACE(poly_freeze) -void poly_freeze(poly *a); - -#define poly_highbits HAETAE_NAMESPACE(poly_highbits) -void poly_highbits(poly *a2, const poly *a); -#define poly_lowbits HAETAE_NAMESPACE(poly_lowbits) -void poly_lowbits(poly *a1, const poly *a); -#define poly_compose HAETAE_NAMESPACE(poly_compose) -void poly_compose(poly *a, const poly *ha, const poly *la); -#define poly_lsb HAETAE_NAMESPACE(poly_lsb) -void poly_lsb(poly *a0, const poly *a); - -#define poly_uniform HAETAE_NAMESPACE(poly_uniform) -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); -#define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define poly_challenge HAETAE_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]); - -#define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) -void poly_decomposed_pack(uint8_t *buf, const poly *a); -#define poly_decomposed_unpack HAETAE_NAMESPACE(poly_decomposed_unpack) -void poly_decomposed_unpack(poly *a, const uint8_t *buf); - -#define poly_pack_highbits HAETAE_NAMESPACE(poly_pack_highbits) -void poly_pack_highbits(uint8_t *buf, const poly *a); - -#define poly_pack_lsb HAETAE_NAMESPACE(poly_pack_lsb) -void poly_pack_lsb(uint8_t *buf, const poly *a); - -#define polyq_pack HAETAE_NAMESPACE(polyq_pack) -void polyq_pack(uint8_t *r, const poly *a); -#define polyq_unpack HAETAE_NAMESPACE(polyq_unpack) -void polyq_unpack(poly *r, const uint8_t *a); - -#define polyeta_pack HAETAE_NAMESPACE(polyeta_pack) -void polyeta_pack(uint8_t *r, const poly *a); -#define polyeta_unpack HAETAE_NAMESPACE(polyeta_unpack) -void polyeta_unpack(poly *r, const uint8_t *a); -#define poly2eta_pack HAETAE_NAMESPACE(poly2eta_pack) -void poly2eta_pack(uint8_t *r, const poly *a); -#define poly2eta_unpack HAETAE_NAMESPACE(poly2eta_unpack) -void poly2eta_unpack(poly *r, const uint8_t *a); - -#define poly_fromcrt HAETAE_NAMESPACE(poly_fromcrt) -void poly_fromcrt(poly *w, const poly *u, const poly *v); -#define poly_fromcrt0 HAETAE_NAMESPACE(poly_fromcrt0) -void poly_fromcrt0(poly *w, const poly *u); - -#define poly_ntt HAETAE_NAMESPACE(poly_ntt) -void poly_ntt(poly *a); -#define poly_invntt_tomont HAETAE_NAMESPACE(poly_invntt_tomont) -void poly_invntt_tomont(poly *a); - -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/polyfix.c b/crypto_sign/haetae2/ref/polyfix.c deleted file mode 100644 index c453d293..00000000 --- a/crypto_sign/haetae2/ref/polyfix.c +++ /dev/null @@ -1,292 +0,0 @@ -#include "polyfix.h" -#include "decompose.h" -#include "math.h" -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: polyfix_add - * - * Description: Add double polynomial and integer polynomial. - * No modular reduction is performed. - * - * Arguments: - polyfix *c: pointer to output double polynomial - * - const polyfix *a: pointer to first summand - * - const poly *b: pointer to second summand - **************************************************/ -void polyfix_add(polyfix *c, const polyfix *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + LN * b->coeffs[i]; -} - -/************************************************* - * Name: polyfixfix_sub - * - * Description: Subtract fixed polynomial and fixed polynomial. - * No modular reduction is performed. - * - * Arguments: - polyfix *c: pointer to output fixed polynomial - * - const polyfix *a: pointer to first summand - * - const polyfix *b: pointer to second summand - **************************************************/ -void polyfixfix_sub(polyfix *c, const polyfix *a, const polyfix *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; -} - -int32_t fix_round(int32_t num) { - num += (num >> 31) & (-LN + 1); - num += - LN / - 2; // total \floor(LN / 2) if positive, -\floor(LN / 2) + 1 if negative - return num / LN; -} - -/************************************************* - * Name: polyfix_round - * - * Description: rounds a fixed polynomial to integer polynomial - * - * Arguments: - poly *a: output integer polynomial - * - poly *b: input fixed polynomial - **************************************************/ -void polyfix_round(poly *a, const polyfix *b) { - unsigned i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = fix_round(b->coeffs[i]); -} - -/**************************************************************/ -/********* Double Vectors of polynomials of length K **********/ -/**************************************************************/ - -/************************************************* - * Name: polyfixveck_add - * - * Description: Add vector to a vector of double polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first summand - * - const polyveck *v: pointer to second summand - **************************************************/ -void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixfixveck_sub - * - * Description: subtract vector to a vector of fixed polynomials of length k. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyfixveck *u: pointer to first summand - * - const polyfixveck *v: pointer to second summand - **************************************************/ -void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, - const polyfixveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixveck_double - * - * Description: Double vector of polynomials of length K. - * - * Arguments: - polyveck *b: pointer to output vector - * - polyveck *a: pointer to input vector - **************************************************/ -void polyfixveck_double(polyfixveck *b, const polyfixveck *a) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; -} - -/************************************************* - * Name: polyfixveck_round - * - * Description: rounds a fixed polynomial vector of length K - * - * Arguments: - polyveck *a: output integer polynomial vector - * - polyfixveck *b: input fixed polynomial vector - **************************************************/ -void polyfixveck_round(polyveck *a, const polyfixveck *b) { - unsigned i; - - for (i = 0; i < K; ++i) - polyfix_round(&a->vec[i], &b->vec[i]); -} - -/**************************************************************/ -/********* Double Vectors of polynomials of length L **********/ -/**************************************************************/ - -/************************************************* - * Name: polyfixvecl_add - * - * Description: Add vector to a vector of double polynomials of length L. - * No modular reduction is performed. - * - * Arguments: - polyvecl *w: pointer to output vector - * - const polyfixvecl *u: pointer to first summand - * - const polyvecl *v: pointer to second summand - **************************************************/ -void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixfixvecl_sub - * - * Description: subtract vector to a vector of fixed polynomials of length l. - * No modular reduction is performed. - * - * Arguments: - polyvecl *w: pointer to output vector - * - const polyfixvecl *u: pointer to first summand - * - const polyfixvecl *v: pointer to second summand - **************************************************/ -void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, - const polyfixvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} -/************************************************* - * Name: polyfixvecl_double - * - * Description: Double vector of polynomials of length L. - * - * Arguments: - polyveck *b: pointer to output vector - * - polyveck *a: pointer to input vector - **************************************************/ -void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) { - unsigned int i, j; - - for (i = 0; i < L; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; -} - -/************************************************* - * Name: polyfixvecl_round - * - * Description: rounds a fixed polynomial vector of length L - * - * Arguments: - polyvecl *a: output integer polynomial vector - * - polyfixvecl *b: input fixed polynomial vector - **************************************************/ -void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) { - unsigned i; - - for (i = 0; i < L; ++i) - polyfix_round(&a->vec[i], &b->vec[i]); -} - -/************************************************* - * Name: polyfixveclk_norm2 - * - * Description: Calculates L2 norm of a fixed point polynomial vector with - *length L + K The result is L2 norm * LN similar to the way polynomial is - *usually stored - * - * Arguments: - polyfixvecl *a: polynomial vector with length L to calculate - * norm - * - polyfixveck *a: polynomial vector with length K to calculate - * norm - **************************************************/ -uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < L; ++i) { - for (j = 0; j < N; ++j) - ret += (int64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; - } - - for (i = 0; i < K; ++i) { - for (j = 0; j < N; ++j) - ret += (int64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; - } - - return ret; -} - -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, - const uint8_t seed[CRHBYTES], - const uint16_t nonce) { - uint16_t ni = nonce; - uint64_t samples[N * (L + K)]; - fp96_76 sqsum, invsqrt; - unsigned int i, j; - uint8_t signs[N * (L + K) / 8]; - - do { - sqsum.limb48[0] = 0; - sqsum.limb48[1] = 0; - - sample_gauss_N(&samples[0], &signs[0], &sqsum, seed, ni++, N + 1); - sample_gauss_N(&samples[N], &signs[N / 8], &sqsum, seed, ni++, N + 1); - - for (i = 2; i < L + K; i++) - sample_gauss_N(&samples[N * i], &signs[N / 8 * i], &sqsum, seed, - ni++, N); - - // divide sqsum by 2 and approximate inverse square root - sqsum.limb48[0] += 1; // rounding - sqsum.limb48[0] >>= 1; - sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; - sqsum.limb48[1] >>= 1; - sqsum.limb48[1] += sqsum.limb48[0] >> 48; - sqsum.limb48[0] &= (1ULL << 48) - 1; - fixpoint_newton_invsqrt(&invsqrt, &sqsum); - fixpoint_mul_high(&sqsum, &invsqrt, - (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); - - for (i = 0; i < L; i++) { - for (j = 0; j < N; j++) - y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( - samples[(i * N + j)], &sqsum, - (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); - } - for (i = L; i < K + L; i++) { - for (j = 0; j < N; j++) - y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( - samples[(i * N + j)], &sqsum, - (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); - } - } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); - - { - uint8_t tmp[CRHBYTES + 2]; - for (i = 0; i < CRHBYTES; i++) - { - tmp[i] = seed[i]; - } - tmp[CRHBYTES + 0] = ni >> 0; - tmp[CRHBYTES + 1] = ni >> 8; - shake256(b, 1, tmp, CRHBYTES+2); - } - - return ni; -} diff --git a/crypto_sign/haetae2/ref/polyfix.h b/crypto_sign/haetae2/ref/polyfix.h deleted file mode 100644 index 6177319c..00000000 --- a/crypto_sign/haetae2/ref/polyfix.h +++ /dev/null @@ -1,61 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLYFIX_H -#define HAETAE_POLYFIX_H - -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include "reduce.h" -#include - -typedef struct { - int32_t coeffs[N]; -} polyfix; - -#define polyfix_norm2 HAETAE_NAMESPACE(polyfix_norm2) -double polyfix_norm2(const polyfix *a); - -#define polyfix_round HAETAE_NAMESPACE(polyfix_round) -void polyfix_round(poly *a, const polyfix *b); - -#define polyfix_add HAETAE_NAMESPACE(polyfix_add) -void polyfix_add(polyfix *c, const polyfix *a, const poly *b); - -typedef struct { - polyfix vec[K]; -} polyfixveck; - -#define polyfixveck_add HAETAE_NAMESPACE(polyfixveck_add) -void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v); -#define polyfixfixveck_sub HAETAE_NAMESPACE(polyfixfixveck_sub) -void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, - const polyfixveck *v); -#define polyfixveck_double HAETAE_NAMESPACE(polyfixveck_double) -void polyfixveck_double(polyfixveck *b, const polyfixveck *a); - -#define polyfixveck_round HAETAE_NAMESPACE(polyfixveck_round) -void polyfixveck_round(polyveck *a, const polyfixveck *b); - -typedef struct { - polyfix vec[L]; -} polyfixvecl; - -#define polyfixvecl_add HAETAE_NAMESPACE(polyfixvecl_add) -void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v); -#define polyfixfixvecl_sub HAETAE_NAMESPACE(polyfixfixvecl_sub) -void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, - const polyfixvecl *v); -#define polyfixvecl_double HAETAE_NAMESPACE(polyfixvecl_double) -void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a); - -#define polyfixvecl_round HAETAE_NAMESPACE(polyfixvecl_round) -void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); - -#define polyfixveclk_sqnorm2 HAETAE_NAMESPACE(polyfixveclk_sqnorm2) -uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); - -#define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); - -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/polymat.c b/crypto_sign/haetae2/ref/polymat.c deleted file mode 100644 index c97f4dfb..00000000 --- a/crypto_sign/haetae2/ref/polymat.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "polymat.h" -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include - -/************************************************* - * Name: polymat_expand - * - * Description: Implementation of ExpandA. Generates matrix A with uniformly - * random coefficients a_{i,j} by performing rejection - * sampling on the output stream of SHAKE128(rho|j|i) - * or AES256CTR(rho,j|i). - * - * Arguments: - polyvecm mat[K]: output matrix k \times m - * - const uint8_t rho[]: byte array containing seed rho - **************************************************/ -void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < M; ++j) - poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); -} - -/************************************************* - * Name: polymat_expand - * - * Description: Implementation of ExpandA. Generates matrix A with uniformly - * random coefficients a_{i,j} by performing rejection - * sampling on the output stream of SHAKE128(rho|j|i) - * or AES256CTR(rho,j|i). - * - * Arguments: - polyvecm mat[K]: output matrix k \times m - * - const uint8_t rho[]: byte array containing seed rho - **************************************************/ -void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < M; ++j) - poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); -} - -// doubles k * m sub-matrix of k * l mat -void polymatkl_double(polyvecl mat[K]) { - unsigned int i, j, k; - for (i = 0; i < K; ++i) { - for (j = 1; j < L; ++j) { - for (k = 0; k < N; ++k) { - mat[i].vec[j].coeffs[k] *= 2; - } - } - } -} - -void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], - const polyvecl *v) { - unsigned int i; - - for (i = 0; i < K; ++i) { - polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); - } -} - -void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], - const polyvecm *v) { - unsigned int i; - - for (i = 0; i < K; ++i) { - polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); - } -} diff --git a/crypto_sign/haetae2/ref/polymat.h b/crypto_sign/haetae2/ref/polymat.h deleted file mode 100644 index c12bc28a..00000000 --- a/crypto_sign/haetae2/ref/polymat.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef HAETAE_POLYMAT_H -#define HAETAE_POLYMAT_H - -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include - -#define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) -void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); - -#define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) -void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); - -#define polymatkm_pointwise_montgomery \ - HAETAE_NAMESPACE(polymatkm_pointwise_montgomery) -void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], - const polyvecm *v); - -#define polymatkl_pointwise_montgomery \ - HAETAE_NAMESPACE(polymatkl_pointwise_montgomery) -void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], - const polyvecl *v); - -#define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) -void polymatkl_double(polyvecl mat[K]); - -#endif diff --git a/crypto_sign/haetae2/ref/polyvec.c b/crypto_sign/haetae2/ref/polyvec.c deleted file mode 100644 index 3b8b0336..00000000 --- a/crypto_sign/haetae2/ref/polyvec.c +++ /dev/null @@ -1,543 +0,0 @@ -#include - -#include "decompose.h" -#include "fft.h" -#include "math.h" -#include "params.h" -#include "poly.h" -#include "polyvec.h" - -/**************************************************************/ -/************ Vectors of polynomials of length K **************/ -/**************************************************************/ - -/************************************************* - * Name: polyveck_add - * - * Description: Add vectors of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first summand - * - const polyveck *v: pointer to second summand - **************************************************/ -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyveck_sub - * - * Description: Subtract vectors of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first input vector - * - const polyveck *v: pointer to second input vector to be - * subtracted from first input vector - **************************************************/ -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyveck_double - * - * Description: Double vector of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - **************************************************/ -void polyveck_double(polyveck *b) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] *= 2; -} - -/************************************************* - * Name: polyveck_reduce2q - * - * Description: Reduce coefficients to 2q - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_reduce2q(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_reduce2q(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_freeze - * - * Description: For all coefficients of polynomials in vector of length K - * compute standard representative r = a mod^+ Q. - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_freeze(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_freeze(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_freeze2q - * - * Description: For all coefficients of polynomials in vector of length K - * compute standard representative r = a mod^+ 2Q. - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_freeze2q(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_freeze2q(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_expand - * - * Description: Sample a vector of polynomials with uniformly random - * coefficients in Zq by rejection sampling on the - * output stream from SHAKE128(seed|nonce) - * - * Arguments: - polyveck *v: pointer to output a vector of polynomials of - * length K - * - const uint8_t seed[]: byte array with seed of length SEEDBYTES - **************************************************/ -void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]) { - unsigned int i, nonce = (K << 8) + M; - for (i = 0; i < K; ++i) - poly_uniform(&v->vec[i], seed, nonce++); -} - -/************************************************* - * Name: polyvecmk_uniform_eta - * - * Description: Sample a vector of polynomials with uniformly random - * coefficients in [-ETA,ETA] by rejection sampling on the - * output stream from SHAKE256(seed|nonce) - * - * Arguments: - polyveck *v: pointer to output a vector of polynomials of - * length K - * - const uint8_t seed[]: byte array with seed of length CRHBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, - const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i, n = nonce; - for (i = 0; i < M; i++) - poly_uniform_eta(&u->vec[i], seed, n++); - for (i = 0; i < K; ++i) - poly_uniform_eta(&v->vec[i], seed, n++); -} - -/************************************************* - * Name: polyveck_double_negate - * - * Description: multiply each coefficient with -2 - * - * Arguments: - polyveck *v: pointer to output vector of polynomials of - * length K - **************************************************/ -void polyveck_double_negate(polyveck *v) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; j++) - v->vec[i].coeffs[j] = - montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2); -} - -/************************************************* - * Name: polyveck_frommont - * - * Description: multiply each coefficient with MONT - * - * Arguments: - polyveck *v: pointer to output vector of polynomials of - * length K - **************************************************/ -void polyveck_frommont(polyveck *v) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; j++) - v->vec[i].coeffs[j] = - montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ); -} - -void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, - const poly *v) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v); - } -} - -/************************************************* - * Name: polyveck_poly_fromcrt - * - * Description: recover polynomials from CRT domain, where all "mod q" - * polynomials are known and only the uppermost "mod 2" polynomial - * is non-zero - * - * Arguments: - polyveck *w: pointer to output vector of polynomials of - * length K - * - const polyveck *u: pointer to the input vector of polynomials - * of length K - * - const poly *v: pointer to the input polynomial ("mod 2") - **************************************************/ -void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) { - unsigned int i; - - poly_fromcrt(&w->vec[0], &u->vec[0], v); - - for (i = 1; i < K; i++) { - poly_fromcrt0(&w->vec[i], &u->vec[i]); - } -} - -void polyveck_highbits_hint(polyveck *w, const polyveck *v) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]); - } - } -} - -void polyveck_pack_highbits(uint8_t *buf, const polyveck *v) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_pack_highbits(buf + i * POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]); - } -} - -void polyveck_cneg(polyveck *v, const uint8_t b) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] *= 1 - 2 * b; - } - } -} - -void polyveck_caddDQ2ALPHA(polyveck *h) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - h->vec[i].coeffs[j] += - (h->vec[i].coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); - } - } -} - -void polyveck_csubDQ2ALPHA(polyveck *v) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] -= - ~((v->vec[i].coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & - ((DQ - 2) / ALPHA_HINT); - } - } -} - -void polyveck_mul_alpha(polyveck *v, const polyveck *u) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * ALPHA_HINT; - } - } -} - -void polyveck_div2(polyveck *v) { - unsigned i, j; - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - v->vec[i].coeffs[j] >>= 1; -} - -void polyveck_caddq(polyveck *v) { - unsigned i, j; - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]); -} - -void polyveck_decompose_vk(polyveck *v0, polyveck *v) { - for (int i = 0; i < K; i++) { - for (int j = 0; j < N; j++) { - v->vec[i].coeffs[j] = - decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]); - } - } -} - -void polyveck_ntt(polyveck *x) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_ntt(&x->vec[i]); - } -} - -void polyveck_invntt_tomont(polyveck *x) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_invntt_tomont(&x->vec[i]); - } -} - -/************************************************* - * Name: polyveck_sqnorm2 - * - * Description: Calculates L2 norm of a polynomial vector with length k - * - * Arguments: - polyveck *b: polynomial vector with length k to calculate - *norm - **************************************************/ -uint64_t polyveck_sqnorm2(const polyveck *b) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < K; ++i) { - for (j = 0; j < N; ++j) { - ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; - } - } - return ret; -} - -/**************************************************************/ -/************ Vectors of polynomials of length L **************/ -/**************************************************************/ - -/************************************************* - * Name: polyvecl_highbits - * - * Description: Compute HighBits of a vector of polynomials - * - * Arguments: - polyvecl *v2: pointer to output vector of polynomials of - * length L - * - const polyvecl *v: pointer to input vector of polynomials of - * length L - **************************************************/ -void polyvecl_highbits(polyvecl *v2, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - poly_highbits(&v2->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyvecl_lowbits - * - * Description: Compute LowBits of a vector of polynomials - * - * Arguments: - polyvecl *v1: pointer to output vector of polynomials of - * length L - * - const polyvecl *v: pointer to input vector of polynomials of - * length L - **************************************************/ -void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - poly_lowbits(&v1->vec[i], &v->vec[i]); -} - -void polyvecl_cneg(polyvecl *v, const uint8_t b) { - unsigned int i, j; - for (i = 0; i < L; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] *= 1 - 2 * b; - } - } -} - -/************************************************* - * Name: polyvecl_sqnorm2 - * - * Description: Calculates L2 norm of a polynomial vector with length l - * - * Arguments: - polyvecl *a: polynomial vector with length l to calculate - *norm - **************************************************/ -uint64_t polyvecl_sqnorm2(const polyvecl *a) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < L; ++i) { - for (j = 0; j < N; ++j) { - ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; - } - } - - return ret; -} - -/************************************************* - * Name: polyvecl_pointwise_acc_montgomery - * - * Description: Pointwise multiply vectors of polynomials of length L, multiply - * resulting vector by 2^{-32} and add (accumulate) polynomials - * in it. Input/output vectors are in NTT domain representation. - * - * Arguments: - poly *w: output polynomial - * - const polyvecl *u: pointer to first input vector - * - const polyvecl *v: pointer to second input vector - **************************************************/ -void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, - const polyvecl *v) { - unsigned int i; - poly t; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -void polyvecl_ntt(polyvecl *x) { - unsigned int i; - for (i = 0; i < L; i++) { - poly_ntt(&x->vec[i]); - } -} - -/**************************************************************/ -/************ Vectors of polynomials of length M **************/ -/**************************************************************/ - -/************************************************* - * Name: polyvecm_pointwise_acc_montgomery - * - * Description: Pointwise multiply vectors of polynomials of length L, multiply - * resulting vector by 2^{-32} and add (accumulate) polynomials - * in it. Input/output vectors are in NTT domain representation. - * - * Arguments: - poly *w: output polynomial - * - const polyvecm *u: pointer to first input vector - * - const polyvecm *v: pointer to second input vector - **************************************************/ -void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u, - const polyvecm *v) { - unsigned int i; - poly t; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for (i = 1; i < M; ++i) { - poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -void polyvecm_ntt(polyvecm *x) { - unsigned int i; - for (i = 0; i < M; i++) { - poly_ntt(&x->vec[i]); - } -} - -static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort -{ - int32_t a = *x; - int32_t b = *y; - int32_t ab = b ^ a; - int32_t c = b - a; - c ^= ab & (c ^ b); - c >>= 31; - c &= ab; - *x = a ^ c; - *y = b ^ c; -} -static inline void minmaxmask(int32_t *x, int32_t *y, - int32_t *mask) // adapted from djbsort -{ - // If mask is -1, we perform the operation, else we do basically nothing. - // mask truth table: - // mask = 0 -> mask = 0, no swap is performed - // mask = -1, swap performed -> mask = 0 - // mask = -1, swap not performed -> mask = -1 - int32_t a = *x; - int32_t b = *y; - int32_t ab = (b ^ a) & *mask; - int32_t c = b - a; - c ^= ab & (c ^ b); - c >>= 31; - *mask &= ~c; - c &= ab; - *x = a ^ c; - *y = b ^ c; -} - -int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2) { - int32_t res = 0; - complex_fp32_16 input[FFT_N] = {0}; - int32_t sum[N] = {0}, bestm[N / TAU + 1] = {0}, min = 0; - - for (size_t i = 0; i < M; ++i) { - fft_bitrev(input, &s1->vec[i]); - fft(input); - - // cumulative sum - for (size_t j = 0; j < N; j++) { - sum[j] += complex_fp_sqabs(input[2 * j + 1]); - } - } - - for (size_t i = 0; i < K; ++i) { - fft_bitrev(input, &s2->vec[i]); - fft(input); - - // cumulative sum - for (size_t j = 0; j < N; j++) { - sum[j] += complex_fp_sqabs(input[2 * j + 1]); - } - } - - // compute max m - for (size_t i = 0; i < N / TAU + 1; ++i) { - bestm[i] = sum[i]; - } - for (size_t i = N / TAU + 1; i < N; i++) { - int32_t mask = -1; - for (size_t j = 0; j < N / TAU + 1; j++) { - minmaxmask(&sum[i], &bestm[j], &mask); - } - } - // find minimum in bestm - min = bestm[0]; - for (size_t i = 1; i < N / TAU + 1; i++) { - int32_t tmp = bestm[i]; - minmax(&min, &tmp); - } - // multiply all but the minimum by N mod TAU - for (size_t i = 0; i < N / TAU + 1; i++) { - int32_t fac = ((min - bestm[i]) >> 31); // all-ones if bestm[i] != min (TODO: impl specific behaviour) - fac = - (fac & (TAU)) ^ - ((~fac) & (N % TAU)); // fac = TAU for all != min and N%TAU for min - bestm[i] += - 0x10200; // add 1 for the "1 poly" in S, and prepare rounding - bestm[i] >>= 10; // round off 10 bits - bestm[i] *= fac; - res += bestm[i]; - } - - return (res + (1 << 5)) >> 6; // return rounded, squared value -} diff --git a/crypto_sign/haetae2/ref/polyvec.h b/crypto_sign/haetae2/ref/polyvec.h deleted file mode 100644 index 8d48aa40..00000000 --- a/crypto_sign/haetae2/ref/polyvec.h +++ /dev/null @@ -1,129 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLYVEC_H -#define HAETAE_POLYVEC_H - -#include "params.h" -#include "poly.h" -#include - -/* Vectors of polynomials of length K */ -typedef struct { - poly vec[K]; -} polyveck; - -#define polyveck_add HAETAE_NAMESPACE(polyveck_add) -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_sub HAETAE_NAMESPACE(polyveck_sub) -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_double HAETAE_NAMESPACE(polyveck_double) -void polyveck_double(polyveck *b); - -#define polyveck_reduce2q HAETAE_NAMESPACE(polyveck_reduce2q) -void polyveck_reduce2q(polyveck *v); -#define polyveck_freeze2q HAETAE_NAMESPACE(polyveck_freeze2q) -void polyveck_freeze2q(polyveck *v); -#define polyveck_freeze HAETAE_NAMESPACE(polyveck_freeze) -void polyveck_freeze(polyveck *v); - -#define polyveck_uniform_eta HAETAE_NAMESPACE(polyveck_uniform_eta) -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define polyveck_expand HAETAE_NAMESPACE(polyveck_expand) -void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]); - -#define polyveck_ntt HAETAE_NAMESPACE(polyveck_ntt) -void polyveck_ntt(polyveck *x); - -#define polyveck_invntt_tomont HAETAE_NAMESPACE(polyveck_invntt_tomont) -void polyveck_invntt_tomont(polyveck *x); - -#define polyveck_double_negate HAETAE_NAMESPACE(polyveck_double_negate) -void polyveck_double_negate(polyveck *x); - -#define polyveck_frommont HAETAE_NAMESPACE(polyveck_frommont) -void polyveck_frommont(polyveck *x); - -#define polyveck_poly_pointwise_montgomery HAETAE_NAMESPACE(polyveck_poly_pointwise_montgomery) -void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, const poly *v); - -#define polyveck_poly_fromcrt HAETAE_NAMESPACE(polyveck_poly_fromcrt) -void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v); - -#define polyveck_highbits_hint HAETAE_NAMESPACE(polyveck_highbits_hint) -void polyveck_highbits_hint(polyveck *w, const polyveck *v); - -#define polyveck_pack_highbits HAETAE_NAMESPACE(polyveck_pack_highbits) -void polyveck_pack_highbits(uint8_t *buf, const polyveck *v); - -#define polyveck_cneg HAETAE_NAMESPACE(polyveck_cneg) -void polyveck_cneg(polyveck *v, const uint8_t b); - -#define polyveck_caddDQ2ALPHA HAETAE_NAMESPACE(polyveck_caddDQ2ALPHA) -void polyveck_caddDQ2ALPHA(polyveck *h); - -#define polyveck_csubDQ2ALPHA HAETAE_NAMESPACE(polyveck_csubDQ2ALPHA) -void polyveck_csubDQ2ALPHA(polyveck *v); - -#define polyveck_mul_alpha HAETAE_NAMESPACE(polyveck_mul_alpha) -void polyveck_mul_alpha(polyveck *v, const polyveck *u); - -#define polyveck_div2 HAETAE_NAMESPACE(polyveck_div2) -void polyveck_div2(polyveck *v); - -#define polyveck_caddq HAETAE_NAMESPACE(polyveck_caddq) -void polyveck_caddq(polyveck *v); - -#define polyveck_decompose_vk HAETAE_NAMESPACE(polyveck_decompose_vk) -void polyveck_decompose_vk(polyveck *v0, polyveck *v); - -#define polyveck_sqnorm2 HAETAE_NAMESPACE(polyveck_sqnorm2) -uint64_t polyveck_sqnorm2(const polyveck *b); - -/* Vectors of polynomials of length L */ -typedef struct { - poly vec[L]; -} polyvecl; - -#define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) -void polyvecl_cneg(polyvecl *v, const uint8_t b); - -#define polyvecl_sqnorm2 HAETAE_NAMESPACE(polyvecl_sqnorm2) -uint64_t polyvecl_sqnorm2(const polyvecl *a); - -#define polyvecl_ntt HAETAE_NAMESPACE(polyvecl_ntt) -void polyvecl_ntt(polyvecl *x); - -#define polyvecl_highbits HAETAE_NAMESPACE(polyvecl_highbits) -void polyvecl_highbits(polyvecl *v2, const polyvecl *v); -#define polyvecl_lowbits HAETAE_NAMESPACE(polyvecl_lowbits) -void polyvecl_lowbits(polyvecl *v2, const polyvecl *v); - -#define polyvecl_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery) -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v); - - -/* Vectors of polynomials of length M */ -typedef struct { - poly vec[M]; -} polyvecm; - -#define polyvecm_ntt HAETAE_NAMESPACE(polyvecm_ntt) -void polyvecm_ntt(polyvecm *x); - -#define polyvecmk_uniform_eta HAETAE_NAMESPACE(polyvecmk_uniform_eta) -void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecm_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecm_pointwise_acc_montgomery) -void polyvecm_pointwise_acc_montgomery(poly *w, - const polyvecm *u, - const polyvecm *v); - -#define polyvecmk_sqsing_value HAETAE_NAMESPACE(polyvecmk_sqsing_value) -int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2); - -#define polyvecmk_sing_value HAETAE_NAMESPACE(polyvecmk_sing_value) -int64_t polyvecmk_sing_value(const polyvecm *s1, const polyveck *s2); - -#endif -//clang-format on diff --git a/crypto_sign/haetae2/ref/rans_byte.h b/crypto_sign/haetae2/ref/rans_byte.h deleted file mode 100644 index 403ce20e..00000000 --- a/crypto_sign/haetae2/ref/rans_byte.h +++ /dev/null @@ -1,333 +0,0 @@ -// Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014 -// -// Not intended to be "industrial strength"; just meant to illustrate the general -// idea. - -#ifndef RANS_BYTE_HEADER -#define RANS_BYTE_HEADER - -#include - -#ifdef assert -#define RansAssert assert -#else -#define RansAssert(x) -#endif - -// READ ME FIRST: -// -// This is designed like a typical arithmetic coder API, but there's three -// twists you absolutely should be aware of before you start hacking: -// -// 1. You need to encode data in *reverse* - last symbol first. rANS works -// like a stack: last in, first out. -// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give -// it a pointer to the *end* of your buffer (exclusive), and it will -// slowly move towards the beginning as more bytes are emitted. -// 3. Unlike basically any other entropy coder implementation you might -// have used, you can interleave data from multiple independent rANS -// encoders into the same bytestream without any extra signaling; -// you can also just write some bytes by yourself in the middle if -// you want to. This is in addition to the usual arithmetic encoder -// property of being able to switch models on the fly. Writing raw -// bytes can be useful when you have some data that you know is -// incompressible, and is cheaper than going through the rANS encode -// function. Using multiple rANS coders on the same byte stream wastes -// a few bytes compared to using just one, but execution of two -// independent encoders can happen in parallel on superscalar and -// Out-of-Order CPUs, so this can be *much* faster in tight decoding -// loops. -// -// This is why all the rANS functions take the write pointer as an -// argument instead of just storing it in some context struct. - -// -------------------------------------------------------------------------- - -// L ('l' in the paper) is the lower bound of our normalization interval. -// Between this and our byte-aligned emission, we use 31 (not 32!) bits. -// This is done intentionally because exact reciprocals for 31-bit uints -// fit in 32-bit uints: this permits some optimizations during encoding. -#define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval - -// State for a rANS encoder. Yep, that's all there is to it. -typedef uint32_t RansState; - -// Initialize a rANS encoder. -static inline void RansEncInit(RansState* r) -{ - *r = RANS_BYTE_L; -} - -// Renormalize the encoder. Internal function. -static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits) -{ - uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift. - if (x >= x_max) { - uint8_t* ptr = *pptr; - do { - *--ptr = (uint8_t) (x & 0xff); - x >>= 8; - } while (x >= x_max); - *pptr = ptr; - } - return x; -} - -// Encodes a single symbol with range start "start" and frequency "freq". -// All frequencies are assumed to sum to "1 << scale_bits", and the -// resulting bytes get written to ptr (which is updated). -// -// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from -// beginning to end! Likewise, the output bytestream is written *backwards*: -// ptr starts pointing at the end of the output buffer and keeps decrementing. -static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - // renormalize - RansState x = RansEncRenorm(*r, pptr, freq, scale_bits); - - // x = C(s,x) - *r = ((x / freq) << scale_bits) + (x % freq) + start; -} - -// Flushes the rANS encoder. -static inline void RansEncFlush(RansState* r, uint8_t** pptr) -{ - uint32_t x = *r; - uint8_t* ptr = *pptr; - - ptr -= 4; - ptr[0] = (uint8_t) (x >> 0); - ptr[1] = (uint8_t) (x >> 8); - ptr[2] = (uint8_t) (x >> 16); - ptr[3] = (uint8_t) (x >> 24); - - *pptr = ptr; -} - -// Initializes a rANS decoder. -// Unlike the encoder, the decoder works forwards as you'd expect. -static inline int RansDecInit(RansState* r, uint8_t** pptr) -{ - uint32_t x; - uint8_t* ptr = *pptr; - - x = ptr[0] << 0; - x |= ptr[1] << 8; - x |= ptr[2] << 16; - x |= ptr[3] << 24; - if (x < RANS_BYTE_L || (RANS_BYTE_L << 8) <= x ) - return 1; // initial state out of range - - ptr += 4; - *pptr = ptr; - *r = x; - return 0; -} - -// Returns the current cumulative frequency (map it to a symbol yourself!) -static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits) -{ - return *r & ((1u << scale_bits) - 1); -} - -// Advances in the bit stream by "popping" a single symbol with range start -// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", -// and the resulting bytes get written to ptr (which is updated). -static inline void RansDecAdvance(RansState* r, uint8_t** pptr, const uint8_t* end, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - uint32_t mask = (1u << scale_bits) - 1; - - // s, x = D(x) - uint32_t x = *r; - x = freq * (x >> scale_bits) + (x & mask) - start; - - // renormalize - if (x < RANS_BYTE_L && *pptr < end) { - uint8_t* ptr = *pptr; - do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L && ptr < end); - *pptr = ptr; - } - - *r = x; -} - -// -------------------------------------------------------------------------- - -// That's all you need for a full encoder; below here are some utility -// functions with extra convenience or optimizations. - -// Encoder symbol description -// This (admittedly odd) selection of parameters was chosen to make -// RansEncPutSymbol as cheap as possible. -typedef struct { - uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval - uint32_t rcp_freq; // Fixed-point reciprocal frequency - uint32_t bias; // Bias - uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq - uint16_t rcp_shift; // Reciprocal shift -} RansEncSymbol; - -// Decoder symbols are straightforward. -typedef struct { - uint16_t start; // Start of range. - uint16_t freq; // Symbol frequency. -} RansDecSymbol; - -// Initializes an encoder symbol to start "start" and frequency "freq" -static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - RansAssert(scale_bits <= 16); - RansAssert(start <= (1u << scale_bits)); - RansAssert(freq <= (1u << scale_bits) - start); - - // Say M := 1 << scale_bits. - // - // The original encoder does: - // x_new = (x/freq)*M + start + (x%freq) - // - // The fast encoder does (schematically): - // q = mul_hi(x, rcp_freq) >> rcp_shift (division) - // r = x - q*freq (remainder) - // x_new = q*M + bias + r (new x) - // plugging in r into x_new yields: - // x_new = bias + x + q*(M - freq) - // =: bias + x + q*cmpl_freq (*) - // - // and we can just precompute cmpl_freq. Now we just need to - // set up our parameters such that the original encoder and - // the fast encoder agree. - - s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; - s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq); - if (freq < 2) { - // freq=0 symbols are never valid to encode, so it doesn't matter what - // we set our values to. - // - // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately, - // our fixed-point reciprocal approximation can only multiply by values - // smaller than 1. - // - // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0. - // This gives: - // q = mul_hi(x, rcp_freq) >> rcp_shift - // = mul_hi(x, (1<<32) - 1)) >> 0 - // = floor(x - x/(2^32)) - // = x - 1 if 1 <= x < 2^32 - // and we know that x>0 (x=0 is never in a valid normalization interval). - // - // So we now need to choose the other parameters such that - // x_new = x*M + start - // plug it in: - // x*M + start (desired result) - // = bias + x + q*cmpl_freq (*) - // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq) - // = bias + 1 + (x - 1)*M - // = x*M + (bias + 1 - M) - // - // so we have start = bias + 1 - M, or equivalently - // bias = start + M - 1. - s->rcp_freq = ~0u; - s->rcp_shift = 0; - s->bias = start + (1 << scale_bits) - 1; - } else { - // Alverson, "Integer Division using reciprocals" - // shift=ceil(log2(freq)) - uint32_t shift = 0; - while (freq > (1u << shift)) - shift++; - - s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq); - s->rcp_shift = shift - 1; - - // With these values, 'q' is the correct quotient, so we - // have bias=start. - s->bias = start; - } -} - -// Initialize a decoder symbol to start "start" and frequency "freq" -static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq) -{ - RansAssert(start <= (1 << 16)); - RansAssert(freq <= (1 << 16) - start); - s->start = (uint16_t) start; - s->freq = (uint16_t) freq; -} - -// Encodes a given symbol. This is faster than straight RansEnc since we can do -// multiplications instead of a divide. -// -// See RansEncSymbolInit for a description of how this works. -static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym) -{ - RansAssert(sym->x_max != 0); // can't encode symbol with freq=0 - - // renormalize - uint32_t x = *r; - uint32_t x_max = sym->x_max; - if (x >= x_max) { - uint8_t* ptr = *pptr; - do { - *--ptr = (uint8_t) (x & 0xff); - x >>= 8; - } while (x >= x_max); - *pptr = ptr; - } - - // x = C(s,x) - // NOTE: written this way so we get a 32-bit "multiply high" when - // available. If you're on a 64-bit platform with cheap multiplies - // (e.g. x64), just bake the +32 into rcp_shift. - uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift; - *r = x + sym->bias + q * sym->cmpl_freq; -} - -// Equivalent to RansDecAdvance that takes a symbol. -static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, const uint8_t* end, RansDecSymbol const* sym, uint32_t scale_bits) -{ - RansDecAdvance(r, pptr, end, sym->start, sym->freq, scale_bits); -} - -// Advances in the bit stream by "popping" a single symbol with range start -// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". -// No renormalization or output happens. -static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - uint32_t mask = (1u << scale_bits) - 1; - - // s, x = D(x) - uint32_t x = *r; - *r = freq * (x >> scale_bits) + (x & mask) - start; -} - -// Equivalent to RansDecAdvanceStep that takes a symbol. -static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits) -{ - RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits); -} - -// Renormalize. -static inline void RansDecRenorm(RansState* r, uint8_t** pptr) -{ - // renormalize - uint32_t x = *r; - if (x < RANS_BYTE_L) { - uint8_t* ptr = *pptr; - do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L); - *pptr = ptr; - } - - *r = x; -} - -// Verify final state -static inline int RansDecVerify(const RansState* const r) -{ - if (*r != RANS_BYTE_L) - { - return 1; // the final state is inconsistent with the initial state - } - return 0; -} - -#endif // RANS_BYTE_HEADER \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/reduce.c b/crypto_sign/haetae2/ref/reduce.c deleted file mode 100644 index 55623734..00000000 --- a/crypto_sign/haetae2/ref/reduce.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "reduce.h" -#include "params.h" -#include - -/************************************************* - * Name: montgomery_reduce - * - * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, - * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. - * - * Arguments: - int64_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t montgomery_reduce(int64_t a) { - int32_t t; - - t = (int64_t)(int32_t)a * QINV; - t = (a - (int64_t)t * Q) >> 32; - return t; -} - -/************************************************* - * Name: caddq - * - * Description: Add Q if input coefficient is negative. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t caddq(int32_t a) { - a += (a >> 31) & Q; - return a; -} - -/************************************************* - * Name: freeze - * - * Description: For finite field element a, compute standard - * representative r = a mod^+ Q. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t freeze(int32_t a) { - int64_t t = (int64_t)a * QREC; - t = t >> 32; - t = a - t * Q; // -2Q < t < 2Q - t += (t >> 31) & DQ; // 0 <= t < 2Q - t -= ~((t - Q) >> 31) & Q; // 0 <= t < Q - return t; -} - -/************************************************* - * Name: reduce32_2q - * - * Description: compute reduction with 2Q - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t reduce32_2q(int32_t a) { - int64_t t = (int64_t)a * DQREC; - t >>= 32; - t = a - t * DQ; // -4Q < t < 4Q - t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q - t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q - t -= ~((t - Q) >> 31) & DQ; // centered representation - return (int32_t)t; -} - -/************************************************* - * Name: freeze2q - * - * Description: For finite field element a, compute standard - * representative r = a mod^+ 2Q. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t freeze2q(int32_t a) { - int64_t t = (int64_t)a * DQREC; - t >>= 32; - t = a - t * DQ; // -4Q < t < 4Q - t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q - t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q - return (int32_t)t; -} diff --git a/crypto_sign/haetae2/ref/reduce.h b/crypto_sign/haetae2/ref/reduce.h deleted file mode 100644 index 6f4a3a76..00000000 --- a/crypto_sign/haetae2/ref/reduce.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef HAETAE_REDUCE_H -#define HAETAE_REDUCE_H - -#include "params.h" -#include - -#define MONT 14321 // 2^32 % Q -#define MONTSQ 4214 // 2^64 % Q -#define QINV 940508161 // q^(-1) mod 2^32 -#define QREC 66575 // 2^32 / Q for Barrett -#define DQREC 33287 // 2^32 / DQ for Barrett - -#define montgomery_reduce HAETAE_NAMESPACE(montgomery_reduce) -int32_t montgomery_reduce(int64_t a); - -#define caddq HAETAE_NAMESPACE(caddq) -int32_t caddq(int32_t a); - -#define freeze HAETAE_NAMESPACE(freeze) -int32_t freeze(int32_t a); - -#define reduce32_2q HAETAE_NAMESPACE(reduce32_2q) -int32_t reduce32_2q(int32_t a); - -#define freeze2q HAETAE_NAMESPACE(freeze2q) -int32_t freeze2q(int32_t a); - -#endif diff --git a/crypto_sign/haetae2/ref/sampler.c b/crypto_sign/haetae2/ref/sampler.c deleted file mode 100644 index 4bb546b3..00000000 --- a/crypto_sign/haetae2/ref/sampler.c +++ /dev/null @@ -1,272 +0,0 @@ -#include "sampler.h" -#include "fixpoint.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: rej_uniform - * - * Description: Sample uniformly random coefficients in [0, Q-1] by - * performing rejection sampling on array of random bytes. - * - * Arguments: - int32_t *a: pointer to output array (allocated) - * - unsigned int len: number of coefficients to be sampled - * - const uint8_t *buf: array of random bytes - * - unsigned int buflen: length of array of random bytes - * - * Returns number of sampled coefficients. Can be smaller than len if not enough - * random bytes were given. - **************************************************/ -unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen) { - unsigned int ctr, pos; - uint32_t t; - - ctr = pos = 0; - while (ctr < len && pos + 2 <= buflen) { - t = buf[pos++]; - t |= (uint32_t)buf[pos++] << 8; - - if (t < Q) - a[ctr++] = t; - } - return ctr; -} - -/************************************************* - * Name: rej_eta - * - * Description: Sample uniformly random coefficients in [-ETA, ETA] by - * performing rejection sampling on array of random bytes. - * - * Arguments: - int32_t *a: pointer to output array (allocated) - * - unsigned int len: number of coefficients to be sampled - * - const uint8_t *buf: array of random bytes - * - unsigned int buflen: length of array of random bytes - * - * Returns number of sampled coefficients. Can be smaller than len if not enough - * random bytes were given. - **************************************************/ -static int32_t mod3(uint8_t t) { - int32_t r; - r = (t >> 4) + (t & 0xf); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -static int32_t mod3_leq26(uint8_t t) { - int32_t r; - r = (t >> 4) + (t & 0xf); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -static int32_t mod3_leq8(uint8_t t) { - int32_t r; - r = (t >> 2) + (t & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen) { - unsigned int ctr, pos; - - ctr = pos = 0; - while (ctr < len && pos < buflen) { -#if ETA == 1 - uint32_t t = buf[pos++]; - if (t < 243) { - // reduce mod 3 - a[ctr++] = mod3(t); - - if (ctr >= len) - break; - - t *= 171; // 171*3 = 1 mod 256 - t >>= 9; - a[ctr++] = mod3(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = mod3_leq26(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = mod3_leq8(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = (int32_t)t - (int32_t)3 * (t >> 1); - } -#elif ETA == 2 - uint32_t t0, t1; - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - if (t0 < 15) { - t0 = t0 - (205 * t0 >> 10) * 5; - a[ctr++] = 2 - t0; - } - if (t1 < 15 && ctr < len) { - t1 = t1 - (205 * t1 >> 10) * 5; - a[ctr++] = 2 - t1; - } -#endif - } - return ctr; -} - -static uint64_t approx_exp(const uint64_t x) { - int64_t result; - result = -0x0000B6C6340925AELL; - result = ((smulh48(result, x) + (1LL << 2)) >> 3) + 0x0000B4BD4DF85227LL; - result = ((smulh48(result, x) + (1LL << 2)) >> 3) - 0x0000887F727491E2LL; - result = ((smulh48(result, x) + (1LL << 1)) >> 2) + 0x0000AAAA643C7E8DLL; - result = ((smulh48(result, x) + (1LL << 1)) >> 2) - 0x0000AAAAA98179E6LL; - result = ((smulh48(result, x) + 1LL) >> 1) + 0x0000FFFFFFFB2E7ALL; - result = ((smulh48(result, x) + 1LL) >> 1) - 0x0000FFFFFFFFF85FLL; - result = ((smulh48(result, x))) + 0x0000FFFFFFFFFFFCLL; - return result; -} - -#define CDTLEN 64 -static const uint32_t CDT[CDTLEN] = { - 3266, 6520, 9748, 12938, 16079, 19159, 22168, 25096, -27934, 30674, 33309, 35833, 38241, 40531, 42698, 44742, -46663, 48460, 50135, 51690, 53128, 54454, 55670, 56781, -57794, 58712, 59541, 60287, 60956, 61554, 62085, 62556, -62972, 63337, 63657, 63936, 64178, 64388, 64569, 64724, -64857, 64970, 65066, 65148, 65216, 65273, 65321, 65361, -65394, 65422, 65444, 65463, 65478, 65490, 65500, 65508, -65514, 65519, 65523, 65527, 65529, 65531, 65533, 65534 -}; - - -static uint64_t sample_gauss16(const uint64_t rand16) { - unsigned int i; - uint64_t r = 0; - for (i = 0; i < CDTLEN; i++) { - r += (((uint64_t)CDT[i] - rand16) >> 63) & 1; - } - return r; -} - -#define GAUSS_RAND (72 + 16 + 48) -#define GAUSS_RAND_BYTES ((GAUSS_RAND + 7) / 8) -static int sample_gauss_sigma76(uint64_t *r, fp96_76 *sqr, - const uint8_t rand[GAUSS_RAND_BYTES]) { - const uint64_t *rand_gauss16_ptr = (uint64_t *)rand, - *rand_rej_ptr = (uint64_t *)(&rand[2]); - const uint64_t rand_gauss16 = (*rand_gauss16_ptr) & ((1ULL << 16) - 1); - const uint64_t rand_rej = (*rand_rej_ptr) & ((1ULL << 48) - 1); - uint64_t x, exp_in; - fp96_76 y; - - // sample x - x = sample_gauss16(rand_gauss16); - - // y := append x to y - // leave 16 bit for carries - y.limb48[0] = rand[8] | ((uint64_t)rand[9] << 8) | - ((uint64_t)rand[10] << 16) | ((uint64_t)rand[11] << 24) | - ((uint64_t)rand[12] << 32) | ((uint64_t)rand[13] << 40); - y.limb48[1] = - rand[14] | ((uint64_t)rand[15] << 8) | ((uint64_t)rand[16] << 16) | - (x << 24); - - // r := round y - *r = (y.limb48[0] >> 15) ^ (y.limb48[1] << 33); - *r += 1; // rounding - *r >>= 1; - - // sqr := y*y - fixpoint_square(sqr, &y); - - // sqr[1] = y^2 >> (76+48) // 34 bit - // sqr[0] = (y^2 >> 76) & ((1UL<<48)-1) // 48 bit - // exp_in := sqr - ((x*x) << 68) - exp_in = sqr->limb48[1] - ((x*x) << (68 - 48)); - exp_in <<= 20; - exp_in |= sqr->limb48[0] >> 28; - exp_in += 1; // rounding - exp_in >>= 1; - - return ((((int64_t)(rand_rej ^ - (rand_rej & 1)) // set lowest bit to zero in order to - // use it for rejection if sample==0 - - (int64_t)approx_exp(exp_in)) >> - 63) // reject with prob 1-approx_exp(exp_in) - & (((*r | -*r) >> 63) | rand_rej)) & - 1; // if the sample is zero, clear the return value with prob 1/2 -} - -int sample_gauss(uint64_t *r, fp96_76 *sqsum, const uint8_t *buf, const size_t buflen, const size_t len, const int dont_write_last) -{ - const uint8_t *pos = buf; - fp96_76 sqr; - size_t bytecnt = buflen, coefcnt = 0, cnt = 0; - int accepted; - uint64_t dummy; - - while (coefcnt < len) { - if (bytecnt < GAUSS_RAND_BYTES) { - renormalize(sqsum); - return coefcnt; - } - - if (dont_write_last && coefcnt == len-1) - { - accepted = sample_gauss_sigma76(&dummy, &sqr, pos); - } else { - accepted = sample_gauss_sigma76(&r[coefcnt], &sqr, pos); - } - cnt += 1; - coefcnt += accepted; - pos += GAUSS_RAND_BYTES; - bytecnt -= GAUSS_RAND_BYTES; - - sqsum->limb48[0] += sqr.limb48[0] & -(int64_t)accepted; - sqsum->limb48[1] += sqr.limb48[1] & -(int64_t)accepted; - } - - renormalize(sqsum); - return len; -} - -#define POLY_HYPERBALL_BUFLEN (GAUSS_RAND_BYTES * N) -#define POLY_HYPERBALL_NBLOCKS ((POLY_HYPERBALL_BUFLEN + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, - const uint8_t seed[CRHBYTES], const uint16_t nonce, - const size_t len) { - uint8_t buf[POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES]; - size_t bytecnt, coefcnt, firstflag = 1; - stream256_state state; - stream256_init(&state, seed, nonce); - - stream256_squeezeblocks(buf, POLY_HYPERBALL_NBLOCKS, &state); - for (size_t i = 0; i < len / 8; i++) { - signs[i] = buf[i]; - } - bytecnt = POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES - len / 8; - coefcnt = sample_gauss(r, sqsum, buf + len / 8, bytecnt, len, len%N); - while (coefcnt < len) { - size_t off = bytecnt % GAUSS_RAND_BYTES; - for (size_t i = 0; i < off; i++) { - buf[i] = buf[bytecnt + len/8*firstflag - off + i]; - } - stream256_squeezeblocks(buf + off, 1, &state); - bytecnt = STREAM256_BLOCKBYTES + off; - - coefcnt += sample_gauss(r + coefcnt, sqsum, buf, bytecnt, len - coefcnt, len%N); - firstflag = 0; - } -} diff --git a/crypto_sign/haetae2/ref/sampler.h b/crypto_sign/haetae2/ref/sampler.h deleted file mode 100644 index adb71bfd..00000000 --- a/crypto_sign/haetae2/ref/sampler.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef HAETAE_SAMPLER_H -#define HAETAE_SAMPLER_H - -#include "fixpoint.h" -#include "params.h" -#include "reduce.h" -#include - -#define rej_uniform HAETAE_NAMESPACE(rej_uniform) -unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen); -#define rej_eta HAETAE_NAMESPACE(rej_eta) -unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen); - -#define sample_gauss_N HAETAE_NAMESPACE(sample_gauss_N) -void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, - const uint8_t seed[CRHBYTES], const uint16_t nonce, - const size_t len); - -#endif diff --git a/crypto_sign/haetae2/ref/sign.c b/crypto_sign/haetae2/ref/sign.c deleted file mode 100644 index a53cac2b..00000000 --- a/crypto_sign/haetae2/ref/sign.c +++ /dev/null @@ -1,453 +0,0 @@ -#include "sign.h" -#include "packing.h" -#include "params.h" -#include "poly.h" -#include "polyfix.h" -#include "polymat.h" -#include "polyvec.h" -#include "randombytes.h" -#include "symmetric.h" -#include -#include -#include -#include - -/************************************************* - * Name: crypto_sign_keypair - * - * Description: Generates public and private key. - * - * Arguments: - uint8_t *pk: pointer to output public key (allocated - * array of CRYPTO_PUBLICKEYBYTES bytes) - * - uint8_t *sk: pointer to output private key (allocated - * array of CRYPTO_SECRETKEYBYTES bytes) - * - * Returns 0 (success) - **************************************************/ - -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES] = {0}; - uint16_t nonce = 0; - const uint8_t *rhoprime, *sigma, *key; - polyvecm A[K], s1, s1hat; - polyveck b, s2; -#if D > 0 - polyveck a, b0; -#else - polyveck s2hat; -#endif - xof256_state state; - - // Get entropy \rho - randombytes(seedbuf, SEEDBYTES); - - // Sample seeds with entropy \rho - xof256_absorbe_once(&state, seedbuf, SEEDBYTES); - xof256_squeeze(seedbuf, 2 * SEEDBYTES + CRHBYTES, &state); - - rhoprime = seedbuf; - sigma = rhoprime + SEEDBYTES; - key = sigma + CRHBYTES; - - // Expand Matrix A0 and vector a - polymatkm_expand(A, rhoprime); - -#if D > 0 - /********************************************** - * If there is rounding (D > 0), we need another polyveck a. - * Then, b = a + A0 * s1 + s2 and the lower D bits are - * rounded from b. The lower D bits are subsequently - * subtracted from s2. - **********************************************/ - polyveck_expand(&a, rhoprime); - -reject: - // Sample secret vectors s1 and s2 - polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); - nonce += M + K; - - // b = a + A0 * s1 + s2 mod q - s1hat = s1; - polyvecm_ntt(&s1hat); - polymatkm_pointwise_montgomery(&b, A, &s1hat); - polyveck_invntt_tomont(&b); - polyveck_add(&b, &b, &s2); - polyveck_add(&b, &b, &a); - polyveck_freeze(&b); - - // round off D bits - polyveck_decompose_vk(&b0, &b); - polyveck_sub(&s2, &s2, &b0); - - int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); - if (squared_singular_value > GAMMA * GAMMA * N) { - goto reject; - } -#else - /********************************************** - * If there is no rounding (D == 0), we store - * -2b directly in NTT domain into the public key. - **********************************************/ -reject: - // Sample secret vectors s1 and s2 - polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); - nonce += M + K; - int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); - if (squared_singular_value > GAMMA * GAMMA * N) { - goto reject; - } - - // b = A0 * s1 + s2 mod q - s1hat = s1; - s2hat = s2; - polyvecm_ntt(&s1hat); - polyveck_ntt(&s2hat); - polymatkm_pointwise_montgomery(&b, A, &s1hat); - polyveck_frommont(&b); - polyveck_add(&b, &b, &s2hat); - polyveck_double_negate(&b); - polyveck_caddq(&b); // directly compute and store NTT(-2b) -#endif - - pack_pk(pk, &b, rhoprime); - pack_sk(sk, pk, &s1, &s2, key); - - return 0; -} - -/************************************************* - * Name: crypto_sign_signature - * - * Description: Computes signature. - * - * Arguments: - uint8_t *sig: pointer to output signature (of length - * CRYPTO_BYTES) - * - size_t *siglen: pointer to output length of signature - * - uint8_t *m: pointer to message to be signed - * - size_t mlen: length of message - * - uint8_t *sk: pointer to bit-packed secret key - * - * Returns 0 (success) - **************************************************/ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, - size_t mlen, const uint8_t *sk) { - - uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; - uint8_t mu[SEEDBYTES] = {0}; - uint8_t b = 0; // one bit - uint16_t counter = 0; - uint64_t reject1, reject2; - - polyvecm s1; - polyvecl A1[K], cs1; - polyveck s2, cs2, highbits, Ay; - polyfixvecl y1, z1, z1tmp; - polyfixveck y2, z2, z2tmp; - polyvecl z1rnd; // round of z1 - polyvecl hb_z1, lb_z1; - polyveck z2rnd, h, htmp; // round of z2 - poly c, chat, z1rnd0, lsb; - - xof256_state state; - - unsigned int i; - - // Unpack secret key - unpack_sk(A1, &s1, &s2, key, sk); - - xof256_absorbe_twice(&state, sk, CRYPTO_PUBLICKEYBYTES, m, mlen); - xof256_squeeze(mu, SEEDBYTES, &state); - xof256_absorbe_twice(&state, key, SEEDBYTES, mu, SEEDBYTES); - xof256_squeeze(seedbuf, CRHBYTES, &state); - - polyvecm_ntt(&s1); - polyveck_ntt(&s2); - -reject: - - /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ - counter = polyfixveclk_sample_hyperball(&y1, &y2, &b, seedbuf, counter); - - /*------------------- 2. Compute a chanllenge c --------------------------*/ - // Round y1 and y2 - polyfixvecl_round(&z1rnd, &y1); - polyfixveck_round(&z2rnd, &y2); - - // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q - z1rnd0 = z1rnd.vec[0]; - polyvecl_ntt(&z1rnd); - polymatkl_pointwise_montgomery(&Ay, A1, &z1rnd); - polyveck_invntt_tomont(&Ay); - polyveck_double(&z2rnd); - polyveck_add(&Ay, &Ay, &z2rnd); - - // recover A * round(y) mod 2q - polyveck_poly_fromcrt(&Ay, &Ay, &z1rnd0); - polyveck_freeze2q(&Ay); - - // HighBits of (A * round(y) mod 2q) - polyveck_highbits_hint(&highbits, &Ay); - - // LSB(round(y_0) * j) - poly_lsb(&lsb, &z1rnd0); - - // Pack HighBits of A * round(y) mod 2q and LSB of round(y0) - polyveck_pack_highbits(buf, &highbits); - poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); - - // c = challenge(highbits, lsb, mu) - poly_challenge(&c, buf, mu); - - /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ - // cs = c * s = c * (si1 || s2) - cs1.vec[0] = c; - chat = c; - poly_ntt(&chat); - - for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&cs1.vec[i], &chat, &s1.vec[i - 1]); - poly_invntt_tomont(&cs1.vec[i]); - } - polyveck_poly_pointwise_montgomery(&cs2, &s2, &chat); - polyveck_invntt_tomont(&cs2); - - // z = y + (-1)^b cs = z1 + z2 - polyvecl_cneg(&cs1, b & 1); - polyveck_cneg(&cs2, b & 1); - polyfixvecl_add(&z1, &y1, &cs1); - polyfixveck_add(&z2, &y2, &cs2); - - // reject if norm(z) >= B' - reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&z1, &z2)) >> 63; - reject1 &= 1; - - polyfixvecl_double(&z1tmp, &z1); - polyfixveck_double(&z2tmp, &z2); - - polyfixfixvecl_sub(&z1tmp, &z1tmp, &y1); - polyfixfixveck_sub(&z2tmp, &z2tmp, &y2); - - // reject if norm(2z-y) < B and b' = 0 - reject2 = - (polyfixveclk_sqnorm2(&z1tmp, &z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; - reject2 &= 1; - reject2 &= (b & 0x2) >> 1; - - if (reject1 | reject2) { - goto reject; - } - - /*------------------- 4. Make a hint -------------------------------------*/ - // Round z1 and z2 - polyfixvecl_round(&z1rnd, &z1); - polyfixveck_round(&z2rnd, &z2); - - // recover A1 * round(z1) - qcj mod 2q - polyveck_double(&z2rnd); - polyveck_sub(&htmp, &Ay, &z2rnd); - polyveck_freeze2q(&htmp); - - // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) - polyveck_highbits_hint(&htmp, &htmp); - polyveck_sub(&h, &highbits, &htmp); - polyveck_caddDQ2ALPHA(&h); - - /*------------------ Decompose(z1) and Pack signature -------------------*/ - polyvecl_lowbits(&lb_z1, &z1rnd); // TODO do this in one function together! - polyvecl_highbits(&hb_z1, &z1rnd); - - if (pack_sig(sig, &c, &lb_z1, &hb_z1, - &h)) { // reject if signature is too big - goto reject; - } - *siglen = CRYPTO_BYTES; - - return 0; -} - -/************************************************* - * Name: crypto_sign - * - * Description: Compute signed message. - * - * Arguments: - uint8_t *sm: pointer to output signed message (allocated - * array with CRYPTO_BYTES + mlen bytes), - * can be equal to m - * - size_t *smlen: pointer to output length of signed - * message - * - const uint8_t *m: pointer to message to be signed - * - size_t mlen: length of message - * - const uint8_t *sk: pointer to bit-packed secret key - * - * Returns 0 (success) - **************************************************/ -int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t i; - - for (i = 0; i < mlen; ++i) - sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); - *smlen += mlen; - return 0; -} - -/************************************************* - * Name: crypto_sign_verify - * - * Description: Verifies signature. - * - * Arguments: - uint8_t *m: pointer to input signature - * - size_t siglen: length of signature - * - const uint8_t *m: pointer to message - * - size_t mlen: length of message - * - const uint8_t *pk: pointer to bit-packed public key - * - * Returns 0 if signature could be verified correctly and -1 otherwise - **************************************************/ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, - size_t mlen, const uint8_t *pk) { - unsigned int i; - uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t rhoprime[SEEDBYTES] = {0}, mu[SEEDBYTES]; - uint64_t sqnorm2; - polyvecl A1[K], z1; - polyveck b, highbits, h, z2, w; -#if D > 0 - polyveck a; -#endif - poly c, cprime, wprime; - - xof256_state state; - - // Check signature length - if (siglen != CRYPTO_BYTES) { - return -1; - } - - // Unpack public key - unpack_pk(&b, rhoprime, pk); - - // Unpack signature and Check conditions -- A1 is used only as intermediate - // buffer for the low bits - if (unpack_sig(&c, A1, &z1, &h, sig)) { - return -1; - } - - // Compose z1 out of HighBits(z1) and LowBits(z1) - for (i = 0; i < L; ++i) { - poly_compose(&z1.vec[i], &z1.vec[i], &A1[0].vec[i]); - } - - /*------------------- 1. Recover A1 --------------------------------------*/ - // A1 = (-2b + qj || 2 * A0) - polymatkl_expand(A1, rhoprime); - polymatkl_double(A1); -#if D == 1 - polyveck_expand(&a, rhoprime); - polyveck_double(&b); - polyveck_sub(&b, &a, &b); - polyveck_double(&b); - polyveck_ntt(&b); -#elif D == 0 - // no action required as b already contains -2b in NTT domain -#else -#error "Not yet implemented." -#endif - - for (i = 0; i < K; ++i) { - A1[i].vec[0] = b.vec[i]; - } - - /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ - // compute squared norm of z1 and w' before NTT - sqnorm2 = polyvecl_sqnorm2(&z1); - poly_sub(&wprime, &z1.vec[0], &c); - poly_lsb(&wprime, &wprime); - - // A1 * round(z1) - qcj mod q - polyvecl_ntt(&z1); - polymatkl_pointwise_montgomery(&highbits, A1, &z1); - polyveck_invntt_tomont(&highbits); - - // recover A1 * round(z1) - qcj mod 2q - polyveck_poly_fromcrt(&highbits, &highbits, &wprime); - polyveck_freeze2q(&highbits); - - // recover w1 - polyveck_highbits_hint(&w, &highbits); - polyveck_add(&w, &w, &h); - polyveck_csubDQ2ALPHA(&w); - - // recover \tilde{z}_2 mod q - polyveck_mul_alpha(&z2, &w); - polyveck_sub(&z2, &z2, &highbits); - poly_add(&z2.vec[0], &z2.vec[0], &wprime); - polyveck_reduce2q(&z2); - polyveck_div2(&z2); - - // check final norm of \tilde{z} - if (sqnorm2 + polyveck_sqnorm2(&z2) > B2SQ) { - return -1; - } - - /*------------------- 3. Compute c_seed' and Compare ---------------------*/ - - // Pack highBits(A * round(z) - qcj mod 2q) and h' - polyveck_pack_highbits(buf, &w); - poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); - - xof256_absorbe_twice(&state, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); - xof256_squeeze(mu, SEEDBYTES, &state); - - // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - poly_challenge(&cprime, buf, mu); - - for (i = 0; i < N; ++i) { - if (c.coeffs[i] != cprime.coeffs[i]) { - return -1; - } - } - return 0; -} - -/************************************************* - * Name: crypto_sign_open - * - * Description: Verify signed message. - * - * Arguments: - uint8_t *m: pointer to output message (allocated - * array with smlen bytes), can be equal to sm - * - size_t *mlen: pointer to output length of message - * - const uint8_t *sm: pointer to signed message - * - size_t smlen: length of signed message - * - const uint8_t *pk: pointer to bit-packed public key - * - * Returns 0 if signed message could be verified correctly and -1 otherwise - **************************************************/ -int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - size_t i; - - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - if (crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) - goto badsig; - else { - /* All good, copy msg, return 0 */ - for (i = 0; i < *mlen; ++i) - m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - for (i = 0; i < smlen; ++i) - m[i] = 0; - - return -1; -} diff --git a/crypto_sign/haetae2/ref/sign.h b/crypto_sign/haetae2/ref/sign.h deleted file mode 100644 index edfc0e80..00000000 --- a/crypto_sign/haetae2/ref/sign.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef HAETAE_SIGN_H -#define HAETAE_SIGN_H - -#include "params.h" -#include "poly.h" -#include "polymat.h" -#include "polyvec.h" -#include -#include - -#define crypto_sign_keypair HAETAE_NAMESPACE(keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -#define crypto_sign_signature HAETAE_NAMESPACE(signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, - size_t mlen, const uint8_t *sk); - -#define crypto_sign HAETAE_NAMESPACE(sign) -int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, - const uint8_t *sk); - -#define crypto_sign_verify HAETAE_NAMESPACE(verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, - size_t mlen, const uint8_t *pk); - -#define crypto_sign_open HAETAE_NAMESPACE(open) -int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif // HAETAE_SIGN_H diff --git a/crypto_sign/haetae2/ref/symmetric-shake.c b/crypto_sign/haetae2/ref/symmetric-shake.c deleted file mode 100644 index c9aeadd3..00000000 --- a/crypto_sign/haetae2/ref/symmetric-shake.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "fips202.h" -#include "params.h" -#include "symmetric.h" -#include - -void haetae_shake128_stream_init(keccak_state *state, - const uint8_t seed[SEEDBYTES], - uint16_t nonce) { - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake128_init(state); - shake128_absorb(state, seed, SEEDBYTES); - shake128_absorb(state, t, 2); - shake128_finalize(state); -} - -void haetae_shake256_stream_init(keccak_state *state, - const uint8_t seed[CRHBYTES], uint16_t nonce) { - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake256_init(state); - shake256_absorb(state, seed, CRHBYTES); - shake256_absorb(state, t, 2); - shake256_finalize(state); -} - -void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, - size_t in1len, const uint8_t *in2, - size_t in2len) { - shake256_init(state); - shake256_absorb(state, in1, in1len); - shake256_absorb(state, in2, in2len); - shake256_finalize(state); -} diff --git a/crypto_sign/haetae2/ref/symmetric.h b/crypto_sign/haetae2/ref/symmetric.h deleted file mode 100644 index b3b9c37d..00000000 --- a/crypto_sign/haetae2/ref/symmetric.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include "params.h" -#include -#include "fips202.h" - -// Cryptographic XOF function: shake256 -typedef keccak_state xof256_state; - -#define haetae_shake256_absorb_twice \ - HAETAE_NAMESPACE(haetae_shake256_absorb_twice) -void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, - size_t in1len, const uint8_t *in2, size_t in2len); - -#define XOF256_BLOCKBYTES SHAKE256_RATE - -#define xof256_absorbe_once(STATE, IN, IN_LEN) \ - shake256_absorb_once(STATE, IN, IN_LEN) -#define xof256_absorbe_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) \ - haetae_shake256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) -#define xof256_squeeze(OUT, OUT_LEN, STATE) \ - shake256_squeeze(OUT, OUT_LEN, STATE) -#define xof256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - - -// Stream function: aes256 or shake128|256 -#ifdef HAETAE_USE_AES // stream: aes256 - -#include "aes256ctr.h" - -typedef aes256ctr_ctx stream128_state; -typedef aes256ctr_ctx stream256_state; - -#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES -#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES - -#define stream128_init(STATE, SEED, NONCE) \ - aes256ctr_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - aes256ctr_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#else // stream: shake128 and shake256 - -typedef keccak_state stream128_state; -typedef keccak_state stream256_state; - -#define haetae_shake128_stream_init \ - HAETAE_NAMESPACE(haetae_shake128_stream_init) -void haetae_shake128_stream_init(keccak_state *state, - const uint8_t seed[SEEDBYTES], uint16_t nonce); - -#define haetae_shake256_stream_init \ - HAETAE_NAMESPACE(haetae_shake256_stream_init) -void haetae_shake256_stream_init(keccak_state *state, - const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define STREAM128_BLOCKBYTES SHAKE128_RATE -#define STREAM256_BLOCKBYTES SHAKE256_RATE - -#define stream128_init(STATE, SEED, NONCE) \ - haetae_shake128_stream_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - haetae_shake256_stream_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#endif // stream - -#endif //SYMMETRIC_H - From c2438e02db23ccdc6290ec92449596feb0632b10 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 24 Nov 2023 15:41:59 +0800 Subject: [PATCH 035/107] turn into symlinks --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 94cf8339..c1afb82d 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 94cf833955d5687ca7b45b822a8fee8fc0dae27f +Subproject commit c1afb82d91f66ba6ba35c8d88abf9aa66403e913 From 694a4a8d2889c82f74c2d299e0341ded719e6c5d Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 24 Nov 2023 15:52:07 +0800 Subject: [PATCH 036/107] eliminate static memory --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index c1afb82d..739b6dc0 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit c1afb82d91f66ba6ba35c8d88abf9aa66403e913 +Subproject commit 739b6dc02cbbf5250a127bc8cf23e67c6bb20e42 From 71f0daa874b1226215c219deecd3e230ed170e5a Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 24 Nov 2023 08:58:50 +0100 Subject: [PATCH 037/107] Add biscuit --- mupq | 2 +- skiplist.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 5850427a..4ba92e08 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 5850427a3d608931744cddd6cee5ca02322bdc13 +Subproject commit 4ba92e08551453e89df2e870d631475c6b7506bb diff --git a/skiplist.py b/skiplist.py index 4b021dff..3d7e1f07 100644 --- a/skiplist.py +++ b/skiplist.py @@ -225,4 +225,10 @@ {'scheme': 'cross-sha3-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, {'scheme': 'cross-sha3-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, {'scheme': 'cross-sha3-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'biscuit128f', 'implementation': 'ref', 'estmemory': 145408}, + {'scheme': 'biscuit128s', 'implementation': 'ref', 'estmemory': 1099776}, + {'scheme': 'biscuit192f', 'implementation': 'ref', 'estmemory': 282624}, + {'scheme': 'biscuit192s', 'implementation': 'ref', 'estmemory': 2257920}, + {'scheme': 'biscuit256f', 'implementation': 'ref', 'estmemory': 505856}, + {'scheme': 'biscuit256s', 'implementation': 'ref', 'estmemory': 4004864}, ] From 8821d31bdf63967572f3239b991a5993ebc888ea Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 24 Nov 2023 09:05:20 +0100 Subject: [PATCH 038/107] Add MiRitH --- mupq | 2 +- skiplist.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 5850427a..4ba92e08 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 5850427a3d608931744cddd6cee5ca02322bdc13 +Subproject commit 4ba92e08551453e89df2e870d631475c6b7506bb diff --git a/skiplist.py b/skiplist.py index 4b021dff..f8a1e590 100644 --- a/skiplist.py +++ b/skiplist.py @@ -201,6 +201,36 @@ {'scheme': 'ascon-sign-192s-robust', 'implementation': 'ref', 'estmemory': 23552}, {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, + {'scheme': 'mirith_IIIa_fast', 'implementation': 'ref', 'estmemory': 287744}, + {'scheme': 'mirith_IIIa_short', 'implementation': 'ref', 'estmemory': 2197504}, + {'scheme': 'mirith_IIIb_fast', 'implementation': 'ref', 'estmemory': 320512}, + {'scheme': 'mirith_IIIb_short', 'implementation': 'ref', 'estmemory': 2386944}, + {'scheme': 'mirith_Ia_fast', 'implementation': 'ref', 'estmemory': 134144}, + {'scheme': 'mirith_Ia_short', 'implementation': 'ref', 'estmemory': 1019904}, + {'scheme': 'mirith_Ib_fast', 'implementation': 'ref', 'estmemory': 163840}, + {'scheme': 'mirith_Ib_short', 'implementation': 'ref', 'estmemory': 1195008}, + {'scheme': 'mirith_Va_fast', 'implementation': 'ref', 'estmemory': 519168}, + {'scheme': 'mirith_Va_short', 'implementation': 'ref', 'estmemory': 3816448}, + {'scheme': 'mirith_Vb_fast', 'implementation': 'ref', 'estmemory': 572416}, + {'scheme': 'mirith_Vb_short', 'implementation': 'ref', 'estmemory': 4117504}, + {'scheme': 'mirith_hypercube_IIIa_fast', 'implementation': 'ref', 'estmemory': 188416}, + {'scheme': 'mirith_hypercube_IIIa_short', 'implementation': 'ref', 'estmemory': 502784}, + {'scheme': 'mirith_hypercube_IIIa_shorter', 'implementation': 'ref', 'estmemory': 3894272}, + {'scheme': 'mirith_hypercube_IIIb_fast', 'implementation': 'ref', 'estmemory': 211968}, + {'scheme': 'mirith_hypercube_IIIb_short', 'implementation': 'ref', 'estmemory': 526336}, + {'scheme': 'mirith_hypercube_IIIb_shorter', 'implementation': 'ref', 'estmemory': 3916800}, + {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'ref', 'estmemory': 89088}, + {'scheme': 'mirith_hypercube_Ia_short', 'implementation': 'ref', 'estmemory': 227328}, + {'scheme': 'mirith_hypercube_Ia_shorter', 'implementation': 'ref', 'estmemory': 1779712}, + {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'ref', 'estmemory': 109568}, + {'scheme': 'mirith_hypercube_Ib_short', 'implementation': 'ref', 'estmemory': 247808}, + {'scheme': 'mirith_hypercube_Ib_shorter', 'implementation': 'ref', 'estmemory': 1800192}, + {'scheme': 'mirith_hypercube_Va_fast', 'implementation': 'ref', 'estmemory': 344064}, + {'scheme': 'mirith_hypercube_Va_short', 'implementation': 'ref', 'estmemory': 878592}, + {'scheme': 'mirith_hypercube_Va_shorter', 'implementation': 'ref', 'estmemory': 4217856}, + {'scheme': 'mirith_hypercube_Vb_fast', 'implementation': 'ref', 'estmemory': 382976}, + {'scheme': 'mirith_hypercube_Vb_short', 'implementation': 'ref', 'estmemory': 916480}, + {'scheme': 'mirith_hypercube_Vb_shorter', 'implementation': 'ref', 'estmemory': 4218880}, {'scheme': 'cross-sha3-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, {'scheme': 'cross-sha3-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, {'scheme': 'cross-sha3-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, From 991a5b678c7b3d18bf1d84675e4c0fcc532c360c Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 24 Nov 2023 09:53:06 +0100 Subject: [PATCH 039/107] Update skiplist for bike --- skiplist.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skiplist.py b/skiplist.py index 4b021dff..ab9c9990 100644 --- a/skiplist.py +++ b/skiplist.py @@ -11,8 +11,10 @@ {'scheme': 'kyber768', 'implementation': 'm4fstack', 'estmemory': 9216}, {'scheme': 'kyber768-90s', 'implementation': 'm4fspeed', 'estmemory': 14336}, {'scheme': 'kyber768-90s', 'implementation': 'm4fstack', 'estmemory': 11264}, + {'scheme': 'bikel3', 'implementation': 'opt', 'estmemory': 175104}, + {'scheme': 'bikel1', 'implementation': 'opt', 'estmemory': 90112}, + {'scheme': 'bikel3', 'implementation': 'm4f', 'estmemory': 194560}, {'scheme': 'bikel1', 'implementation': 'm4f', 'estmemory': 103424}, - {'scheme': 'bikel3', 'implementation': 'm4f', 'estmemory': 181248}, {'scheme': 'frodokem640aes', 'implementation': 'm4', 'estmemory': 124928}, {'scheme': 'firesaber', 'implementation': 'm4f', 'estmemory': 15360}, {'scheme': 'frodokem640shake', 'implementation': 'm4', 'estmemory': 113664}, @@ -38,9 +40,7 @@ {'scheme': 'sntrup653', 'implementation': 'm4f', 'estmemory': 97280}, {'scheme': 'sntrup1277', 'implementation': 'm4f', 'estmemory': 99328}, {'scheme': 'sntrup1013', 'implementation': 'm4f', 'estmemory': 110592}, - {'scheme': 'bikel1', 'implementation': 'opt', 'estmemory': 90112}, {'scheme': 'sikep434', 'implementation': 'opt', 'estmemory': 10240}, - {'scheme': 'bikel3', 'implementation': 'opt', 'estmemory': 175104}, {'scheme': 'sikep610', 'implementation': 'opt', 'estmemory': 14336}, {'scheme': 'sikep503', 'implementation': 'opt', 'estmemory': 10240}, {'scheme': 'sikep751', 'implementation': 'opt', 'estmemory': 16384}, From dc26f540ad2d40b70c86d59e9d54eaaab2a2eeed Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 24 Nov 2023 09:56:49 +0100 Subject: [PATCH 040/107] Update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 5850427a..4ba92e08 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 5850427a3d608931744cddd6cee5ca02322bdc13 +Subproject commit 4ba92e08551453e89df2e870d631475c6b7506bb From c8b34566d29981bb9be05ee072e4bb9dd5abc1fb Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 24 Nov 2023 17:11:57 +0800 Subject: [PATCH 041/107] do expensive pre-computation only once --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 739b6dc0..5a1c0a1a 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 739b6dc02cbbf5250a127bc8cf23e67c6bb20e42 +Subproject commit 5a1c0a1ab1ebc79fab4924adeb6f11c46fdff950 From bd9b47d6d96582fbc2926dd76d99b07a92520913 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Sat, 25 Nov 2023 15:24:26 +0800 Subject: [PATCH 042/107] recompute static tables --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 97c1c0a3..26d9df9d 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 97c1c0a3c42d9102384717510d1f5d22faf344b2 +Subproject commit 26d9df9d7dbaf47564ec78acd15945ac1b7162d0 From 76f069c9281fd5ab5f4ffd8fbc0b86e4d140f0d9 Mon Sep 17 00:00:00 2001 From: Till Eifert Date: Fri, 27 Oct 2023 07:48:26 +0200 Subject: [PATCH 043/107] stm32f415: enable hw rng and extend clock setup update interface.py platform_memory to handle stm32f415 --- common/hal-opencm3.c | 25 ++++++++++++++++++++++--- interface.py | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/common/hal-opencm3.c b/common/hal-opencm3.c index 8bc1e597..ec80ad01 100644 --- a/common/hal-opencm3.c +++ b/common/hal-opencm3.c @@ -66,6 +66,7 @@ const struct rcc_clock_scale benchmarkclock = { #include #include #include +#include #define SERIAL_GPIO GPIOA #define SERIAL_USART USART1 @@ -143,13 +144,31 @@ static void clock_setup(enum clock_mode clock) rcc_apb2_frequency = 7372800; _clock_freq = 7372800; rcc_set_hpre(RCC_CFGR_HPRE_DIV_NONE); -#if defined(STM32F3) +# if defined(STM32F3) rcc_set_ppre1(RCC_CFGR_PPRE1_DIV_NONE); rcc_set_ppre2(RCC_CFGR_PPRE2_DIV_NONE); -#elif defined(STM32F4) +# elif defined(STM32F4) rcc_set_ppre1(RCC_CFGR_PPRE_DIV_NONE); rcc_set_ppre2(RCC_CFGR_PPRE_DIV_NONE); -#endif +# if defined(STM32F415RGT6) + flash_set_ws(FLASH_ACR_LATENCY_0WS); + rcc_set_sysclk_source(RCC_CFGR_SW_HSE); + rcc_wait_for_sysclk_status(RCC_HSE); + + /* HSI and PLL needed for RNG + that's why we can't use rcc_clock_setup_pll()*/ + rcc_osc_on(RCC_HSI); + rcc_wait_for_osc_ready(RCC_HSI); + rcc_osc_off(RCC_PLL); + rcc_set_main_pll_hse(12, 196, 4, 7, 0); + + rcc_osc_on(RCC_PLL); + rcc_wait_for_osc_ready(RCC_PLL); + + rcc_periph_clock_enable(RCC_RNG); + rng_enable(); +# endif +# endif rcc_set_sysclk_source(RCC_CFGR_SW_HSE); rcc_wait_for_sysclk_status(RCC_HSE); #elif defined(NUCLEO_BOARD) diff --git a/interface.py b/interface.py index 64278507..2b386caf 100644 --- a/interface.py +++ b/interface.py @@ -66,6 +66,7 @@ class M4Settings(mupq.PlatformSettings): 'stm32f4discovery': 128*1024, 'nucleo-l476rg': 128*1024, 'cw308t-stm32f3': 64*1024, + 'cw308t-stm32f415': 192*1024, 'mps2-an386': 4096*1024, 'nucleo-l4r5zi': 640*1024 } From 258a11f1525226d5003f2e13a6a3d36b984ff82e Mon Sep 17 00:00:00 2001 From: Marc <134507752+mmoeller23@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:36:32 +0100 Subject: [PATCH 044/107] add ref implementation for haetae2 stack usage (keypair/sign/verify): * haetae2: 26152 / 83128 / 29856 --- crypto_sign/haetae2/ref/api.h | 6 + crypto_sign/haetae2/ref/config.h | 19 + crypto_sign/haetae2/ref/decompose.c | 69 ++ crypto_sign/haetae2/ref/decompose.h | 16 + crypto_sign/haetae2/ref/encoding.c | 227 +++++++ crypto_sign/haetae2/ref/encoding.h | 17 + crypto_sign/haetae2/ref/fft.c | 231 +++++++ crypto_sign/haetae2/ref/fft.h | 19 + crypto_sign/haetae2/ref/fips202.c | 746 ++++++++++++++++++++++ crypto_sign/haetae2/ref/fips202.h | 57 ++ crypto_sign/haetae2/ref/fixpoint.c | 140 ++++ crypto_sign/haetae2/ref/fixpoint.h | 126 ++++ crypto_sign/haetae2/ref/ntt.c | 95 +++ crypto_sign/haetae2/ref/ntt.h | 13 + crypto_sign/haetae2/ref/packing.c | 280 ++++++++ crypto_sign/haetae2/ref/packing.h | 25 + crypto_sign/haetae2/ref/params.h | 116 ++++ crypto_sign/haetae2/ref/poly.c | 659 +++++++++++++++++++ crypto_sign/haetae2/ref/poly.h | 80 +++ crypto_sign/haetae2/ref/polyfix.c | 292 +++++++++ crypto_sign/haetae2/ref/polyfix.h | 61 ++ crypto_sign/haetae2/ref/polymat.c | 73 +++ crypto_sign/haetae2/ref/polymat.h | 28 + crypto_sign/haetae2/ref/polyvec.c | 543 ++++++++++++++++ crypto_sign/haetae2/ref/polyvec.h | 129 ++++ crypto_sign/haetae2/ref/rans_byte.h | 333 ++++++++++ crypto_sign/haetae2/ref/reduce.c | 92 +++ crypto_sign/haetae2/ref/reduce.h | 28 + crypto_sign/haetae2/ref/sampler.c | 272 ++++++++ crypto_sign/haetae2/ref/sampler.h | 21 + crypto_sign/haetae2/ref/sign.c | 453 +++++++++++++ crypto_sign/haetae2/ref/sign.h | 30 + crypto_sign/haetae2/ref/symmetric-shake.c | 38 ++ crypto_sign/haetae2/ref/symmetric.h | 78 +++ 34 files changed, 5412 insertions(+) create mode 100644 crypto_sign/haetae2/ref/api.h create mode 100644 crypto_sign/haetae2/ref/config.h create mode 100644 crypto_sign/haetae2/ref/decompose.c create mode 100644 crypto_sign/haetae2/ref/decompose.h create mode 100644 crypto_sign/haetae2/ref/encoding.c create mode 100644 crypto_sign/haetae2/ref/encoding.h create mode 100644 crypto_sign/haetae2/ref/fft.c create mode 100644 crypto_sign/haetae2/ref/fft.h create mode 100644 crypto_sign/haetae2/ref/fips202.c create mode 100644 crypto_sign/haetae2/ref/fips202.h create mode 100644 crypto_sign/haetae2/ref/fixpoint.c create mode 100644 crypto_sign/haetae2/ref/fixpoint.h create mode 100644 crypto_sign/haetae2/ref/ntt.c create mode 100644 crypto_sign/haetae2/ref/ntt.h create mode 100644 crypto_sign/haetae2/ref/packing.c create mode 100644 crypto_sign/haetae2/ref/packing.h create mode 100644 crypto_sign/haetae2/ref/params.h create mode 100644 crypto_sign/haetae2/ref/poly.c create mode 100644 crypto_sign/haetae2/ref/poly.h create mode 100644 crypto_sign/haetae2/ref/polyfix.c create mode 100644 crypto_sign/haetae2/ref/polyfix.h create mode 100644 crypto_sign/haetae2/ref/polymat.c create mode 100644 crypto_sign/haetae2/ref/polymat.h create mode 100644 crypto_sign/haetae2/ref/polyvec.c create mode 100644 crypto_sign/haetae2/ref/polyvec.h create mode 100644 crypto_sign/haetae2/ref/rans_byte.h create mode 100644 crypto_sign/haetae2/ref/reduce.c create mode 100644 crypto_sign/haetae2/ref/reduce.h create mode 100644 crypto_sign/haetae2/ref/sampler.c create mode 100644 crypto_sign/haetae2/ref/sampler.h create mode 100644 crypto_sign/haetae2/ref/sign.c create mode 100644 crypto_sign/haetae2/ref/sign.h create mode 100644 crypto_sign/haetae2/ref/symmetric-shake.c create mode 100644 crypto_sign/haetae2/ref/symmetric.h diff --git a/crypto_sign/haetae2/ref/api.h b/crypto_sign/haetae2/ref/api.h new file mode 100644 index 00000000..28d58fca --- /dev/null +++ b/crypto_sign/haetae2/ref/api.h @@ -0,0 +1,6 @@ +#ifndef API_H +#define API_H + +#include "sign.h" + +#endif diff --git a/crypto_sign/haetae2/ref/config.h b/crypto_sign/haetae2/ref/config.h new file mode 100644 index 00000000..52c9e87b --- /dev/null +++ b/crypto_sign/haetae2/ref/config.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 2 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif +#endif diff --git a/crypto_sign/haetae2/ref/decompose.c b/crypto_sign/haetae2/ref/decompose.c new file mode 100644 index 00000000..467767e5 --- /dev/null +++ b/crypto_sign/haetae2/ref/decompose.c @@ -0,0 +1,69 @@ +#include "decompose.h" +#include "params.h" +#include + +/************************************************* + * Name: decompose_z1 + * + * Description: For finite field element r, compute high and lowbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *lowbits: pointer to output element lb + * - int32_t *highbits: pointer to output element hb + **************************************************/ +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r) { + const int alpha = 256; // TODO magic numbers! + const int log_alpha = 8; + + int32_t lb, center; + uint32_t alpha_mask = alpha - 1; + + lb = r & alpha_mask; + center = ((alpha >> 1) - (lb + 1)) >> 31; // if lb >= HALF_ALPHA + lb -= alpha & center; + *lowbits = lb; + *highbits = (r + (alpha >> 1)) >> log_alpha; +} + +/************************************************* + * Name: decompose_hint + * + * Description: For finite field element r, compute highbits + * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. + * + * Arguments: - int32_t r: input element + * - int32_t *highbits: pointer to output element hb + **************************************************/ + +void decompose_hint(int32_t *highbits, const int32_t r) { + int32_t hb, edgecase; + + hb = (r + HALF_ALPHA_HINT) >> LOG_ALPHA_HINT; + edgecase = + ((DQ - 2) / ALPHA_HINT - (hb + 1)) >> 31; // if hb == (DQ-2)/ALPHA + hb -= (DQ - 2) / ALPHA_HINT & edgecase; // hb = 0 + + *highbits = hb; +} + +/************************************************* + * Name: decompose_vk + * + * Description: For finite field element a, compute a0, a1 such that + * a mod^+ Q = a1*2^D + a0 with -2^{D-1} <= a0 < 2^{D-1}. + * Assumes a to be standard representative. + * + * Arguments: - int32_t a: input element + * - int32_t *a0: pointer to output element a0 + * + * Returns a1 + **************************************************/ +int32_t decompose_vk(int32_t *a0, const int32_t a) { +#if D > 1 +#error "Only implemented for D = 1" +#endif + *a0 = a & 1; + *a0 -= ((a >> 1) & *a0) << 1; + return (a - *a0) >> 1; +} diff --git a/crypto_sign/haetae2/ref/decompose.h b/crypto_sign/haetae2/ref/decompose.h new file mode 100644 index 00000000..67146cf1 --- /dev/null +++ b/crypto_sign/haetae2/ref/decompose.h @@ -0,0 +1,16 @@ +#ifndef HAETAE_ROUNDING_H +#define HAETAE_ROUNDING_H + +#include "params.h" +#include + +#define decompose_z1 HAETAE_NAMESPACE(decompose_z1) +void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r); + +#define decompose_hint HAETAE_NAMESPACE(decompose_hint) +void decompose_hint(int32_t *highbits, const int32_t r); + +#define decompose_vk HAETAE_NAMESPACE(decompose_vk) +int32_t decompose_vk(int32_t *a0, const int32_t a); + +#endif diff --git a/crypto_sign/haetae2/ref/encoding.c b/crypto_sign/haetae2/ref/encoding.c new file mode 100644 index 00000000..ca6a182f --- /dev/null +++ b/crypto_sign/haetae2/ref/encoding.c @@ -0,0 +1,227 @@ +#include "encoding.h" +#include "params.h" +#include "rans_byte.h" + +#include +#include +#include + +#define SCALE_BITS 10 +#define SCALE (1u << SCALE_BITS) + +#if HAETAE_MODE == 2 +#define M_H 13 +#define OFFSET_H 239 +#define M_HB_Z1 13 +#define OFFSET_HB_Z1 6 +static RansEncSymbol esyms_h[M_H] = {{801112064, -1416664605, 0, 642, 8}, {515899392, -2060187564, 382, 778, 7}, {136314880, -66076419, 628, 959, 6}, {14680064, -1840700269, 693, 1017, 2}, {2097152, -1, 1723, 1023, 0}, {2097152, -1, 1724, 1023, 0}, {2097152, -1, 1725, 1023, 0}, {2097152, -1, 1726, 1023, 0}, {2097152, -1, 1727, 1023, 0}, {2097152, -1, 1728, 1023, 0}, {14680064, -1840700269, 706, 1017, 2}, {136314880, -66076419, 713, 959, 6}, {515899392, -2060187564, 778, 778, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 382}, {382, 246}, {628, 65}, {693, 7}, {700, 1}, {701, 1}, {702, 1}, {703, 1}, {704, 1}, {705, 1}, {706, 7}, {713, 65}, {778, 246}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {10485760, -858993459, 3, 1019, 2}, {121634816, -1925330167, 8, 966, 5}, {515899392, -2060187564, 66, 778, 7}, {834666496, -1532375266, 312, 626, 8}, {517996544, -2069235255, 710, 777, 7}, {123731968, -1965493508, 957, 965, 5}, {10485760, -858993459, 1016, 1019, 2}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 5}, {8, 58}, {66, 246}, {312, 398}, {710, 247}, {957, 59}, {1016, 5}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 11, 12, }; + +#elif HAETAE_MODE == 3 +#define M_H 17 +#define OFFSET_H 235 +#define M_HB_Z1 17 +#define OFFSET_HB_Z1 8 +static RansEncSymbol esyms_h[M_H] = {{557842432, -161464935, 0, 758, 8}, {446693376, -1713954085, 266, 811, 7}, {236978176, -1862419446, 479, 911, 6}, {83886080, -858993459, 592, 984, 5}, {18874368, -477218588, 632, 1015, 3}, {2097152, -1, 1664, 1023, 0}, {2097152, -1, 1665, 1023, 0}, {2097152, -1, 1666, 1023, 0}, {2097152, -1, 1667, 1023, 0}, {2097152, -1, 1668, 1023, 0}, {2097152, -1, 1669, 1023, 0}, {2097152, -1, 1670, 1023, 0}, {2097152, -1, 1671, 1023, 0}, {18874368, -477218588, 649, 1015, 3}, {83886080, -858993459, 658, 984, 5}, {236978176, -1862419446, 698, 911, 6}, {446693376, -1713954085, 811, 811, 7}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 266}, {266, 213}, {479, 113}, {592, 40}, {632, 9}, {641, 1}, {642, 1}, {643, 1}, {644, 1}, {645, 1}, {646, 1}, {647, 1}, {648, 1}, {649, 9}, {658, 40}, {698, 113}, {811, 213}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {16777216, -2147483648, 4, 1016, 2}, {77594624, -580400985, 12, 987, 5}, {234881024, -1840700269, 49, 912, 6}, {452984832, -1749801490, 161, 808, 7}, {564133888, -207563475, 377, 755, 8}, {452984832, -1749801490, 646, 808, 7}, {234881024, -1840700269, 862, 912, 6}, {79691776, -678152730, 974, 986, 5}, {16777216, -2147483648, 1012, 1016, 2}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 8}, {12, 37}, {49, 112}, {161, 216}, {377, 269}, {646, 216}, {862, 112}, {974, 38}, {1012, 8}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, }; + +#elif HAETAE_MODE == 5 +#define M_H 33 +#define OFFSET_H 471 +#define M_HB_Z1 19 +#define OFFSET_HB_Z1 9 +static RansEncSymbol esyms_h[M_H] = {{255852544, -2041869698, 0, 902, 6}, {245366784, -1945583475, 122, 907, 6}, {213909504, -1600085855, 239, 922, 6}, {169869312, -901412889, 341, 943, 6}, {123731968, -1965493508, 422, 965, 5}, {81788928, -770891565, 481, 985, 5}, {48234496, -1307163959, 520, 1001, 4}, {27262976, -1651910498, 543, 1011, 3}, {12582912, -1431655765, 556, 1018, 2}, {6291456, -1431655765, 562, 1021, 1}, {2097152, -1, 1588, 1023, 0}, {2097152, -1, 1589, 1023, 0}, {2097152, -1, 1590, 1023, 0}, {2097152, -1, 1591, 1023, 0}, {2097152, -1, 1592, 1023, 0}, {2097152, -1, 1593, 1023, 0}, {2097152, -1, 1594, 1023, 0}, {2097152, -1, 1595, 1023, 0}, {2097152, -1, 1596, 1023, 0}, {2097152, -1, 1597, 1023, 0}, {2097152, -1, 1598, 1023, 0}, {2097152, -1, 1599, 1023, 0}, {2097152, -1, 1600, 1023, 0}, {2097152, -1, 1601, 1023, 0}, {6291456, -1431655765, 579, 1021, 1}, {12582912, -1431655765, 582, 1018, 2}, {27262976, -1651910498, 588, 1011, 3}, {50331648, -1431655765, 601, 1000, 4}, {81788928, -770891565, 625, 985, 5}, {123731968, -1965493508, 664, 965, 5}, {169869312, -901412889, 723, 943, 6}, {213909504, -1600085855, 804, 922, 6}, {247463936, -1965493508, 906, 906, 6}, }; +static RansDecSymbol dsyms_h[M_H] = {{0, 122}, {122, 117}, {239, 102}, {341, 81}, {422, 59}, {481, 39}, {520, 23}, {543, 13}, {556, 6}, {562, 3}, {565, 1}, {566, 1}, {567, 1}, {568, 1}, {569, 1}, {570, 1}, {571, 1}, {572, 1}, {573, 1}, {574, 1}, {575, 1}, {576, 1}, {577, 1}, {578, 1}, {579, 3}, {582, 6}, {588, 13}, {601, 24}, {625, 39}, {664, 59}, {723, 81}, {804, 102}, {906, 118}, }; +static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; +static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {4194304, -2147483648, 4, 1022, 0}, {27262976, -1651910498, 6, 1011, 3}, {100663296, -1431655765, 19, 976, 5}, {247463936, -1965493508, 67, 906, 6}, {427819008, -1600085855, 185, 820, 7}, {513802240, -2051066014, 389, 779, 7}, {427819008, -1600085855, 634, 820, 7}, {247463936, -1965493508, 838, 906, 6}, {100663296, -1431655765, 956, 976, 5}, {29360128, -1840700269, 1004, 1010, 3}, {4194304, -2147483648, 1018, 1022, 0}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; +static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 2}, {6, 13}, {19, 48}, {67, 118}, {185, 204}, {389, 245}, {634, 204}, {838, 118}, {956, 48}, {1004, 14}, {1018, 2}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; +static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 15, 16, 17, 18, }; + +#endif // HAETAE_MODE +#define H_CUT ((M_H -1) >>1) + +/************************************************* + * Name: encode_h + * + * Description: rANS encode polynomial vector h + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *h: pointer to polynomial vector h + **************************************************/ +uint16_t encode_h(uint8_t *buf, const int32_t *h) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + uint8_t encoding[size_h]; // size_h is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_h; // end of encoding buffer + + for (size_t i = size_h; i > 0; i--) { + tmp = h[i - 1]; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(H_CUT < tmp && tmp <= H_CUT + OFFSET_H) { + return 0; + } + // map the upper likely part of symbols next to the lower part + // to have a dense and compact distribution: + tmp = (tmp > (H_CUT + OFFSET_H)) ? tmp - OFFSET_H : tmp; + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_h[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_h - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_h + * + * Description: rANS decode polynomial vector h + * + * Arguments: - int32_t *h: pointer to polynomial vector h + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_h = N * K; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_h; i++) { + s = symbol_h[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_H) { + return 1; // invalid symbol + } + tmp = (H_CUT < tmp) ? (tmp + OFFSET_H) : tmp; + h[i] = tmp; + RansDecAdvanceSymbol(&rans, (uint8_t **) &buf, buf_end, &dsyms_h[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} + +/************************************************* + * Name: encode_hb_z1 + * + * Description: rANS encode polynomial vector HighBits(z1) + * + * Arguments: - uint8_t *buf: pointer to output buffer + * - const int32_t *hb_z1: pointer to polynomial vector + *HighBits(z1) + **************************************************/ +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1) { + size_t size_encoded; + RansState rans; + uint8_t *ptr; + size_t size_hb_z1 = N * L; + int8_t s; + int32_t tmp; + uint8_t encoding[size_hb_z1]; // size_hb_z1 is a loose upper bound + + RansEncInit(&rans); + ptr = encoding + size_hb_z1; // end of output buffer + + for (size_t i = size_hb_z1; i > 0; i--) { + // from centered to positive representation: + tmp = hb_z1[i - 1] + OFFSET_HB_Z1; + // check for very unlikely values that we do not encode + // to make the encoding cheaper : + if(tmp < 0 || M_HB_Z1 <= tmp) { + return 0; + } + s = (uint8_t) tmp; + + RansEncPutSymbol(&rans, &ptr, &esyms_hb_z1[s]); + // check that at least 4 byte remain for memory safety: + if (ptr < encoding + 4) + { + return 0; + } + } + RansEncFlush(&rans, &ptr); + + size_encoded = encoding + size_hb_z1 - ptr; + memcpy(buf, ptr, size_encoded); + return size_encoded; +} + +/************************************************* + * Name: decode_hb_z1 + * + * Description: rANS decode polynomial vector HighBits(z1) + * + * Arguments: - int32_t *hb_z1: pointer to polynomial vector HighBits(z1) + * - uint8_t *buf: pointer to output buffer + **************************************************/ +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in) { + size_t size_used; + RansState rans; + size_t size_hb_z1 = N * L; + uint32_t tmp; + uint8_t s; + const uint8_t *buf_start = buf; + const uint8_t *buf_end = buf + size_in; + + if(RansDecInit(&rans, (uint8_t **) &buf)) { + return 1; // corrupted initial state + } + + for (size_t i = 0; i < size_hb_z1; i++) { + s = symbol_hb_z1[RansDecGet(&rans, SCALE_BITS)]; + tmp = (uint32_t) s; + if(tmp >= M_HB_Z1) { + return 1; // invalid symbol + } + // from positive to centered representation: + hb_z1[i] = tmp - OFFSET_HB_Z1; + RansDecAdvanceSymbol(&rans, (uint8_t **)&buf, buf_end, &dsyms_hb_z1[s], SCALE_BITS); + } + + if(RansDecVerify(&rans)) { + return 1; // final state not correct + } + + size_used = buf - buf_start; + if(size_used != size_in) { + return 1; // size does not match + } + return 0; +} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/encoding.h b/crypto_sign/haetae2/ref/encoding.h new file mode 100644 index 00000000..b1e6239d --- /dev/null +++ b/crypto_sign/haetae2/ref/encoding.h @@ -0,0 +1,17 @@ +#ifndef HAETAE_ENCODING_H +#define HAETAE_ENCODING_H + +#include "params.h" +#include +#include + +#define encode_h HAETAE_NAMESPACE(encode_h) +uint16_t encode_h(uint8_t *buf, const int32_t *h); +#define decode_h HAETAE_NAMESPACE(decode_h) +uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in); +#define encode_hb_z1 HAETAE_NAMESPACE(encode_hb_z1) +uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1); +#define decode_hb_z1 HAETAE_NAMESPACE(decode_hb_z1) +uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in); + +#endif // HAETAE_ENCODING_H diff --git a/crypto_sign/haetae2/ref/fft.c b/crypto_sign/haetae2/ref/fft.c new file mode 100644 index 00000000..f625ad79 --- /dev/null +++ b/crypto_sign/haetae2/ref/fft.c @@ -0,0 +1,231 @@ +#include "fft.h" + +static const complex_fp32_16 roots[] = { + {.real = +65536L, .imag = +0L}, {.real = +65531L, .imag = -804L}, + {.real = +65516L, .imag = -1608L}, {.real = +65492L, .imag = -2412L}, + {.real = +65457L, .imag = -3216L}, {.real = +65413L, .imag = -4019L}, + {.real = +65358L, .imag = -4821L}, {.real = +65294L, .imag = -5623L}, + {.real = +65220L, .imag = -6424L}, {.real = +65137L, .imag = -7224L}, + {.real = +65043L, .imag = -8022L}, {.real = +64940L, .imag = -8820L}, + {.real = +64827L, .imag = -9616L}, {.real = +64704L, .imag = -10411L}, + {.real = +64571L, .imag = -11204L}, {.real = +64429L, .imag = -11996L}, + {.real = +64277L, .imag = -12785L}, {.real = +64115L, .imag = -13573L}, + {.real = +63944L, .imag = -14359L}, {.real = +63763L, .imag = -15143L}, + {.real = +63572L, .imag = -15924L}, {.real = +63372L, .imag = -16703L}, + {.real = +63162L, .imag = -17479L}, {.real = +62943L, .imag = -18253L}, + {.real = +62714L, .imag = -19024L}, {.real = +62476L, .imag = -19792L}, + {.real = +62228L, .imag = -20557L}, {.real = +61971L, .imag = -21320L}, + {.real = +61705L, .imag = -22078L}, {.real = +61429L, .imag = -22834L}, + {.real = +61145L, .imag = -23586L}, {.real = +60851L, .imag = -24335L}, + {.real = +60547L, .imag = -25080L}, {.real = +60235L, .imag = -25821L}, + {.real = +59914L, .imag = -26558L}, {.real = +59583L, .imag = -27291L}, + {.real = +59244L, .imag = -28020L}, {.real = +58896L, .imag = -28745L}, + {.real = +58538L, .imag = -29466L}, {.real = +58172L, .imag = -30182L}, + {.real = +57798L, .imag = -30893L}, {.real = +57414L, .imag = -31600L}, + {.real = +57022L, .imag = -32303L}, {.real = +56621L, .imag = -33000L}, + {.real = +56212L, .imag = -33692L}, {.real = +55794L, .imag = -34380L}, + {.real = +55368L, .imag = -35062L}, {.real = +54934L, .imag = -35738L}, + {.real = +54491L, .imag = -36410L}, {.real = +54040L, .imag = -37076L}, + {.real = +53581L, .imag = -37736L}, {.real = +53114L, .imag = -38391L}, + {.real = +52639L, .imag = -39040L}, {.real = +52156L, .imag = -39683L}, + {.real = +51665L, .imag = -40320L}, {.real = +51166L, .imag = -40951L}, + {.real = +50660L, .imag = -41576L}, {.real = +50146L, .imag = -42194L}, + {.real = +49624L, .imag = -42806L}, {.real = +49095L, .imag = -43412L}, + {.real = +48559L, .imag = -44011L}, {.real = +48015L, .imag = -44604L}, + {.real = +47464L, .imag = -45190L}, {.real = +46906L, .imag = -45769L}, + {.real = +46341L, .imag = -46341L}, {.real = +45769L, .imag = -46906L}, + {.real = +45190L, .imag = -47464L}, {.real = +44604L, .imag = -48015L}, + {.real = +44011L, .imag = -48559L}, {.real = +43412L, .imag = -49095L}, + {.real = +42806L, .imag = -49624L}, {.real = +42194L, .imag = -50146L}, + {.real = +41576L, .imag = -50660L}, {.real = +40951L, .imag = -51166L}, + {.real = +40320L, .imag = -51665L}, {.real = +39683L, .imag = -52156L}, + {.real = +39040L, .imag = -52639L}, {.real = +38391L, .imag = -53114L}, + {.real = +37736L, .imag = -53581L}, {.real = +37076L, .imag = -54040L}, + {.real = +36410L, .imag = -54491L}, {.real = +35738L, .imag = -54934L}, + {.real = +35062L, .imag = -55368L}, {.real = +34380L, .imag = -55794L}, + {.real = +33692L, .imag = -56212L}, {.real = +33000L, .imag = -56621L}, + {.real = +32303L, .imag = -57022L}, {.real = +31600L, .imag = -57414L}, + {.real = +30893L, .imag = -57798L}, {.real = +30182L, .imag = -58172L}, + {.real = +29466L, .imag = -58538L}, {.real = +28745L, .imag = -58896L}, + {.real = +28020L, .imag = -59244L}, {.real = +27291L, .imag = -59583L}, + {.real = +26558L, .imag = -59914L}, {.real = +25821L, .imag = -60235L}, + {.real = +25080L, .imag = -60547L}, {.real = +24335L, .imag = -60851L}, + {.real = +23586L, .imag = -61145L}, {.real = +22834L, .imag = -61429L}, + {.real = +22078L, .imag = -61705L}, {.real = +21320L, .imag = -61971L}, + {.real = +20557L, .imag = -62228L}, {.real = +19792L, .imag = -62476L}, + {.real = +19024L, .imag = -62714L}, {.real = +18253L, .imag = -62943L}, + {.real = +17479L, .imag = -63162L}, {.real = +16703L, .imag = -63372L}, + {.real = +15924L, .imag = -63572L}, {.real = +15143L, .imag = -63763L}, + {.real = +14359L, .imag = -63944L}, {.real = +13573L, .imag = -64115L}, + {.real = +12785L, .imag = -64277L}, {.real = +11996L, .imag = -64429L}, + {.real = +11204L, .imag = -64571L}, {.real = +10411L, .imag = -64704L}, + {.real = +9616L, .imag = -64827L}, {.real = +8820L, .imag = -64940L}, + {.real = +8022L, .imag = -65043L}, {.real = +7224L, .imag = -65137L}, + {.real = +6424L, .imag = -65220L}, {.real = +5623L, .imag = -65294L}, + {.real = +4821L, .imag = -65358L}, {.real = +4019L, .imag = -65413L}, + {.real = +3216L, .imag = -65457L}, {.real = +2412L, .imag = -65492L}, + {.real = +1608L, .imag = -65516L}, {.real = +804L, .imag = -65531L}, + {.real = +0L, .imag = -65536L}, {.real = -804L, .imag = -65531L}, + {.real = -1608L, .imag = -65516L}, {.real = -2412L, .imag = -65492L}, + {.real = -3216L, .imag = -65457L}, {.real = -4019L, .imag = -65413L}, + {.real = -4821L, .imag = -65358L}, {.real = -5623L, .imag = -65294L}, + {.real = -6424L, .imag = -65220L}, {.real = -7224L, .imag = -65137L}, + {.real = -8022L, .imag = -65043L}, {.real = -8820L, .imag = -64940L}, + {.real = -9616L, .imag = -64827L}, {.real = -10411L, .imag = -64704L}, + {.real = -11204L, .imag = -64571L}, {.real = -11996L, .imag = -64429L}, + {.real = -12785L, .imag = -64277L}, {.real = -13573L, .imag = -64115L}, + {.real = -14359L, .imag = -63944L}, {.real = -15143L, .imag = -63763L}, + {.real = -15924L, .imag = -63572L}, {.real = -16703L, .imag = -63372L}, + {.real = -17479L, .imag = -63162L}, {.real = -18253L, .imag = -62943L}, + {.real = -19024L, .imag = -62714L}, {.real = -19792L, .imag = -62476L}, + {.real = -20557L, .imag = -62228L}, {.real = -21320L, .imag = -61971L}, + {.real = -22078L, .imag = -61705L}, {.real = -22834L, .imag = -61429L}, + {.real = -23586L, .imag = -61145L}, {.real = -24335L, .imag = -60851L}, + {.real = -25080L, .imag = -60547L}, {.real = -25821L, .imag = -60235L}, + {.real = -26558L, .imag = -59914L}, {.real = -27291L, .imag = -59583L}, + {.real = -28020L, .imag = -59244L}, {.real = -28745L, .imag = -58896L}, + {.real = -29466L, .imag = -58538L}, {.real = -30182L, .imag = -58172L}, + {.real = -30893L, .imag = -57798L}, {.real = -31600L, .imag = -57414L}, + {.real = -32303L, .imag = -57022L}, {.real = -33000L, .imag = -56621L}, + {.real = -33692L, .imag = -56212L}, {.real = -34380L, .imag = -55794L}, + {.real = -35062L, .imag = -55368L}, {.real = -35738L, .imag = -54934L}, + {.real = -36410L, .imag = -54491L}, {.real = -37076L, .imag = -54040L}, + {.real = -37736L, .imag = -53581L}, {.real = -38391L, .imag = -53114L}, + {.real = -39040L, .imag = -52639L}, {.real = -39683L, .imag = -52156L}, + {.real = -40320L, .imag = -51665L}, {.real = -40951L, .imag = -51166L}, + {.real = -41576L, .imag = -50660L}, {.real = -42194L, .imag = -50146L}, + {.real = -42806L, .imag = -49624L}, {.real = -43412L, .imag = -49095L}, + {.real = -44011L, .imag = -48559L}, {.real = -44604L, .imag = -48015L}, + {.real = -45190L, .imag = -47464L}, {.real = -45769L, .imag = -46906L}, + {.real = -46341L, .imag = -46341L}, {.real = -46906L, .imag = -45769L}, + {.real = -47464L, .imag = -45190L}, {.real = -48015L, .imag = -44604L}, + {.real = -48559L, .imag = -44011L}, {.real = -49095L, .imag = -43412L}, + {.real = -49624L, .imag = -42806L}, {.real = -50146L, .imag = -42194L}, + {.real = -50660L, .imag = -41576L}, {.real = -51166L, .imag = -40951L}, + {.real = -51665L, .imag = -40320L}, {.real = -52156L, .imag = -39683L}, + {.real = -52639L, .imag = -39040L}, {.real = -53114L, .imag = -38391L}, + {.real = -53581L, .imag = -37736L}, {.real = -54040L, .imag = -37076L}, + {.real = -54491L, .imag = -36410L}, {.real = -54934L, .imag = -35738L}, + {.real = -55368L, .imag = -35062L}, {.real = -55794L, .imag = -34380L}, + {.real = -56212L, .imag = -33692L}, {.real = -56621L, .imag = -33000L}, + {.real = -57022L, .imag = -32303L}, {.real = -57414L, .imag = -31600L}, + {.real = -57798L, .imag = -30893L}, {.real = -58172L, .imag = -30182L}, + {.real = -58538L, .imag = -29466L}, {.real = -58896L, .imag = -28745L}, + {.real = -59244L, .imag = -28020L}, {.real = -59583L, .imag = -27291L}, + {.real = -59914L, .imag = -26558L}, {.real = -60235L, .imag = -25821L}, + {.real = -60547L, .imag = -25080L}, {.real = -60851L, .imag = -24335L}, + {.real = -61145L, .imag = -23586L}, {.real = -61429L, .imag = -22834L}, + {.real = -61705L, .imag = -22078L}, {.real = -61971L, .imag = -21320L}, + {.real = -62228L, .imag = -20557L}, {.real = -62476L, .imag = -19792L}, + {.real = -62714L, .imag = -19024L}, {.real = -62943L, .imag = -18253L}, + {.real = -63162L, .imag = -17479L}, {.real = -63372L, .imag = -16703L}, + {.real = -63572L, .imag = -15924L}, {.real = -63763L, .imag = -15143L}, + {.real = -63944L, .imag = -14359L}, {.real = -64115L, .imag = -13573L}, + {.real = -64277L, .imag = -12785L}, {.real = -64429L, .imag = -11996L}, + {.real = -64571L, .imag = -11204L}, {.real = -64704L, .imag = -10411L}, + {.real = -64827L, .imag = -9616L}, {.real = -64940L, .imag = -8820L}, + {.real = -65043L, .imag = -8022L}, {.real = -65137L, .imag = -7224L}, + {.real = -65220L, .imag = -6424L}, {.real = -65294L, .imag = -5623L}, + {.real = -65358L, .imag = -4821L}, {.real = -65413L, .imag = -4019L}, + {.real = -65457L, .imag = -3216L}, {.real = -65492L, .imag = -2412L}, + {.real = -65516L, .imag = -1608L}, {.real = -65531L, .imag = -804L}}; + +static inline int32_t _mulrnd16(const int32_t x, const int32_t y) { + int64_t r = ((int64_t)x * (int64_t)y) + (1 << 15); + return r >> 16; +} + +static inline int32_t _complex_mul_real(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.real) - _mulrnd16(x.imag, y.imag); +} + +static inline int32_t _complex_mul_imag(const complex_fp32_16 x, + const complex_fp32_16 y) { + return _mulrnd16(x.real, y.imag) + _mulrnd16(x.imag, y.real); +} + +static void _complex_mul(complex_fp32_16 *r, const complex_fp32_16 x, + const complex_fp32_16 y) { + r->real = _complex_mul_real(x, y); + r->imag = _complex_mul_imag(x, y); +} + +const uint16_t brv9[] = { + 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, + 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, + 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, + 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, + 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, + 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, + 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, + 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, + 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, + 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, + 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, + 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, + 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, + 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, + 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, + 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, + 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, + 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, + 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, + 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, + 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, + 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, + 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, + 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, + 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, + 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, + 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, + 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, + 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, + 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 263, + 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, + 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, + 15, 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, + 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, + 255, 511}; + +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x) { + int i, inv_i; + for (i = 0; i < N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = x->coeffs[i] << 16; + } + for (i = N; i < FFT_N; i++) { + inv_i = brv9[i]; + r[inv_i].imag = 0; + r[inv_i].real = 0; + } +} + +int32_t complex_fp_sqabs(complex_fp32_16 x) { + return _mulrnd16(x.real, x.real) + _mulrnd16(x.imag, x.imag); +} + +void fft(complex_fp32_16 data[FFT_N]) { + unsigned int r, m, md2, n, k, even, odd, twid; + complex_fp32_16 u, t; + + for (r = 1; r <= FFT_LOGN; r++) { + m = 1 << r; + md2 = m >> 1; + for (n = 0; n < FFT_N; n += m) { + for (k = 0; k < md2; k++) { + even = n + k; + odd = even + md2; + twid = k << (FFT_LOGN - r); + + u = data[even]; + _complex_mul(&t, roots[twid], data[odd]); + data[even].real = u.real + t.real; + data[even].imag = u.imag + t.imag; + data[odd].real = u.real - t.real; + data[odd].imag = u.imag - t.imag; + } + } + } +} diff --git a/crypto_sign/haetae2/ref/fft.h b/crypto_sign/haetae2/ref/fft.h new file mode 100644 index 00000000..46a365ce --- /dev/null +++ b/crypto_sign/haetae2/ref/fft.h @@ -0,0 +1,19 @@ +#ifndef FFT__H +#define FFT__H + +#include "poly.h" +#include + +#define FFT_N 512 +#define FFT_LOGN 9 + +typedef struct { + int32_t real; + int32_t imag; +} complex_fp32_16; + +void fft(complex_fp32_16 data[FFT_N]); +void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x); +int32_t complex_fp_sqabs(complex_fp32_16 x); + +#endif diff --git a/crypto_sign/haetae2/ref/fips202.c b/crypto_sign/haetae2/ref/fips202.c new file mode 100644 index 00000000..e0ec2668 --- /dev/null +++ b/crypto_sign/haetae2/ref/fips202.c @@ -0,0 +1,746 @@ +/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ + * from http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public + * domain "TweetFips202" implementation from https://twitter.com/tweetfips202 by + * Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ + +#include "fips202.h" +#include +#include + +#define NROUNDS 24 +#define ROL(a, offset) ((a << offset) ^ (a >> (64 - offset))) + +/************************************************* + * Name: load64 + * + * Description: Load 8 bytes into uint64_t in little-endian order + * + * Arguments: - const uint8_t *x: pointer to input byte array + * + * Returns the loaded 64-bit unsigned integer + **************************************************/ +static uint64_t load64(const uint8_t x[8]) { + unsigned int i; + uint64_t r = 0; + + for (i = 0; i < 8; ++i) + r |= (uint64_t)x[i] << 8 * i; + + return r; +} + +/************************************************* + * Name: store64 + * + * Description: Store a 64-bit integer to array of 8 bytes in little-endian + *order + * + * Arguments: - uint8_t *x: pointer to the output byte array (allocated) + * - uint64_t u: input 64-bit unsigned integer + **************************************************/ +static void store64(uint8_t x[8], uint64_t u) { + unsigned int i; + + for (i = 0; i < 8; ++i) + x[i] = u >> 8 * i; +} + +/* Keccak round constants */ +const uint64_t KeccakF_RoundConstants[NROUNDS] = { + (uint64_t)0x0000000000000001ULL, (uint64_t)0x0000000000008082ULL, + (uint64_t)0x800000000000808aULL, (uint64_t)0x8000000080008000ULL, + (uint64_t)0x000000000000808bULL, (uint64_t)0x0000000080000001ULL, + (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008009ULL, + (uint64_t)0x000000000000008aULL, (uint64_t)0x0000000000000088ULL, + (uint64_t)0x0000000080008009ULL, (uint64_t)0x000000008000000aULL, + (uint64_t)0x000000008000808bULL, (uint64_t)0x800000000000008bULL, + (uint64_t)0x8000000000008089ULL, (uint64_t)0x8000000000008003ULL, + (uint64_t)0x8000000000008002ULL, (uint64_t)0x8000000000000080ULL, + (uint64_t)0x000000000000800aULL, (uint64_t)0x800000008000000aULL, + (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008080ULL, + (uint64_t)0x0000000080000001ULL, (uint64_t)0x8000000080008008ULL}; + +/************************************************* + * Name: KeccakF1600_StatePermute + * + * Description: The Keccak F1600 Permutation + * + * Arguments: - uint64_t *state: pointer to input/output Keccak state + **************************************************/ +static void KeccakF1600_StatePermute(uint64_t state[25]) { + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + // copyFromState(A, state) + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; + BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + // thetaRhoPiChiIotaPrepareTheta(round, A, E) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^ ((~BCe) & BCi); + Eba ^= (uint64_t)KeccakF_RoundConstants[round]; + Ebe = BCe ^ ((~BCi) & BCo); + Ebi = BCi ^ ((~BCo) & BCu); + Ebo = BCo ^ ((~BCu) & BCa); + Ebu = BCu ^ ((~BCa) & BCe); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^ ((~BCe) & BCi); + Ege = BCe ^ ((~BCi) & BCo); + Egi = BCi ^ ((~BCo) & BCu); + Ego = BCo ^ ((~BCu) & BCa); + Egu = BCu ^ ((~BCa) & BCe); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^ ((~BCe) & BCi); + Eke = BCe ^ ((~BCi) & BCo); + Eki = BCi ^ ((~BCo) & BCu); + Eko = BCo ^ ((~BCu) & BCa); + Eku = BCu ^ ((~BCa) & BCe); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^ ((~BCe) & BCi); + Eme = BCe ^ ((~BCi) & BCo); + Emi = BCi ^ ((~BCo) & BCu); + Emo = BCo ^ ((~BCu) & BCa); + Emu = BCu ^ ((~BCa) & BCe); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^ ((~BCe) & BCi); + Ese = BCe ^ ((~BCi) & BCo); + Esi = BCi ^ ((~BCo) & BCu); + Eso = BCo ^ ((~BCu) & BCa); + Esu = BCu ^ ((~BCa) & BCe); + + // prepareTheta + BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^ ((~BCe) & BCi); + Aba ^= (uint64_t)KeccakF_RoundConstants[round + 1]; + Abe = BCe ^ ((~BCi) & BCo); + Abi = BCi ^ ((~BCo) & BCu); + Abo = BCo ^ ((~BCu) & BCa); + Abu = BCu ^ ((~BCa) & BCe); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^ ((~BCe) & BCi); + Age = BCe ^ ((~BCi) & BCo); + Agi = BCi ^ ((~BCo) & BCu); + Ago = BCo ^ ((~BCu) & BCa); + Agu = BCu ^ ((~BCa) & BCe); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^ ((~BCe) & BCi); + Ake = BCe ^ ((~BCi) & BCo); + Aki = BCi ^ ((~BCo) & BCu); + Ako = BCo ^ ((~BCu) & BCa); + Aku = BCu ^ ((~BCa) & BCe); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^ ((~BCe) & BCi); + Ame = BCe ^ ((~BCi) & BCo); + Ami = BCi ^ ((~BCo) & BCu); + Amo = BCo ^ ((~BCu) & BCa); + Amu = BCu ^ ((~BCa) & BCe); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^ ((~BCe) & BCi); + Ase = BCe ^ ((~BCi) & BCo); + Asi = BCi ^ ((~BCo) & BCu); + Aso = BCo ^ ((~BCu) & BCa); + Asu = BCu ^ ((~BCa) & BCe); + } + + // copyToState(state, A) + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* + * Name: keccak_init + * + * Description: Initializes the Keccak state. + * + * Arguments: - uint64_t *s: pointer to Keccak state + **************************************************/ +static void keccak_init(uint64_t s[25]) { + unsigned int i; + for (i = 0; i < 25; ++i) + s[i] = 0; +} + +/************************************************* + * Name: keccak_absorb + * + * Description: Absorb step of Keccak; incremental. + * + * Arguments: - uint64_t *s: pointer to Keccak state + * - unsigned int pos: position in current block to be absorbed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + * + * Returns new position pos in current block + **************************************************/ +static unsigned int keccak_absorb(uint64_t s[25], unsigned int pos, + unsigned int r, const uint8_t *in, + size_t inlen) { + unsigned int i; + + while (pos + inlen >= r) { + for (i = pos; i < r; ++i) + s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); + inlen -= r - pos; + KeccakF1600_StatePermute(s); + pos = 0; + } + + for (i = pos; i < pos + inlen; ++i) + s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); + + return i; +} + +/************************************************* + * Name: keccak_finalize + * + * Description: Finalize absorb step. + * + * Arguments: - uint64_t *s: pointer to Keccak state + * - unsigned int pos: position in current block to be absorbed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - uint8_t p: domain separation byte + **************************************************/ +static void keccak_finalize(uint64_t s[25], unsigned int pos, unsigned int r, + uint8_t p) { + s[pos / 8] ^= (uint64_t)p << 8 * (pos % 8); + s[r / 8 - 1] ^= 1ULL << 63; +} + +/************************************************* + * Name: keccak_squeeze + * + * Description: Squeeze step of Keccak. Squeezes arbitratrily many bytes. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: number of bytes to be squeezed (written to out) + * - uint64_t *s: pointer to input/output Keccak state + * - unsigned int pos: number of bytes in current block already + *squeezed + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * + * Returns new position pos in current block + **************************************************/ +static unsigned int keccak_squeeze(uint8_t *out, size_t outlen, uint64_t s[25], + unsigned int pos, unsigned int r) { + unsigned int i; + + while (outlen) { + if (pos == r) { + KeccakF1600_StatePermute(s); + pos = 0; + } + for (i = pos; i < r && i < pos + outlen; ++i) + *out++ = s[i / 8] >> 8 * (i % 8); + outlen -= i - pos; + pos = i; + } + + return pos; +} + +/************************************************* + * Name: keccak_absorb_once + * + * Description: Absorb step of Keccak; + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + * - uint8_t p: domain-separation byte for different Keccak-derived + *functions + **************************************************/ +static void keccak_absorb_once(uint64_t s[25], unsigned int r, + const uint8_t *in, size_t inlen, uint8_t p) { + unsigned int i; + + for (i = 0; i < 25; ++i) + s[i] = 0; + + while (inlen >= r) { + for (i = 0; i < r / 8; ++i) + s[i] ^= load64(in + 8 * i); + in += r; + inlen -= r; + KeccakF1600_StatePermute(s); + } + + for (i = 0; i < inlen; ++i) + s[i / 8] ^= (uint64_t)in[i] << 8 * (i % 8); + + s[i / 8] ^= (uint64_t)p << 8 * (i % 8); + s[(r - 1) / 8] ^= 1ULL << 63; +} + +/************************************************* + * Name: keccak_squeezeblocks + * + * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. Assumes zero bytes of current + * block have already been squeezed. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *out) + * - uint64_t *s: pointer to input/output Keccak state + * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_squeezeblocks(uint8_t *out, size_t nblocks, uint64_t s[25], + unsigned int r) { + unsigned int i; + + while (nblocks) { + KeccakF1600_StatePermute(s); + for (i = 0; i < r / 8; ++i) + store64(out + 8 * i, s[i]); + out += r; + nblocks -= 1; + } +} + +/************************************************* + * Name: shake128_init + * + * Description: Initilizes Keccak state for use as SHAKE128 XOF + * + * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state + **************************************************/ +void shake128_init(keccak_state *state) { + keccak_init(state->s); + state->pos = 0; +} + +/************************************************* + * Name: shake128_absorb + * + * Description: Absorb step of the SHAKE128 XOF; incremental. + * + * Arguments: - keccak_state *state: pointer to (initialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { + state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); +} + +/************************************************* + * Name: shake128_finalize + * + * Description: Finalize absorb step of the SHAKE128 XOF. + * + * Arguments: - keccak_state *state: pointer to Keccak state + **************************************************/ +void shake128_finalize(keccak_state *state) { + keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* + * Name: shake128_squeeze + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many + * bytes. Can be called multiple times to keep squeezing. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t outlen : number of bytes to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { + state->pos = + keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); +} + +/************************************************* + * Name: shake128_absorb_once + * + * Description: Initialize, absorb into and finalize SHAKE128 XOF; + *non-incremental. + * + * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb_once(keccak_state *state, const uint8_t *in, + size_t inlen) { + keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); + state->pos = SHAKE128_RATE; +} + +/************************************************* + * Name: shake128_squeezeblocks + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of + * SHAKE128_RATE bytes each. Can be called multiple times + * to keep squeezing. Assumes new block has not yet been + * started (state->pos = SHAKE128_RATE). + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { + keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); +} + +/************************************************* + * Name: shake256_init + * + * Description: Initilizes Keccak state for use as SHAKE256 XOF + * + * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state + **************************************************/ +void shake256_init(keccak_state *state) { + keccak_init(state->s); + state->pos = 0; +} + +/************************************************* + * Name: shake256_absorb + * + * Description: Absorb step of the SHAKE256 XOF; incremental. + * + * Arguments: - keccak_state *state: pointer to (initialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { + state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); +} + +/************************************************* + * Name: shake256_finalize + * + * Description: Finalize absorb step of the SHAKE256 XOF. + * + * Arguments: - keccak_state *state: pointer to Keccak state + **************************************************/ +void shake256_finalize(keccak_state *state) { + keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* + * Name: shake256_squeeze + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many + * bytes. Can be called multiple times to keep squeezing. + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t outlen : number of bytes to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { + state->pos = + keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); +} + +/************************************************* + * Name: shake256_absorb_once + * + * Description: Initialize, absorb into and finalize SHAKE256 XOF; + *non-incremental. + * + * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak + *state + * - const uint8_t *in: pointer to input to be absorbed into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb_once(keccak_state *state, const uint8_t *in, + size_t inlen) { + keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); + state->pos = SHAKE256_RATE; +} + +/************************************************* + * Name: shake256_squeezeblocks + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of + * SHAKE256_RATE bytes each. Can be called multiple times + * to keep squeezing. Assumes next block has not yet been + * started (state->pos = SHAKE256_RATE). + * + * Arguments: - uint8_t *out: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed (written to + *output) + * - keccak_state *s: pointer to input/output Keccak state + **************************************************/ +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { + keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); +} + +/************************************************* + * Name: shake128 + * + * Description: SHAKE128 XOF with non-incremental API + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { + size_t nblocks; + keccak_state state; + + shake128_absorb_once(&state, in, inlen); + nblocks = outlen / SHAKE128_RATE; + shake128_squeezeblocks(out, nblocks, &state); + outlen -= nblocks * SHAKE128_RATE; + out += nblocks * SHAKE128_RATE; + shake128_squeeze(out, outlen, &state); +} + +/************************************************* + * Name: shake256 + * + * Description: SHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *out: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { + size_t nblocks; + keccak_state state; + + shake256_absorb_once(&state, in, inlen); + nblocks = outlen / SHAKE256_RATE; + shake256_squeezeblocks(out, nblocks, &state); + outlen -= nblocks * SHAKE256_RATE; + out += nblocks * SHAKE256_RATE; + shake256_squeeze(out, outlen, &state); +} + +/************************************************* + * Name: sha3_256 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *h: pointer to output (32 bytes) + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) { + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for (i = 0; i < 4; ++i) + store64(h + 8 * i, s[i]); +} + +/************************************************* + * Name: sha3_512 + * + * Description: SHA3-512 with non-incremental API + * + * Arguments: - uint8_t *h: pointer to output (64 bytes) + * - const uint8_t *in: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) { + unsigned int i; + uint64_t s[25]; + + keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); + KeccakF1600_StatePermute(s); + for (i = 0; i < 8; ++i) + store64(h + 8 * i, s[i]); +} diff --git a/crypto_sign/haetae2/ref/fips202.h b/crypto_sign/haetae2/ref/fips202.h new file mode 100644 index 00000000..58aa8ff2 --- /dev/null +++ b/crypto_sign/haetae2/ref/fips202.h @@ -0,0 +1,57 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_512_RATE 72 + +#define FIPS202_NAMESPACE(s) haetae_fips202_##s + +typedef struct { + uint64_t s[25]; + unsigned int pos; +} keccak_state; + +#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) +extern const uint64_t KeccakF_RoundConstants[]; + +#define shake128_init FIPS202_NAMESPACE(shake128_init) +void shake128_init(keccak_state *state); +#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) +void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) +void shake128_finalize(keccak_state *state); +#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) +void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) +void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) +void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake256_init FIPS202_NAMESPACE(shake256_init) +void shake256_init(keccak_state *state); +#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) +void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) +void shake256_finalize(keccak_state *state); +#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) +void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); +#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) +void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); +#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) +void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); + +#define shake128 FIPS202_NAMESPACE(shake128) +void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define shake256 FIPS202_NAMESPACE(shake256) +void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); +#define sha3_256 FIPS202_NAMESPACE(sha3_256) +void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); +#define sha3_512 FIPS202_NAMESPACE(sha3_512) +void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); + +#endif diff --git a/crypto_sign/haetae2/ref/fixpoint.c b/crypto_sign/haetae2/ref/fixpoint.c new file mode 100644 index 00000000..831f15ec --- /dev/null +++ b/crypto_sign/haetae2/ref/fixpoint.c @@ -0,0 +1,140 @@ +#include "fixpoint.h" +#include "params.h" +#include +#include + +static void __cneg(fp96_76 *x, const uint8_t sign) { + x->limb48[0] ^= (-(int64_t)sign) & ((1ULL << 48) - 1); + x->limb48[1] ^= -(int64_t)sign; + x->limb48[0] += sign; + renormalize(x); +} + +static void __copy_cneg(fp96_76 *y, const fp96_76 *x, const uint8_t sign) { + y->limb48[0] = ((-(int64_t)sign) & ((1ULL << 48) - 1)) ^ x->limb48[0]; + ; + y->limb48[1] = x->limb48[1] ^ (-(int64_t)sign); + y->limb48[0] += sign; + renormalize(y); +} + +static void fixpoint_mul(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y->limb48[0]); + + // shift right by 48, rounding + xy->limb48[0] = xy->limb48[1] + (((xy->limb48[0] >> 47) + 1) >> 1); + + mul48(tmp, x->limb48[0], y->limb48[1]); + xy->limb48[0] += tmp[0]; + xy->limb48[1] = tmp[1]; + mulacc48(&xy->limb48[0], x->limb48[1], y->limb48[0]); + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + mul64(tmp, x->limb48[1], y->limb48[1]); + xy->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(xy); +} + +static void fixpoint_unsigned_signed_mul(fp96_76 *xy, const fp96_76 *y) { + fp96_76 x, z; + uint8_t sign = (y->limb48[1] >> 63) & 1; + __copy_cneg(&x, y, sign); + fixpoint_mul(&z, &x, xy); + __copy_cneg(xy, &z, sign); +} + +static void fixpoint_sub(fp96_76 *xminy, const fp96_76 *x, const fp96_76 *y) { + fp96_76 yneg; + __copy_cneg(&yneg, y, 1); + fixpoint_add(xminy, x, &yneg); +} + +static void fixpoint_sub_from_threehalves(fp96_76 *x) { + __cneg(x, 1); + x->limb48[1] += 3ULL << 27; // left shift by 28 would be "3" + renormalize(x); +} + +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x) { + uint64_t tmp[2]; + sq48(&sqx->limb48[0], x->limb48[0]); + + // shift right by 48, rounding + //sqx->limb48[0] += 1ULL << 47; + sqx->limb48[0] >>= 48; + sqx->limb48[0] += sqx->limb48[1]; + + // mul + mul48(tmp, x->limb48[0], x->limb48[1]); + sqx->limb48[0] += tmp[0] << 1; + sqx->limb48[1] = tmp[1] << 1; + + // shift right by 28, rounding + //sqx->limb48[0] += 1ULL << 27; + sqx->limb48[0] >>= 28; + sqx->limb48[0] += (sqx->limb48[1] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] >>= 28; + + sq64(tmp, x->limb48[1]); + sqx->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); + sqx->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); + + renormalize(sqx); +} + +// start_cube = hex(round(2^64/(sqrt((K + L)*N + 2)^3))) +// start_times_threehalfs = hex(round(2^64 * 2/(3 * sqrt((K + L)*N + 2)))) +#if L == 4 +const fp96_76 start_cube = {.limb48 = {0x770077e2e41aULL, 0x1162ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x693861ad937bULL, 0x9caa56ULL}}; +#elif L == 6 +const fp96_76 start_cube = {.limb48 = {0x1a2935cfae68ULL, 0x978ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x7ad215218533ULL, 0x7ff1c9ULL}}; +#elif L == 7 +const fp96_76 start_cube = {.limb48 = {0x700ff3e8890dULL, 0x702ULL}}; +const fp96_76 start_times_threehalves = { + .limb48 = {0x5768588eed31ULL, 0x73bd40ULL}}; +#endif + +// implements Newton's method +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf) { + fp96_76 tmp, tmp2; + fixpoint_mul(&tmp, xhalf, &start_cube); // definitely two positive values + fixpoint_sub(invsqrtx, &start_times_threehalves, + &tmp); // first Newton iteration done, might be negative (very + // improbable) + + for (int i = 0; i < 6; i++) // 6 more iterations + { + fixpoint_square(&tmp, invsqrtx); // tmp = y^2, never negative + fixpoint_mul(&tmp2, xhalf, &tmp); // tmp2 = x/2 * y^2, never negative + fixpoint_sub_from_threehalves(&tmp2); // tmp = 3/2 - x/2 * y^2 + fixpoint_unsigned_signed_mul(invsqrtx, &tmp2); // y * (3/2 - x/2 * y^2) + } +} + +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign) { + int64_t res; + fp96_76 tmp, xx; + xx.limb48[1] = x >> 32; + xx.limb48[0] = (x & ((1ULL << 32) - 1)) << 16; + fixpoint_mul(&tmp, &xx, y); + res = (tmp.limb48[1] + (1UL << 14)) >> 15; // rounding + return (1 - 2 * (int32_t)sign) * res; +} + +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { + xy->limb48[0] = x->limb48[0] + y->limb48[0]; + xy->limb48[1] = x->limb48[1] + y->limb48[1]; +} diff --git a/crypto_sign/haetae2/ref/fixpoint.h b/crypto_sign/haetae2/ref/fixpoint.h new file mode 100644 index 00000000..7e608aa0 --- /dev/null +++ b/crypto_sign/haetae2/ref/fixpoint.h @@ -0,0 +1,126 @@ +#ifndef FP__H +#define FP__H + +#include "config.h" +#include +#include + +#ifdef __SIZEOF_INT128__ +__extension__ typedef __int128 int128; +__extension__ typedef unsigned __int128 uint128; +#endif + +typedef struct { + uint64_t limb48[2]; +} fp96_76; + +#define fixpoint_square HAETAE_NAMESPACE(fixpoint_square) +void fixpoint_square(fp96_76 *sqx, const fp96_76 *x); + +#define fixpoint_newton_invsqrt HAETAE_NAMESPACE(fixpoint_newton_invsqrt) +void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf); + +#define fixpoint_mul_rnd13 HAETAE_NAMESPACE(fixpoint_mul_rnd13) +int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, + const uint8_t sign); + +#define fixpoint_add HAETAE_NAMESPACE(fixpoint_add) +void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y); + +static inline void renormalize(fp96_76 *x) { + x->limb48[1] += x->limb48[0] >> 48; + x->limb48[0] &= (1ULL << 48) - 1; +} + +static inline int64_t smulh48(int64_t a, uint64_t b) { +#ifndef __SIZEOF_INT128__ + int64_t ah = a >> 24; + int64_t al = a - (ah << 24); + int64_t bl = b & ((1<<24)-1); + int64_t bh = b >> 24; + + int64_t res = (al*bl) >> 24; + res += al * bh + ah * bl + (1 << 23); // rounding + res >>= 24; + return res + (ah * bh); +#else + return ((int128)a * (int128)b + (1ULL << 47)) >> 48; // rounding +#endif +} + +static inline void mul64(uint64_t r[2], const uint64_t b, const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), bl = b & ((1ULL << 32) - 1), + ah = a >> 32, bh = b >> 32; + r[0] = a * b; + r[1] = ah * bl + al * bh + ((al * bl) >> 32); + r[1] >>= 32; + r[1] += ah * bh; +#else + uint128 res = ((uint128)a * (uint128)b); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void sq64(uint64_t r[2], const uint64_t a) { +#ifndef __SIZEOF_INT128__ + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = ah * al * 2; + r[1] >>= 32; + r[1] += ah * ah; +#else + uint128 res = ((uint128)a * (uint128)a); + r[0] = res; + r[1] = res >> 64; +#endif +} + +static inline void mul48(uint64_t r[2], const uint64_t b, const uint64_t a) { + mul64(r, b, a); + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void mulacc48(uint64_t r[2], const uint64_t b, const uint64_t a) { + uint64_t tmp[2]; + mul48(tmp, b, a); + r[0] += tmp[0]; + r[1] += tmp[1]; +} + +// (a0 + a1*2^32)^2 = a0^2 + 2^33*a0*a1 + 2^64*a1^2 +static inline void sq48(uint64_t r[2], const uint64_t a) { + uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; + r[0] = a * a; + r[1] = al * ah << 1; + r[1] >>= 32; + r[1] += ah * ah; + + r[1] <<= 16; + r[1] ^= r[0] >> 48; + r[0] &= (1ULL << 48) - 1; +} + +static inline void fixpoint_mul_high(fp96_76 *xy, const fp96_76 *x, + const uint64_t y) { + uint64_t tmp[2]; + mul48(&xy->limb48[0], x->limb48[0], y); // implicitly shifted right by 48 + + mul48(tmp, x->limb48[1], y); + xy->limb48[1] += tmp[0]; + + // shift right by 28, rounding + xy->limb48[0] += 1UL << 27; + xy->limb48[0] >>= 28; + xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); + xy->limb48[1] >>= 28; + + xy->limb48[1] += tmp[1] << 20; + + renormalize(xy); +} + +#endif diff --git a/crypto_sign/haetae2/ref/ntt.c b/crypto_sign/haetae2/ref/ntt.c new file mode 100644 index 00000000..6b66d3f6 --- /dev/null +++ b/crypto_sign/haetae2/ref/ntt.c @@ -0,0 +1,95 @@ +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include + +static const int32_t zetas[N] = { + 0, 26964, -16505, 22229, 30746, 20243, 19064, -31218, 9395, + -30985, 22859, -8851, 32144, 13744, 21408, 17599, -16039, -22946, + 6241, -19553, 10681, 22935, 22431, -29104, 28147, -27527, -29133, + -20035, 20143, -11361, 30820, 25252, -22562, -6789, -10049, 9383, + 16304, -12296, 16446, 18239, -1296, -19725, -32076, 11782, -17941, + 29643, -8577, 7893, -21464, -19646, -15130, -2391, 30608, -23970, + -16608, 19616, -7941, 26533, -19129, 27690, 7597, -11459, 10615, + -9430, 11591, 7814, 12697, 32114, -3761, -9604, 19813, 20353, + 17456, -16267, -19555, 598, -29942, 4538, 835, 15546, 3970, + -27685, 1488, 8311, -12442, 31352, -17631, 1806, -5342, 9790, + 29068, 16507, -29051, 22131, 6759, 15510, -14941, 28710, 1160, + -31327, 24985, 11261, -10623, -27727, 21502, 18731, -16186, -4127, + -18832, 12050, -14501, 7929, 29563, -31064, 5913, 5322, -16405, + 2844, 29439, 5876, -9522, -18586, -9874, 23844, 30362, -21442, + 9560, 17671, -27989, 3350, 787, -13857, 1657, -21224, -7374, + -9190, 2464, 25555, -3529, -28772, 16588, -15739, 23475, 13666, + 5764, 30980, 13633, -7401, -30317, 28847, 7682, -11808, -8796, + 14864, -24162, -19194, 689, -1311, -31332, -16319, 1025, 10971, + -23016, -2648, -21900, -12543, -25921, 28254, 28521, -16160, 12380, + -12882, -30332, -16630, 23439, 7742, 17182, 17494, 5920, 13642, + 7382, -18166, 21422, -30274, -28190, 13283, -20316, -9939, 10672, + 21454, 6080, -17374, -29735, -25912, -10170, 3808, 10639, -26985, + -10865, 25636, 17261, -26851, -8253, -3304, 18282, -2202, -31368, + -22243, 13882, 12069, -11242, -7729, -10226, 1761, -27298, -4800, + -17737, -22805, -3528, 65, 10770, 8908, -23751, 26934, 21921, + -27010, -21944, 8889, -1035, 23224, -9488, -5823, -994, -20206, + 7655, -16251, -22820, -27740, 15822, 23078, 13803, -8099, 2931, + 9217, -21126, -14203, 25492, -12831, 7947, 17463, -12979, 29003, + 31612, 26554, 8241, -20175}; // q = 64513 + +/************************************************* + * Name: ntt + * + * Description: Forward NTT, in-place. No modular reduction is performed after + * additions or subtractions. Output vector is in bitreversed + *order. + * + * Arguments: - uint32_t p[N]: input/output coefficient array + **************************************************/ +void ntt(int32_t a[N]) { + unsigned int len, start, j, k; + int32_t zeta, t; + + k = 0; + for (len = 128; len > 0; len >>= 1) { + for (start = 0; start < N; start = j + len) { + zeta = zetas[++k]; + for (j = start; j < start + len; ++j) { + t = montgomery_reduce((int64_t)zeta * a[j + len]); + a[j + len] = a[j] - t; + a[j] = a[j] + t; + } + } + } +} + +/************************************************* + * Name: invntt_tomont + * + * Description: Inverse NTT and multiplication by Montgomery factor 2^32. + * In-place. No modular reductions after additions or + * subtractions; input coefficients need to be smaller than + * Q in absolute value. Output coefficient are smaller than Q in + * absolute value. + * + * Arguments: - uint32_t p[N]: input/output coefficient array + **************************************************/ +void invntt_tomont(int32_t a[N]) { + unsigned int start, len, j, k; + int32_t t, zeta; + const int32_t f = -29720; // mont^2/256 + + k = 256; + for (len = 1; len < N; len <<= 1) { + for (start = 0; start < N; start = j + len) { + zeta = -zetas[--k]; + for (j = start; j < start + len; ++j) { + t = a[j]; + a[j] = t + a[j + len]; + a[j + len] = t - a[j + len]; + a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); + } + } + } + + for (j = 0; j < N; ++j) { + a[j] = montgomery_reduce((int64_t)f * a[j]); + } +} diff --git a/crypto_sign/haetae2/ref/ntt.h b/crypto_sign/haetae2/ref/ntt.h new file mode 100644 index 00000000..c7732a34 --- /dev/null +++ b/crypto_sign/haetae2/ref/ntt.h @@ -0,0 +1,13 @@ +#ifndef NTT_H +#define NTT_H + +#include "params.h" +#include + +#define ntt HAETAE_NAMESPACE(ntt) +void ntt(int32_t a[N]); + +#define invntt_tomont HAETAE_NAMESPACE(invntt_tomont) +void invntt_tomont(int32_t a[N]); + +#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.c b/crypto_sign/haetae2/ref/packing.c new file mode 100644 index 00000000..4fd76e2f --- /dev/null +++ b/crypto_sign/haetae2/ref/packing.c @@ -0,0 +1,280 @@ +#include "packing.h" +#include "encoding.h" +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: pack_pk + * + * Description: Bit-pack public key pk = (seed, b). + * + * Arguments: - uint8_t pk[]: output byte array + * - const polyveck *b: polynomial vector of length K containg b + * - const uint8_t seed[]: seed for A' + **************************************************/ +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, + const uint8_t seed[SEEDBYTES]) { + unsigned int i; + + memcpy(pk, seed, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_pack(pk + i * POLYQ_PACKEDBYTES, &b->vec[i]); + } +} + +/************************************************* + * Name: unpack_pk + * + * Description: Unpack public key pk = (seed, b). + * + * Arguments: - uint8_t seed[]: seed for A' + * - polyveck *b: polynomial vector of length K containg b + * - const uint8_t pk[]: output byte array + **************************************************/ +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) { + unsigned int i; + + memcpy(seed, pk, SEEDBYTES); + + pk += SEEDBYTES; + for (i = 0; i < K; ++i) { + polyq_unpack(&b->vec[i], pk + i * POLYQ_PACKEDBYTES); + } +} + +/************************************************* + * Name: pack_sk + * + * Description: Bit-pack secret key sk = (pk, s). + * + * Arguments: - uint8_t sk[]: output byte array + * - const uint8_t pk[PUBLICKEYBYTES]: packed pk + * - const polyvecl *s0: polyvecl pointer containing s0 (encoding + *starting at offset 1) + * - const polyveck *s1: polyveck pointer containing s1 + **************************************************/ +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, + const polyveck *s1, const uint8_t key[SEEDBYTES]) { + unsigned int i; + memcpy(sk, pk, CRYPTO_PUBLICKEYBYTES); + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s0->vec[i]); + + sk += (L - 1) * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_pack(sk + i * POLY2ETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s1->vec[i]); + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(sk, key, SEEDBYTES); +} + +/************************************************* + * Name: unpack_sk + * + * Description: Unpack secret key sk = (A, s). + * + * Arguments: - polyvecl A[K]: output polyvecl array for A + * - polyvecl s0: output polyvecl pointer for s0 + * - polyveck s1: output polyveck pointer for s1 + * - const uint8_t sk[]: byte array containing bit-packed sk + **************************************************/ +void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { + unsigned int i; + uint8_t rhoprime[SEEDBYTES]; + polyveck b1; +#if D > 0 + polyveck a; +#endif + + unpack_pk(&b1, rhoprime, sk); + + sk += CRYPTO_PUBLICKEYBYTES; + for (i = 0; i < M; ++i) + polyeta_unpack(&s0->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += M * POLYETA_PACKEDBYTES; +#if D == 1 + for (i = 0; i < K; ++i) + poly2eta_unpack(&s1->vec[i], sk + i * POLY2ETA_PACKEDBYTES); + + sk += K * POLY2ETA_PACKEDBYTES; +#elif D == 0 + for (i = 0; i < K; ++i) + polyeta_unpack(&s1->vec[i], sk + i * POLYETA_PACKEDBYTES); + + sk += K * POLYETA_PACKEDBYTES; +#else +#error "Not yet implemented." +#endif + memcpy(key, sk, SEEDBYTES); + + // A' = PRG(rhoprime) + polymatkl_expand(A, rhoprime); + polymatkl_double(A); +#if D > 0 + polyveck_expand(&a, rhoprime); +#endif + +#if D == 1 + // first column of A = 2(a-b1*2^d) + polyveck_double(&b1); + polyveck_sub(&b1, &a, &b1); + polyveck_double(&b1); + polyveck_ntt(&b1); +#elif D == 0 +#else +#error "Not yet implemented." +#endif + // append b into A + for (i = 0; i < K; ++i) { + A[i].vec[0] = b1.vec[i]; + } +} + +/************************************************* + * Name: pack_sig + * + * Description: Bit-pack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - uint8_t sig[]: output byte array + * - const poly *c: pointer to challenge polynomial + * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of + *length L + * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of + *length L + * - const polyveck *h: pointer t vector h of length K + * Returns 1 in case the signature size is above the threshold; otherwise 0. + **************************************************/ +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, + const polyvecl *lowbits_z1, const polyvecl *highbits_z1, + const polyveck *h) { + + uint8_t encoded_h[N * K]; + uint8_t encoded_hb_z1[N * L]; + uint16_t size_enc_h, size_enc_hb_z1; + uint8_t offset_enc_h, offset_enc_hb_z1; + + // init/padding with zeros: + memset(sig, 0, CRYPTO_BYTES); + + // encode challenge + for (size_t i = 0; i < N; i++) + { + sig[i/8] |= c->coeffs[i] << (i%8); + } + sig += N / 8; + + for (int i = 0; i < L; ++i) + poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); + sig += L * N; + + size_enc_hb_z1 = + encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]); + size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]); + + if(size_enc_h == 0 || size_enc_hb_z1 == 0) { + return 1; // encoding failed + } + + // The size of the encoded h and HB(z1) does not always fit in one byte, + // thus we output a one byte offset to a fixed baseline + if(size_enc_h < BASE_ENC_H || size_enc_hb_z1 < BASE_ENC_HB_Z1 || + size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { + return 1; // encoding size offset out of range + } + + offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; + offset_enc_h = size_enc_h - BASE_ENC_H; + + if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > + CRYPTO_BYTES) { + return 1; // signature too big + } + + sig[0] = offset_enc_hb_z1; + sig[1] = offset_enc_h; + sig += 2; + + memcpy(sig, encoded_hb_z1, size_enc_hb_z1); + sig += size_enc_hb_z1; + + memcpy(sig, encoded_h, size_enc_h); + sig += size_enc_h; + + return 0; +} + +/************************************************* + * Name: unpack_sig + * + * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), + *Enc(h)). + * + * Arguments: - poly *c: pointer to challenge polynomial + * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) + * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) + * - polyveck *h: pointer to output vector h + * - const uint8_t sig[]: byte array containing + * bit-packed signature + * + * Returns 1 in case of malformed signature; otherwise 0. + **************************************************/ +int unpack_sig(poly *c, polyvecl *lowbits_z1, + polyvecl *highbits_z1, polyveck *h, + const uint8_t sig[CRYPTO_BYTES]) { + + unsigned int i; + uint16_t size_enc_hb_z1, size_enc_h; + + for (i = 0; i < N; i++) + { + c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; + } + sig += N / 8; + + for (i = 0; i < L; ++i) + poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); + sig += L * N; + + size_enc_hb_z1 = (uint16_t)sig[0] + BASE_ENC_HB_Z1; + size_enc_h = (uint16_t)sig[1] + BASE_ENC_H; + sig += 2; + + if(CRYPTO_BYTES < (2 + L*N + SEEDBYTES + size_enc_h + size_enc_hb_z1)) + return 1; // invalid size_enc_h and/or size_enc_hb_z1 + + if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { + return 1; // decoding failed + } + + sig += size_enc_hb_z1; + + if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { + return 1; // decoding failed + } + + sig += size_enc_h; + + for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) + if(sig[i] != 0) return 1; // verify zero padding + + return 0; +} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.h b/crypto_sign/haetae2/ref/packing.h new file mode 100644 index 00000000..ff9eb03b --- /dev/null +++ b/crypto_sign/haetae2/ref/packing.h @@ -0,0 +1,25 @@ +// clang-format off +#ifndef HAETAE_PACKING_H +#define HAETAE_PACKING_H + +#include "params.h" +#include "polyvec.h" +#include + +#define pack_pk HAETAE_NAMESPACE(pack_pk) +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, const uint8_t seed[SEEDBYTES]); +#define unpack_pk HAETAE_NAMESPACE(unpack_pk) +void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define pack_sk HAETAE_NAMESPACE(pack_sk) +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); +#define unpack_sk HAETAE_NAMESPACE(unpack_sk) +void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +#define pack_sig HAETAE_NAMESPACE(pack_sig) +int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); +#define unpack_sig HAETAE_NAMESPACE(unpack_sig) +int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + +#endif //HAETAE_PACKING_H +// clang-format on diff --git a/crypto_sign/haetae2/ref/params.h b/crypto_sign/haetae2/ref/params.h new file mode 100644 index 00000000..c73e63f2 --- /dev/null +++ b/crypto_sign/haetae2/ref/params.h @@ -0,0 +1,116 @@ +// clang-format off +#ifndef HAETAE_PARAMS_H +#define HAETAE_PARAMS_H + +#include "config.h" + +#define SEEDBYTES 32 +#define CRHBYTES 64 +#define N 256 +#define ROOT_OF_UNITY 3 + +#define Q 64513 +#define DQ (Q << 1)// 2Q + +#if HAETAE_MODE == 2 +#define K 2 +#define L 4 +#define ETA 1 +#define TAU 58 +#define B0 9846.02 +#define B1 9838.99 +#define B2 12777.52 +#define GAMMA 48.858 +#define LN 8192 // Large N +#define SQNM 39.191835884530846 // \sqrt(n * m) +#define D 1 +#define CRYPTO_BYTES 1474 + +#define BASE_ENC_HB_Z1 132 +#define BASE_ENC_H 7 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 3 +#define K 3 +#define L 6 +#define ETA 1 +#define TAU 80 +#define B0 18314.98 +#define B1 18307.70 +#define B2 21906.65 +#define GAMMA 57.707 +#define LN 8192 // Large N +#define SQNM 48.0 +#define D 1 +#define CRYPTO_BYTES 2349 + +#define BASE_ENC_HB_Z1 376 +#define BASE_ENC_H 127 + +#define ALPHA_HINT 512 +#define LOG_ALPHA_HINT 9 + +#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits +#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits + +#elif HAETAE_MODE == 5 +#define K 4 +#define L 7 +#define ETA 1 +#define TAU 128 +#define B0 22343.66 +#define B1 22334.95 +#define B2 24441.49 +#define GAMMA 55.13 +#define LN 8192 // Large N +#define SQNM 53.0659966456864 +#define D 0 +#define CRYPTO_BYTES 2948 + +#define BASE_ENC_HB_Z1 501 +#define BASE_ENC_H 358 + +#define ALPHA_HINT 256 +#define LOG_ALPHA_HINT 8 + +#define POLYB1_PACKEDBYTES 512 // 16bits * N / 8bits +#define POLYQ_PACKEDBYTES 512 // 16bits * N / 8bits + +#endif // HAETAE_MODE + +#define HALF_ALPHA_HINT (ALPHA_HINT >> 1) // ALPHA / 2 + +#define B0SQ ((uint64_t)(B0*B0)) +#define B1SQ ((uint64_t)(B1*B1)) +#define B2SQ ((uint64_t)(B2*B2)) + +#define M (L-1) + +#if ETA == 1 +#define POLYETA_PACKEDBYTES 64 +#define POLY2ETA_PACKEDBYTES 96 +#elif ETA == 2 +#define POLYETA_PACKEDBYTES 96 +#endif + +#define POLYC_PACKEDBYTES 32 // 1bit * N / 8bits +#define POLY_HIGHBITS_PACKEDBYTES (N * 9 / 8) +#define POLYVECK_HIGHBITS_PACKEDBYTES (POLY_HIGHBITS_PACKEDBYTES * K) +#define POLYVECK_BYTES (K * N * sizeof(int32_t)) +#define POLYVECL_BYTES (L * N * sizeof(int32_t)) + +#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLYQ_PACKEDBYTES) // seed + b +#if D == 1 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + M * POLYETA_PACKEDBYTES + K * POLY2ETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#elif D == 0 +#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + (M + K) * POLYETA_PACKEDBYTES + SEEDBYTES) // pk + s + K +#else +#error +#endif +#endif +// clang-format on diff --git a/crypto_sign/haetae2/ref/poly.c b/crypto_sign/haetae2/ref/poly.c new file mode 100644 index 00000000..70ebe816 --- /dev/null +++ b/crypto_sign/haetae2/ref/poly.c @@ -0,0 +1,659 @@ +#include "poly.h" +#include "decompose.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: poly_add + * + * Description: Add polynomials. No modular reduction is performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +/************************************************* + * Name: poly_sub + * + * Description: Subtract polynomials. No modular reduction is + * performed. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial to be + * subtraced from first input polynomial + **************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +/************************************************* + * Name: poly_pointwise_montgomery + * + * Description: Pointwise multiplication of polynomials in NTT domain + * representation and multiplication of resulting polynomial + * by 2^{-32}. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial + **************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); +} + +/************************************************* + * Name: poly_reduce2q + * + * Description: Inplace reduction of all coefficients of polynomial to 2q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_reduce2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = reduce32_2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze2q + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ 2Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze2q(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze2q(a->coeffs[i]); +} + +/************************************************* + * Name: poly_freeze + * + * Description: For all coefficients of in/out polynomial compute standard + * representative r = a mod^+ Q + * + * Arguments: - poly *a: pointer to input/output polynomial + **************************************************/ +void poly_freeze(poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = freeze(a->coeffs[i]); +} + +/************************************************* + * Name: poly_highbits + * + * Description: Compute HighBits of polynomial + * + * Arguments: - poly *a2: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_highbits(poly *a2, const poly *a) { + unsigned int i; + int32_t a1tmp; + + for (i = 0; i < N; ++i) + decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]); +} + +/************************************************* + * Name: poly_lowbits + * + * Description: Compute LowBits of polynomial + * + * Arguments: - poly *a1: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lowbits(poly *a1, const poly *a) { + unsigned int i = 0; + int32_t a2tmp = 0; + + for (i = 0; i < N; ++i) + decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]); +} + +/************************************************* + * Name: poly_compose + * + * Description: Compose HighBits and LowBits to recreate the polynomial + * + * Arguments: - poly *a3: pointer to output polynomial + * - const poly *ha: pointer to HighBits polynomial + * - const poly *la: pointer to HighBits polynomial + **************************************************/ +void poly_compose(poly *a, const poly *ha, const poly *la) { + unsigned int i = 0; + + for (i = 0; i < N; ++i) + a->coeffs[i] = (ha->coeffs[i] << 8) + la->coeffs[i]; +} + +/************************************************* + * Name: poly_lsb + * + * Description: Compute least significant bits of polynomial + * + * Arguments: - poly *a0: pointer to output polynomial + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly_lsb(poly *a0, const poly *a) { + unsigned int i; + + for (i = 0; i < N; ++i) + a0->coeffs[i] = a->coeffs[i] & 1; +} + +/************************************************* + * Name: poly_uniform + * + * Description: Sample polynomial with uniformly random coefficients + * in [0,Q-1] by performing rejection sampling on the + * output stream of SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#define POLY_UNIFORM_NBLOCKS \ + ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES) +// N * 2(random bytes for [0, Q - 1]) + +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform(a->coeffs, N, buf, buflen); + + while (ctr < N) { + off = buflen % 2; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* + * Name: poly_uniform_eta + * + * Description: Sample polynomial with uniformly random coefficients + * in [-ETA,ETA] by performing rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +#if ETA == 1 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#elif ETA == 2 +#define POLY_UNIFORM_ETA_NBLOCKS \ + ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +#endif + +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int ctr; + unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); + + ctr = rej_eta(a->coeffs, N, buf, buflen); + + while (ctr < N) { + stream256_squeezeblocks(buf, 1, &state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); + } +} + +uint8_t hammingWeight_8(uint8_t x) { + x = (x & 0x55) + (x >> 1 & 0x55); + x = (x & 0x33) + (x >> 2 & 0x33); + x = (x & 0x0F) + (x >> 4 & 0x0F); + + return x; +} + +/************************************************* + * Name: poly_challenge + * + * Description: Implementation of challenge. Samples polynomial with TAU 1 + * coefficients using the output stream of SHAKE256(seed). + * + * Arguments: - poly *c: pointer to output polynomial + * - const uint8_t highbits_lsb[]: packed highbits and lsb + * - const uint8_t mu[]: hash of pk and message + **************************************************/ +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]) { +#if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) + unsigned int i, b, pos = 0; + uint8_t buf[XOF256_BLOCKBYTES]; + xof256_state state; + + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, highbits_lsb, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, + SEEDBYTES); + xof256_squeezeblocks(buf, 1, &state); + + for (i = 0; i < N; ++i) + c->coeffs[i] = 0; + for (i = N - TAU; i < N; ++i) { + do { + if (pos >= XOF256_BLOCKBYTES) { + xof256_squeezeblocks(buf, 1, &state); + pos = 0; + } + + b = buf[pos++]; + } while (b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1; + } +#elif HAETAE_MODE == 5 + unsigned int i, hwt = 0, cond = 0; + uint8_t mask = 0, w0 = 0; + uint8_t buf[32] = {0}; + xof256_state state; + + // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + xof256_absorbe_twice(&state, highbits_lsb, + POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, + SEEDBYTES); + xof256_squeeze(buf, 32, &state); + + for (i = 0; i < 32; ++i) + hwt += hammingWeight_8(buf[i]); + + cond = (128 - hwt); + mask = 0xff & (cond >> 8); + w0 = -(buf[0] & 1); + mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0 + for (i = 0; i < 32; ++i) { + buf[i] ^= mask; + c->coeffs[8 * i] = buf[i] & 1; + c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1; + c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1; + c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1; + c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1; + c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1; + c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1; + c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1; + } +#endif +} + +void poly_decomposed_pack(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + buf[i] = a->coeffs[i]; + } +} + +void poly_decomposed_unpack(poly *a, const uint8_t *buf) { + unsigned int i; + for (i = 0; i < N; i++) { + a->coeffs[i] = (int8_t)buf[i]; + } +} + +void poly_pack_highbits(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N / 8; i++) { + buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff; + + buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01; + buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff; + + buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03; + buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff; + + buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07; + buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff; + + buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f; + buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff; + + buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f; + buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff; + + buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f; + buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff; + + buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f; + buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff; + + buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff; + } +} + +void poly_pack_lsb(uint8_t *buf, const poly *a) { + unsigned int i; + for (i = 0; i < N; i++) { + if ((i % 8) == 0) { + buf[i / 8] = 0; + } + buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8); + } +} + +/************************************************* + * Name: polyq_pack + * + * Description: Bit-pack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYQ_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyq_pack(uint8_t *r, const poly *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r[b_idx] = (a->coeffs[d_idx] & 0xff); + r[b_idx + 1] = ((a->coeffs[d_idx] >> 8) & 0x7f) | + ((a->coeffs[d_idx + 1] & 0x1) << 7); + r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff); + r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) | + ((a->coeffs[d_idx + 2] & 0x3) << 6); + r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff); + r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) | + ((a->coeffs[d_idx + 3] & 0x7) << 5); + r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff); + r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) | + ((a->coeffs[d_idx + 4] & 0xf) << 4); + r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff); + r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) | + ((a->coeffs[d_idx + 5] & 0x1f) << 3); + r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff); + r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) | + ((a->coeffs[d_idx + 6] & 0x3f) << 2); + r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff); + r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) | + (a->coeffs[d_idx + 7] & 0x7f) << 1; + r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff); + } +#else + for (i = 0; i < N / 1; ++i) { + r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0; + r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8; + } +#endif +} + +/************************************************* + * Name: polyq_unpack + * + * Description: Unpack polynomial with coefficients in [0, Q - 1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyq_unpack(poly *r, const uint8_t *a) { + unsigned int i; +#if D == 1 + int b_idx = 0, d_idx = 0; + + for (i = 0; i < (N >> 3); ++i) { + b_idx = 15 * i; + d_idx = 8 * i; + + r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8); + r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) | + ((a[b_idx + 2] & 0xff) << 1) | + ((a[b_idx + 3] & 0x3f) << 9); + r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) | + ((a[b_idx + 4] & 0xff) << 2) | + ((a[b_idx + 5] & 0x1f) << 10); + r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) | + ((a[b_idx + 6] & 0xff) << 3) | + ((a[b_idx + 7] & 0xf) << 11); + r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) | + ((a[b_idx + 8] & 0xff) << 4) | + ((a[b_idx + 9] & 0x7) << 12); + r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) | + ((a[b_idx + 10] & 0xff) << 5) | + ((a[b_idx + 11] & 0x3) << 13); + r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) | + ((a[b_idx + 12] & 0xff) << 6) | + ((a[b_idx + 13] & 0x1) << 14); + r->coeffs[d_idx + 7] = + ((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7); + } + +#else + for (i = 0; i < N / 1; ++i) { + r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0; + r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8; + r->coeffs[1 * i + 0] &= 0xffff; + } +#endif +} + +/************************************************* + * Name: polyeta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void polyeta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + t[0] = ETA - a->coeffs[4 * i + 0]; + t[1] = ETA - a->coeffs[4 * i + 1]; + t[2] = ETA - a->coeffs[4 * i + 2]; + t[3] = ETA - a->coeffs[4 * i + 3]; + r[i] = t[0] >> 0; + r[i] |= t[1] << 2; + r[i] |= t[2] << 4; + r[i] |= t[3] << 6; + } +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + t[0] = ETA - a->coeffs[8 * i + 0]; + t[1] = ETA - a->coeffs[8 * i + 1]; + t[2] = ETA - a->coeffs[8 * i + 2]; + t[3] = ETA - a->coeffs[8 * i + 3]; + t[4] = ETA - a->coeffs[8 * i + 4]; + t[5] = ETA - a->coeffs[8 * i + 5]; + t[6] = ETA - a->coeffs[8 * i + 6]; + t[7] = ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#endif +} + +/************************************************* + * Name: polyeta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA,ETA]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void polyeta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 4; ++i) { + r->coeffs[4 * i + 0] = a[i] >> 0; + r->coeffs[4 * i + 0] &= 0x3; + + r->coeffs[4 * i + 1] = a[i] >> 2; + r->coeffs[4 * i + 1] &= 0x3; + + r->coeffs[4 * i + 2] = a[i] >> 4; + r->coeffs[4 * i + 2] &= 0x3; + + r->coeffs[4 * i + 3] = a[i] >> 6; + r->coeffs[4 * i + 3] &= 0x3; + + r->coeffs[4 * i + 0] = ETA - r->coeffs[4 * i + 0]; + r->coeffs[4 * i + 1] = ETA - r->coeffs[4 * i + 1]; + r->coeffs[4 * i + 2] = ETA - r->coeffs[4 * i + 2]; + r->coeffs[4 * i + 3] = ETA - r->coeffs[4 * i + 3]; + } + +#elif ETA == 2 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7]; + } +#endif +} + +/************************************************* + * Name: poly2eta_pack + * + * Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - uint8_t *r: pointer to output byte array with at least + * POLYETA_PACKEDBYTES bytes + * - const poly *a: pointer to input polynomial + **************************************************/ +void poly2eta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + t[0] = 2 * ETA - a->coeffs[8 * i + 0]; + t[1] = 2 * ETA - a->coeffs[8 * i + 1]; + t[2] = 2 * ETA - a->coeffs[8 * i + 2]; + t[3] = 2 * ETA - a->coeffs[8 * i + 3]; + t[4] = 2 * ETA - a->coeffs[8 * i + 4]; + t[5] = 2 * ETA - a->coeffs[8 * i + 5]; + t[6] = 2 * ETA - a->coeffs[8 * i + 6]; + t[7] = 2 * ETA - a->coeffs[8 * i + 7]; + + r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +/************************************************* + * Name: poly2eta_unpack + * + * Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1]. + * + * Arguments: - poly *r: pointer to output polynomial + * - const uint8_t *a: byte array with bit-packed polynomial + **************************************************/ +void poly2eta_unpack(poly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 1 + for (i = 0; i < N / 8; ++i) { + r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; + r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; + r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; + r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; + r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; + r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; + r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; + r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; + + r->coeffs[8 * i + 0] = 2 * ETA - r->coeffs[8 * i + 0]; + r->coeffs[8 * i + 1] = 2 * ETA - r->coeffs[8 * i + 1]; + r->coeffs[8 * i + 2] = 2 * ETA - r->coeffs[8 * i + 2]; + r->coeffs[8 * i + 3] = 2 * ETA - r->coeffs[8 * i + 3]; + r->coeffs[8 * i + 4] = 2 * ETA - r->coeffs[8 * i + 4]; + r->coeffs[8 * i + 5] = 2 * ETA - r->coeffs[8 * i + 5]; + r->coeffs[8 * i + 6] = 2 * ETA - r->coeffs[8 * i + 6]; + r->coeffs[8 * i + 7] = 2 * ETA - r->coeffs[8 * i + 7]; + } +#elif ETA == 2 +#error "not yet implemented" +#endif +} + +void poly_fromcrt(poly *w, const poly *u, const poly *v) { + unsigned int i; + int32_t xq, x2; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + x2 = v->coeffs[i]; + w->coeffs[i] = xq + (Q & -((xq ^ x2) & 1)); + } +} + +void poly_fromcrt0(poly *w, const poly *u) { + unsigned int i; + int32_t xq; + + for (i = 0; i < N; i++) { + xq = u->coeffs[i]; + w->coeffs[i] = xq + (Q & -(xq & 1)); + } +} + +void poly_ntt(poly *a) { ntt(&a->coeffs[0]); } + +void poly_invntt_tomont(poly *a) { invntt_tomont(&a->coeffs[0]); } diff --git a/crypto_sign/haetae2/ref/poly.h b/crypto_sign/haetae2/ref/poly.h new file mode 100644 index 00000000..3c801b3b --- /dev/null +++ b/crypto_sign/haetae2/ref/poly.h @@ -0,0 +1,80 @@ +// clang-format off +#ifndef HAETAE_POLY_H +#define HAETAE_POLY_H + +#include "params.h" +#include "reduce.h" +#include "sampler.h" +#include + +typedef struct { + int32_t coeffs[N]; +} poly; + +#define poly_add HAETAE_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub HAETAE_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); + +#define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) +void poly_reduce2q(poly *a); +#define poly_freeze2q HAETAE_NAMESPACE(poly_freeze2q) +void poly_freeze2q(poly *a); +#define poly_freeze HAETAE_NAMESPACE(poly_freeze) +void poly_freeze(poly *a); + +#define poly_highbits HAETAE_NAMESPACE(poly_highbits) +void poly_highbits(poly *a2, const poly *a); +#define poly_lowbits HAETAE_NAMESPACE(poly_lowbits) +void poly_lowbits(poly *a1, const poly *a); +#define poly_compose HAETAE_NAMESPACE(poly_compose) +void poly_compose(poly *a, const poly *ha, const poly *la); +#define poly_lsb HAETAE_NAMESPACE(poly_lsb) +void poly_lsb(poly *a0, const poly *a); + +#define poly_uniform HAETAE_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define poly_challenge HAETAE_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]); + +#define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) +void poly_decomposed_pack(uint8_t *buf, const poly *a); +#define poly_decomposed_unpack HAETAE_NAMESPACE(poly_decomposed_unpack) +void poly_decomposed_unpack(poly *a, const uint8_t *buf); + +#define poly_pack_highbits HAETAE_NAMESPACE(poly_pack_highbits) +void poly_pack_highbits(uint8_t *buf, const poly *a); + +#define poly_pack_lsb HAETAE_NAMESPACE(poly_pack_lsb) +void poly_pack_lsb(uint8_t *buf, const poly *a); + +#define polyq_pack HAETAE_NAMESPACE(polyq_pack) +void polyq_pack(uint8_t *r, const poly *a); +#define polyq_unpack HAETAE_NAMESPACE(polyq_unpack) +void polyq_unpack(poly *r, const uint8_t *a); + +#define polyeta_pack HAETAE_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t *r, const poly *a); +#define polyeta_unpack HAETAE_NAMESPACE(polyeta_unpack) +void polyeta_unpack(poly *r, const uint8_t *a); +#define poly2eta_pack HAETAE_NAMESPACE(poly2eta_pack) +void poly2eta_pack(uint8_t *r, const poly *a); +#define poly2eta_unpack HAETAE_NAMESPACE(poly2eta_unpack) +void poly2eta_unpack(poly *r, const uint8_t *a); + +#define poly_fromcrt HAETAE_NAMESPACE(poly_fromcrt) +void poly_fromcrt(poly *w, const poly *u, const poly *v); +#define poly_fromcrt0 HAETAE_NAMESPACE(poly_fromcrt0) +void poly_fromcrt0(poly *w, const poly *u); + +#define poly_ntt HAETAE_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); +#define poly_invntt_tomont HAETAE_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/ref/polyfix.c b/crypto_sign/haetae2/ref/polyfix.c new file mode 100644 index 00000000..c453d293 --- /dev/null +++ b/crypto_sign/haetae2/ref/polyfix.c @@ -0,0 +1,292 @@ +#include "polyfix.h" +#include "decompose.h" +#include "math.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: polyfix_add + * + * Description: Add double polynomial and integer polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output double polynomial + * - const polyfix *a: pointer to first summand + * - const poly *b: pointer to second summand + **************************************************/ +void polyfix_add(polyfix *c, const polyfix *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + LN * b->coeffs[i]; +} + +/************************************************* + * Name: polyfixfix_sub + * + * Description: Subtract fixed polynomial and fixed polynomial. + * No modular reduction is performed. + * + * Arguments: - polyfix *c: pointer to output fixed polynomial + * - const polyfix *a: pointer to first summand + * - const polyfix *b: pointer to second summand + **************************************************/ +void polyfixfix_sub(polyfix *c, const polyfix *a, const polyfix *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; +} + +int32_t fix_round(int32_t num) { + num += (num >> 31) & (-LN + 1); + num += + LN / + 2; // total \floor(LN / 2) if positive, -\floor(LN / 2) + 1 if negative + return num / LN; +} + +/************************************************* + * Name: polyfix_round + * + * Description: rounds a fixed polynomial to integer polynomial + * + * Arguments: - poly *a: output integer polynomial + * - poly *b: input fixed polynomial + **************************************************/ +void polyfix_round(poly *a, const polyfix *b) { + unsigned i; + + for (i = 0; i < N; ++i) + a->coeffs[i] = fix_round(b->coeffs[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length K **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixveck_add + * + * Description: Add vector to a vector of double polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixveck_sub + * + * Description: subtract vector to a vector of fixed polynomials of length k. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyfixveck *u: pointer to first summand + * - const polyfixveck *v: pointer to second summand + **************************************************/ +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixveck_double + * + * Description: Double vector of polynomials of length K. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixveck_double(polyfixveck *b, const polyfixveck *a) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; +} + +/************************************************* + * Name: polyfixveck_round + * + * Description: rounds a fixed polynomial vector of length K + * + * Arguments: - polyveck *a: output integer polynomial vector + * - polyfixveck *b: input fixed polynomial vector + **************************************************/ +void polyfixveck_round(polyveck *a, const polyfixveck *b) { + unsigned i; + + for (i = 0; i < K; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + +/**************************************************************/ +/********* Double Vectors of polynomials of length L **********/ +/**************************************************************/ + +/************************************************* + * Name: polyfixvecl_add + * + * Description: Add vector to a vector of double polynomials of length L. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyvecl *v: pointer to second summand + **************************************************/ +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyfixfixvecl_sub + * + * Description: subtract vector to a vector of fixed polynomials of length l. + * No modular reduction is performed. + * + * Arguments: - polyvecl *w: pointer to output vector + * - const polyfixvecl *u: pointer to first summand + * - const polyfixvecl *v: pointer to second summand + **************************************************/ +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} +/************************************************* + * Name: polyfixvecl_double + * + * Description: Double vector of polynomials of length L. + * + * Arguments: - polyveck *b: pointer to output vector + * - polyveck *a: pointer to input vector + **************************************************/ +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) { + unsigned int i, j; + + for (i = 0; i < L; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; +} + +/************************************************* + * Name: polyfixvecl_round + * + * Description: rounds a fixed polynomial vector of length L + * + * Arguments: - polyvecl *a: output integer polynomial vector + * - polyfixvecl *b: input fixed polynomial vector + **************************************************/ +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) { + unsigned i; + + for (i = 0; i < L; ++i) + polyfix_round(&a->vec[i], &b->vec[i]); +} + +/************************************************* + * Name: polyfixveclk_norm2 + * + * Description: Calculates L2 norm of a fixed point polynomial vector with + *length L + K The result is L2 norm * LN similar to the way polynomial is + *usually stored + * + * Arguments: - polyfixvecl *a: polynomial vector with length L to calculate + * norm + * - polyfixveck *a: polynomial vector with length K to calculate + * norm + **************************************************/ +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + for (j = 0; j < N; ++j) + ret += (int64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; + } + + for (i = 0; i < K; ++i) { + for (j = 0; j < N; ++j) + ret += (int64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; + } + + return ret; +} + +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, + const uint8_t seed[CRHBYTES], + const uint16_t nonce) { + uint16_t ni = nonce; + uint64_t samples[N * (L + K)]; + fp96_76 sqsum, invsqrt; + unsigned int i, j; + uint8_t signs[N * (L + K) / 8]; + + do { + sqsum.limb48[0] = 0; + sqsum.limb48[1] = 0; + + sample_gauss_N(&samples[0], &signs[0], &sqsum, seed, ni++, N + 1); + sample_gauss_N(&samples[N], &signs[N / 8], &sqsum, seed, ni++, N + 1); + + for (i = 2; i < L + K; i++) + sample_gauss_N(&samples[N * i], &signs[N / 8 * i], &sqsum, seed, + ni++, N); + + // divide sqsum by 2 and approximate inverse square root + sqsum.limb48[0] += 1; // rounding + sqsum.limb48[0] >>= 1; + sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; + sqsum.limb48[1] >>= 1; + sqsum.limb48[1] += sqsum.limb48[0] >> 48; + sqsum.limb48[0] &= (1ULL << 48) - 1; + fixpoint_newton_invsqrt(&invsqrt, &sqsum); + fixpoint_mul_high(&sqsum, &invsqrt, + (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); + + for (i = 0; i < L; i++) { + for (j = 0; j < N; j++) + y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + for (i = L; i < K + L; i++) { + for (j = 0; j < N; j++) + y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( + samples[(i * N + j)], &sqsum, + (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); + } + } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); + + { + uint8_t tmp[CRHBYTES + 2]; + for (i = 0; i < CRHBYTES; i++) + { + tmp[i] = seed[i]; + } + tmp[CRHBYTES + 0] = ni >> 0; + tmp[CRHBYTES + 1] = ni >> 8; + shake256(b, 1, tmp, CRHBYTES+2); + } + + return ni; +} diff --git a/crypto_sign/haetae2/ref/polyfix.h b/crypto_sign/haetae2/ref/polyfix.h new file mode 100644 index 00000000..6177319c --- /dev/null +++ b/crypto_sign/haetae2/ref/polyfix.h @@ -0,0 +1,61 @@ +// clang-format off +#ifndef HAETAE_POLYFIX_H +#define HAETAE_POLYFIX_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include "reduce.h" +#include + +typedef struct { + int32_t coeffs[N]; +} polyfix; + +#define polyfix_norm2 HAETAE_NAMESPACE(polyfix_norm2) +double polyfix_norm2(const polyfix *a); + +#define polyfix_round HAETAE_NAMESPACE(polyfix_round) +void polyfix_round(poly *a, const polyfix *b); + +#define polyfix_add HAETAE_NAMESPACE(polyfix_add) +void polyfix_add(polyfix *c, const polyfix *a, const poly *b); + +typedef struct { + polyfix vec[K]; +} polyfixveck; + +#define polyfixveck_add HAETAE_NAMESPACE(polyfixveck_add) +void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v); +#define polyfixfixveck_sub HAETAE_NAMESPACE(polyfixfixveck_sub) +void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, + const polyfixveck *v); +#define polyfixveck_double HAETAE_NAMESPACE(polyfixveck_double) +void polyfixveck_double(polyfixveck *b, const polyfixveck *a); + +#define polyfixveck_round HAETAE_NAMESPACE(polyfixveck_round) +void polyfixveck_round(polyveck *a, const polyfixveck *b); + +typedef struct { + polyfix vec[L]; +} polyfixvecl; + +#define polyfixvecl_add HAETAE_NAMESPACE(polyfixvecl_add) +void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v); +#define polyfixfixvecl_sub HAETAE_NAMESPACE(polyfixfixvecl_sub) +void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, + const polyfixvecl *v); +#define polyfixvecl_double HAETAE_NAMESPACE(polyfixvecl_double) +void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a); + +#define polyfixvecl_round HAETAE_NAMESPACE(polyfixvecl_round) +void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); + +#define polyfixveclk_sqnorm2 HAETAE_NAMESPACE(polyfixveclk_sqnorm2) +uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); + +#define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) +uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); + +#endif +// clang-format on diff --git a/crypto_sign/haetae2/ref/polymat.c b/crypto_sign/haetae2/ref/polymat.c new file mode 100644 index 00000000..c97f4dfb --- /dev/null +++ b/crypto_sign/haetae2/ref/polymat.c @@ -0,0 +1,73 @@ +#include "polymat.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); +} + +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); +} + +// doubles k * m sub-matrix of k * l mat +void polymatkl_double(polyvecl mat[K]) { + unsigned int i, j, k; + for (i = 0; i < K; ++i) { + for (j = 1; j < L; ++j) { + for (k = 0; k < N; ++k) { + mat[i].vec[j].coeffs[k] *= 2; + } + } + } +} + +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} + +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); + } +} diff --git a/crypto_sign/haetae2/ref/polymat.h b/crypto_sign/haetae2/ref/polymat.h new file mode 100644 index 00000000..c12bc28a --- /dev/null +++ b/crypto_sign/haetae2/ref/polymat.h @@ -0,0 +1,28 @@ +#ifndef HAETAE_POLYMAT_H +#define HAETAE_POLYMAT_H + +#include "params.h" +#include "poly.h" +#include "polyvec.h" +#include + +#define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) +void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) +void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); + +#define polymatkm_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkm_pointwise_montgomery) +void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], + const polyvecm *v); + +#define polymatkl_pointwise_montgomery \ + HAETAE_NAMESPACE(polymatkl_pointwise_montgomery) +void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], + const polyvecl *v); + +#define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) +void polymatkl_double(polyvecl mat[K]); + +#endif diff --git a/crypto_sign/haetae2/ref/polyvec.c b/crypto_sign/haetae2/ref/polyvec.c new file mode 100644 index 00000000..3b8b0336 --- /dev/null +++ b/crypto_sign/haetae2/ref/polyvec.c @@ -0,0 +1,543 @@ +#include + +#include "decompose.h" +#include "fft.h" +#include "math.h" +#include "params.h" +#include "poly.h" +#include "polyvec.h" + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +/************************************************* + * Name: polyveck_add + * + * Description: Add vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first summand + * - const polyveck *v: pointer to second summand + **************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_sub + * + * Description: Subtract vectors of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + * - const polyveck *u: pointer to first input vector + * - const polyveck *v: pointer to second input vector to be + * subtracted from first input vector + **************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyveck_double + * + * Description: Double vector of polynomials of length K. + * No modular reduction is performed. + * + * Arguments: - polyveck *w: pointer to output vector + **************************************************/ +void polyveck_double(polyveck *b) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + b->vec[i].coeffs[j] *= 2; +} + +/************************************************* + * Name: polyveck_reduce2q + * + * Description: Reduce coefficients to 2q + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_reduce2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_reduce2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_freeze2q + * + * Description: For all coefficients of polynomials in vector of length K + * compute standard representative r = a mod^+ 2Q. + * + * Arguments: - polyveck *v: pointer to input/output vector + **************************************************/ +void polyveck_freeze2q(polyveck *v) { + unsigned int i; + + for (i = 0; i < K; ++i) + poly_freeze2q(&v->vec[i]); +} + +/************************************************* + * Name: polyveck_expand + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in Zq by rejection sampling on the + * output stream from SHAKE128(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + **************************************************/ +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]) { + unsigned int i, nonce = (K << 8) + M; + for (i = 0; i < K; ++i) + poly_uniform(&v->vec[i], seed, nonce++); +} + +/************************************************* + * Name: polyvecmk_uniform_eta + * + * Description: Sample a vector of polynomials with uniformly random + * coefficients in [-ETA,ETA] by rejection sampling on the + * output stream from SHAKE256(seed|nonce) + * + * Arguments: - polyveck *v: pointer to output a vector of polynomials of + * length K + * - const uint8_t seed[]: byte array with seed of length CRHBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i, n = nonce; + for (i = 0; i < M; i++) + poly_uniform_eta(&u->vec[i], seed, n++); + for (i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, n++); +} + +/************************************************* + * Name: polyveck_double_negate + * + * Description: multiply each coefficient with -2 + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_double_negate(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2); +} + +/************************************************* + * Name: polyveck_frommont + * + * Description: multiply each coefficient with MONT + * + * Arguments: - polyveck *v: pointer to output vector of polynomials of + * length K + **************************************************/ +void polyveck_frommont(polyveck *v) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < N; j++) + v->vec[i].coeffs[j] = + montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ); +} + +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, + const poly *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v); + } +} + +/************************************************* + * Name: polyveck_poly_fromcrt + * + * Description: recover polynomials from CRT domain, where all "mod q" + * polynomials are known and only the uppermost "mod 2" polynomial + * is non-zero + * + * Arguments: - polyveck *w: pointer to output vector of polynomials of + * length K + * - const polyveck *u: pointer to the input vector of polynomials + * of length K + * - const poly *v: pointer to the input polynomial ("mod 2") + **************************************************/ +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) { + unsigned int i; + + poly_fromcrt(&w->vec[0], &u->vec[0], v); + + for (i = 1; i < K; i++) { + poly_fromcrt0(&w->vec[i], &u->vec[i]); + } +} + +void polyveck_highbits_hint(polyveck *w, const polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_pack_highbits(buf + i * POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]); + } +} + +void polyveck_cneg(polyveck *v, const uint8_t b) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] *= 1 - 2 * b; + } + } +} + +void polyveck_caddDQ2ALPHA(polyveck *h) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + h->vec[i].coeffs[j] += + (h->vec[i].coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_csubDQ2ALPHA(polyveck *v) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] -= + ~((v->vec[i].coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & + ((DQ - 2) / ALPHA_HINT); + } + } +} + +void polyveck_mul_alpha(polyveck *v, const polyveck *u) { + unsigned int i, j; + for (i = 0; i < K; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * ALPHA_HINT; + } + } +} + +void polyveck_div2(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] >>= 1; +} + +void polyveck_caddq(polyveck *v) { + unsigned i, j; + for (i = 0; i < K; ++i) + for (j = 0; j < N; ++j) + v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]); +} + +void polyveck_decompose_vk(polyveck *v0, polyveck *v) { + for (int i = 0; i < K; i++) { + for (int j = 0; j < N; j++) { + v->vec[i].coeffs[j] = + decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]); + } + } +} + +void polyveck_ntt(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_ntt(&x->vec[i]); + } +} + +void polyveck_invntt_tomont(polyveck *x) { + unsigned int i; + for (i = 0; i < K; i++) { + poly_invntt_tomont(&x->vec[i]); + } +} + +/************************************************* + * Name: polyveck_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length k + * + * Arguments: - polyveck *b: polynomial vector with length k to calculate + *norm + **************************************************/ +uint64_t polyveck_sqnorm2(const polyveck *b) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < K; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; + } + } + return ret; +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecl_highbits + * + * Description: Compute HighBits of a vector of polynomials + * + * Arguments: - polyvecl *v2: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_highbits(polyvecl *v2, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_highbits(&v2->vec[i], &v->vec[i]); +} + +/************************************************* + * Name: polyvecl_lowbits + * + * Description: Compute LowBits of a vector of polynomials + * + * Arguments: - polyvecl *v1: pointer to output vector of polynomials of + * length L + * - const polyvecl *v: pointer to input vector of polynomials of + * length L + **************************************************/ +void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) { + unsigned int i; + + for (i = 0; i < L; ++i) + poly_lowbits(&v1->vec[i], &v->vec[i]); +} + +void polyvecl_cneg(polyvecl *v, const uint8_t b) { + unsigned int i, j; + for (i = 0; i < L; i++) { + for (j = 0; j < N; j++) { + v->vec[i].coeffs[j] *= 1 - 2 * b; + } + } +} + +/************************************************* + * Name: polyvecl_sqnorm2 + * + * Description: Calculates L2 norm of a polynomial vector with length l + * + * Arguments: - polyvecl *a: polynomial vector with length l to calculate + *norm + **************************************************/ +uint64_t polyvecl_sqnorm2(const polyvecl *a) { + unsigned int i, j; + uint64_t ret = 0; + + for (i = 0; i < L; ++i) { + for (j = 0; j < N; ++j) { + ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; + } + } + + return ret; +} + +/************************************************* + * Name: polyvecl_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecl *u: pointer to first input vector + * - const polyvecl *v: pointer to second input vector + **************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, + const polyvecl *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecl_ntt(polyvecl *x) { + unsigned int i; + for (i = 0; i < L; i++) { + poly_ntt(&x->vec[i]); + } +} + +/**************************************************************/ +/************ Vectors of polynomials of length M **************/ +/**************************************************************/ + +/************************************************* + * Name: polyvecm_pointwise_acc_montgomery + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecm *u: pointer to first input vector + * - const polyvecm *v: pointer to second input vector + **************************************************/ +void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u, + const polyvecm *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < M; ++i) { + poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + +void polyvecm_ntt(polyvecm *x) { + unsigned int i; + for (i = 0; i < M; i++) { + poly_ntt(&x->vec[i]); + } +} + +static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort +{ + int32_t a = *x; + int32_t b = *y; + int32_t ab = b ^ a; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} +static inline void minmaxmask(int32_t *x, int32_t *y, + int32_t *mask) // adapted from djbsort +{ + // If mask is -1, we perform the operation, else we do basically nothing. + // mask truth table: + // mask = 0 -> mask = 0, no swap is performed + // mask = -1, swap performed -> mask = 0 + // mask = -1, swap not performed -> mask = -1 + int32_t a = *x; + int32_t b = *y; + int32_t ab = (b ^ a) & *mask; + int32_t c = b - a; + c ^= ab & (c ^ b); + c >>= 31; + *mask &= ~c; + c &= ab; + *x = a ^ c; + *y = b ^ c; +} + +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2) { + int32_t res = 0; + complex_fp32_16 input[FFT_N] = {0}; + int32_t sum[N] = {0}, bestm[N / TAU + 1] = {0}, min = 0; + + for (size_t i = 0; i < M; ++i) { + fft_bitrev(input, &s1->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + for (size_t i = 0; i < K; ++i) { + fft_bitrev(input, &s2->vec[i]); + fft(input); + + // cumulative sum + for (size_t j = 0; j < N; j++) { + sum[j] += complex_fp_sqabs(input[2 * j + 1]); + } + } + + // compute max m + for (size_t i = 0; i < N / TAU + 1; ++i) { + bestm[i] = sum[i]; + } + for (size_t i = N / TAU + 1; i < N; i++) { + int32_t mask = -1; + for (size_t j = 0; j < N / TAU + 1; j++) { + minmaxmask(&sum[i], &bestm[j], &mask); + } + } + // find minimum in bestm + min = bestm[0]; + for (size_t i = 1; i < N / TAU + 1; i++) { + int32_t tmp = bestm[i]; + minmax(&min, &tmp); + } + // multiply all but the minimum by N mod TAU + for (size_t i = 0; i < N / TAU + 1; i++) { + int32_t fac = ((min - bestm[i]) >> 31); // all-ones if bestm[i] != min (TODO: impl specific behaviour) + fac = + (fac & (TAU)) ^ + ((~fac) & (N % TAU)); // fac = TAU for all != min and N%TAU for min + bestm[i] += + 0x10200; // add 1 for the "1 poly" in S, and prepare rounding + bestm[i] >>= 10; // round off 10 bits + bestm[i] *= fac; + res += bestm[i]; + } + + return (res + (1 << 5)) >> 6; // return rounded, squared value +} diff --git a/crypto_sign/haetae2/ref/polyvec.h b/crypto_sign/haetae2/ref/polyvec.h new file mode 100644 index 00000000..8d48aa40 --- /dev/null +++ b/crypto_sign/haetae2/ref/polyvec.h @@ -0,0 +1,129 @@ +// clang-format off +#ifndef HAETAE_POLYVEC_H +#define HAETAE_POLYVEC_H + +#include "params.h" +#include "poly.h" +#include + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +#define polyveck_add HAETAE_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub HAETAE_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_double HAETAE_NAMESPACE(polyveck_double) +void polyveck_double(polyveck *b); + +#define polyveck_reduce2q HAETAE_NAMESPACE(polyveck_reduce2q) +void polyveck_reduce2q(polyveck *v); +#define polyveck_freeze2q HAETAE_NAMESPACE(polyveck_freeze2q) +void polyveck_freeze2q(polyveck *v); +#define polyveck_freeze HAETAE_NAMESPACE(polyveck_freeze) +void polyveck_freeze(polyveck *v); + +#define polyveck_uniform_eta HAETAE_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); +#define polyveck_expand HAETAE_NAMESPACE(polyveck_expand) +void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]); + +#define polyveck_ntt HAETAE_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *x); + +#define polyveck_invntt_tomont HAETAE_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *x); + +#define polyveck_double_negate HAETAE_NAMESPACE(polyveck_double_negate) +void polyveck_double_negate(polyveck *x); + +#define polyveck_frommont HAETAE_NAMESPACE(polyveck_frommont) +void polyveck_frommont(polyveck *x); + +#define polyveck_poly_pointwise_montgomery HAETAE_NAMESPACE(polyveck_poly_pointwise_montgomery) +void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_poly_fromcrt HAETAE_NAMESPACE(polyveck_poly_fromcrt) +void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v); + +#define polyveck_highbits_hint HAETAE_NAMESPACE(polyveck_highbits_hint) +void polyveck_highbits_hint(polyveck *w, const polyveck *v); + +#define polyveck_pack_highbits HAETAE_NAMESPACE(polyveck_pack_highbits) +void polyveck_pack_highbits(uint8_t *buf, const polyveck *v); + +#define polyveck_cneg HAETAE_NAMESPACE(polyveck_cneg) +void polyveck_cneg(polyveck *v, const uint8_t b); + +#define polyveck_caddDQ2ALPHA HAETAE_NAMESPACE(polyveck_caddDQ2ALPHA) +void polyveck_caddDQ2ALPHA(polyveck *h); + +#define polyveck_csubDQ2ALPHA HAETAE_NAMESPACE(polyveck_csubDQ2ALPHA) +void polyveck_csubDQ2ALPHA(polyveck *v); + +#define polyveck_mul_alpha HAETAE_NAMESPACE(polyveck_mul_alpha) +void polyveck_mul_alpha(polyveck *v, const polyveck *u); + +#define polyveck_div2 HAETAE_NAMESPACE(polyveck_div2) +void polyveck_div2(polyveck *v); + +#define polyveck_caddq HAETAE_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); + +#define polyveck_decompose_vk HAETAE_NAMESPACE(polyveck_decompose_vk) +void polyveck_decompose_vk(polyveck *v0, polyveck *v); + +#define polyveck_sqnorm2 HAETAE_NAMESPACE(polyveck_sqnorm2) +uint64_t polyveck_sqnorm2(const polyveck *b); + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +#define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) +void polyvecl_cneg(polyvecl *v, const uint8_t b); + +#define polyvecl_sqnorm2 HAETAE_NAMESPACE(polyvecl_sqnorm2) +uint64_t polyvecl_sqnorm2(const polyvecl *a); + +#define polyvecl_ntt HAETAE_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *x); + +#define polyvecl_highbits HAETAE_NAMESPACE(polyvecl_highbits) +void polyvecl_highbits(polyvecl *v2, const polyvecl *v); +#define polyvecl_lowbits HAETAE_NAMESPACE(polyvecl_lowbits) +void polyvecl_lowbits(polyvecl *v2, const polyvecl *v); + +#define polyvecl_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + + +/* Vectors of polynomials of length M */ +typedef struct { + poly vec[M]; +} polyvecm; + +#define polyvecm_ntt HAETAE_NAMESPACE(polyvecm_ntt) +void polyvecm_ntt(polyvecm *x); + +#define polyvecmk_uniform_eta HAETAE_NAMESPACE(polyvecmk_uniform_eta) +void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecm_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecm_pointwise_acc_montgomery) +void polyvecm_pointwise_acc_montgomery(poly *w, + const polyvecm *u, + const polyvecm *v); + +#define polyvecmk_sqsing_value HAETAE_NAMESPACE(polyvecmk_sqsing_value) +int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2); + +#define polyvecmk_sing_value HAETAE_NAMESPACE(polyvecmk_sing_value) +int64_t polyvecmk_sing_value(const polyvecm *s1, const polyveck *s2); + +#endif +//clang-format on diff --git a/crypto_sign/haetae2/ref/rans_byte.h b/crypto_sign/haetae2/ref/rans_byte.h new file mode 100644 index 00000000..403ce20e --- /dev/null +++ b/crypto_sign/haetae2/ref/rans_byte.h @@ -0,0 +1,333 @@ +// Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014 +// +// Not intended to be "industrial strength"; just meant to illustrate the general +// idea. + +#ifndef RANS_BYTE_HEADER +#define RANS_BYTE_HEADER + +#include + +#ifdef assert +#define RansAssert assert +#else +#define RansAssert(x) +#endif + +// READ ME FIRST: +// +// This is designed like a typical arithmetic coder API, but there's three +// twists you absolutely should be aware of before you start hacking: +// +// 1. You need to encode data in *reverse* - last symbol first. rANS works +// like a stack: last in, first out. +// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give +// it a pointer to the *end* of your buffer (exclusive), and it will +// slowly move towards the beginning as more bytes are emitted. +// 3. Unlike basically any other entropy coder implementation you might +// have used, you can interleave data from multiple independent rANS +// encoders into the same bytestream without any extra signaling; +// you can also just write some bytes by yourself in the middle if +// you want to. This is in addition to the usual arithmetic encoder +// property of being able to switch models on the fly. Writing raw +// bytes can be useful when you have some data that you know is +// incompressible, and is cheaper than going through the rANS encode +// function. Using multiple rANS coders on the same byte stream wastes +// a few bytes compared to using just one, but execution of two +// independent encoders can happen in parallel on superscalar and +// Out-of-Order CPUs, so this can be *much* faster in tight decoding +// loops. +// +// This is why all the rANS functions take the write pointer as an +// argument instead of just storing it in some context struct. + +// -------------------------------------------------------------------------- + +// L ('l' in the paper) is the lower bound of our normalization interval. +// Between this and our byte-aligned emission, we use 31 (not 32!) bits. +// This is done intentionally because exact reciprocals for 31-bit uints +// fit in 32-bit uints: this permits some optimizations during encoding. +#define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval + +// State for a rANS encoder. Yep, that's all there is to it. +typedef uint32_t RansState; + +// Initialize a rANS encoder. +static inline void RansEncInit(RansState* r) +{ + *r = RANS_BYTE_L; +} + +// Renormalize the encoder. Internal function. +static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits) +{ + uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift. + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + return x; +} + +// Encodes a single symbol with range start "start" and frequency "freq". +// All frequencies are assumed to sum to "1 << scale_bits", and the +// resulting bytes get written to ptr (which is updated). +// +// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from +// beginning to end! Likewise, the output bytestream is written *backwards*: +// ptr starts pointing at the end of the output buffer and keeps decrementing. +static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + // renormalize + RansState x = RansEncRenorm(*r, pptr, freq, scale_bits); + + // x = C(s,x) + *r = ((x / freq) << scale_bits) + (x % freq) + start; +} + +// Flushes the rANS encoder. +static inline void RansEncFlush(RansState* r, uint8_t** pptr) +{ + uint32_t x = *r; + uint8_t* ptr = *pptr; + + ptr -= 4; + ptr[0] = (uint8_t) (x >> 0); + ptr[1] = (uint8_t) (x >> 8); + ptr[2] = (uint8_t) (x >> 16); + ptr[3] = (uint8_t) (x >> 24); + + *pptr = ptr; +} + +// Initializes a rANS decoder. +// Unlike the encoder, the decoder works forwards as you'd expect. +static inline int RansDecInit(RansState* r, uint8_t** pptr) +{ + uint32_t x; + uint8_t* ptr = *pptr; + + x = ptr[0] << 0; + x |= ptr[1] << 8; + x |= ptr[2] << 16; + x |= ptr[3] << 24; + if (x < RANS_BYTE_L || (RANS_BYTE_L << 8) <= x ) + return 1; // initial state out of range + + ptr += 4; + *pptr = ptr; + *r = x; + return 0; +} + +// Returns the current cumulative frequency (map it to a symbol yourself!) +static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits) +{ + return *r & ((1u << scale_bits) - 1); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", +// and the resulting bytes get written to ptr (which is updated). +static inline void RansDecAdvance(RansState* r, uint8_t** pptr, const uint8_t* end, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + x = freq * (x >> scale_bits) + (x & mask) - start; + + // renormalize + if (x < RANS_BYTE_L && *pptr < end) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L && ptr < end); + *pptr = ptr; + } + + *r = x; +} + +// -------------------------------------------------------------------------- + +// That's all you need for a full encoder; below here are some utility +// functions with extra convenience or optimizations. + +// Encoder symbol description +// This (admittedly odd) selection of parameters was chosen to make +// RansEncPutSymbol as cheap as possible. +typedef struct { + uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval + uint32_t rcp_freq; // Fixed-point reciprocal frequency + uint32_t bias; // Bias + uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq + uint16_t rcp_shift; // Reciprocal shift +} RansEncSymbol; + +// Decoder symbols are straightforward. +typedef struct { + uint16_t start; // Start of range. + uint16_t freq; // Symbol frequency. +} RansDecSymbol; + +// Initializes an encoder symbol to start "start" and frequency "freq" +static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + RansAssert(scale_bits <= 16); + RansAssert(start <= (1u << scale_bits)); + RansAssert(freq <= (1u << scale_bits) - start); + + // Say M := 1 << scale_bits. + // + // The original encoder does: + // x_new = (x/freq)*M + start + (x%freq) + // + // The fast encoder does (schematically): + // q = mul_hi(x, rcp_freq) >> rcp_shift (division) + // r = x - q*freq (remainder) + // x_new = q*M + bias + r (new x) + // plugging in r into x_new yields: + // x_new = bias + x + q*(M - freq) + // =: bias + x + q*cmpl_freq (*) + // + // and we can just precompute cmpl_freq. Now we just need to + // set up our parameters such that the original encoder and + // the fast encoder agree. + + s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; + s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq); + if (freq < 2) { + // freq=0 symbols are never valid to encode, so it doesn't matter what + // we set our values to. + // + // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately, + // our fixed-point reciprocal approximation can only multiply by values + // smaller than 1. + // + // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0. + // This gives: + // q = mul_hi(x, rcp_freq) >> rcp_shift + // = mul_hi(x, (1<<32) - 1)) >> 0 + // = floor(x - x/(2^32)) + // = x - 1 if 1 <= x < 2^32 + // and we know that x>0 (x=0 is never in a valid normalization interval). + // + // So we now need to choose the other parameters such that + // x_new = x*M + start + // plug it in: + // x*M + start (desired result) + // = bias + x + q*cmpl_freq (*) + // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq) + // = bias + 1 + (x - 1)*M + // = x*M + (bias + 1 - M) + // + // so we have start = bias + 1 - M, or equivalently + // bias = start + M - 1. + s->rcp_freq = ~0u; + s->rcp_shift = 0; + s->bias = start + (1 << scale_bits) - 1; + } else { + // Alverson, "Integer Division using reciprocals" + // shift=ceil(log2(freq)) + uint32_t shift = 0; + while (freq > (1u << shift)) + shift++; + + s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq); + s->rcp_shift = shift - 1; + + // With these values, 'q' is the correct quotient, so we + // have bias=start. + s->bias = start; + } +} + +// Initialize a decoder symbol to start "start" and frequency "freq" +static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq) +{ + RansAssert(start <= (1 << 16)); + RansAssert(freq <= (1 << 16) - start); + s->start = (uint16_t) start; + s->freq = (uint16_t) freq; +} + +// Encodes a given symbol. This is faster than straight RansEnc since we can do +// multiplications instead of a divide. +// +// See RansEncSymbolInit for a description of how this works. +static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym) +{ + RansAssert(sym->x_max != 0); // can't encode symbol with freq=0 + + // renormalize + uint32_t x = *r; + uint32_t x_max = sym->x_max; + if (x >= x_max) { + uint8_t* ptr = *pptr; + do { + *--ptr = (uint8_t) (x & 0xff); + x >>= 8; + } while (x >= x_max); + *pptr = ptr; + } + + // x = C(s,x) + // NOTE: written this way so we get a 32-bit "multiply high" when + // available. If you're on a 64-bit platform with cheap multiplies + // (e.g. x64), just bake the +32 into rcp_shift. + uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift; + *r = x + sym->bias + q * sym->cmpl_freq; +} + +// Equivalent to RansDecAdvance that takes a symbol. +static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, const uint8_t* end, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvance(r, pptr, end, sym->start, sym->freq, scale_bits); +} + +// Advances in the bit stream by "popping" a single symbol with range start +// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". +// No renormalization or output happens. +static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits) +{ + uint32_t mask = (1u << scale_bits) - 1; + + // s, x = D(x) + uint32_t x = *r; + *r = freq * (x >> scale_bits) + (x & mask) - start; +} + +// Equivalent to RansDecAdvanceStep that takes a symbol. +static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits) +{ + RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits); +} + +// Renormalize. +static inline void RansDecRenorm(RansState* r, uint8_t** pptr) +{ + // renormalize + uint32_t x = *r; + if (x < RANS_BYTE_L) { + uint8_t* ptr = *pptr; + do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L); + *pptr = ptr; + } + + *r = x; +} + +// Verify final state +static inline int RansDecVerify(const RansState* const r) +{ + if (*r != RANS_BYTE_L) + { + return 1; // the final state is inconsistent with the initial state + } + return 0; +} + +#endif // RANS_BYTE_HEADER \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/reduce.c b/crypto_sign/haetae2/ref/reduce.c new file mode 100644 index 00000000..55623734 --- /dev/null +++ b/crypto_sign/haetae2/ref/reduce.c @@ -0,0 +1,92 @@ +#include "reduce.h" +#include "params.h" +#include + +/************************************************* + * Name: montgomery_reduce + * + * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, + * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. + * + * Arguments: - int64_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a * QINV; + t = (a - (int64_t)t * Q) >> 32; + return t; +} + +/************************************************* + * Name: caddq + * + * Description: Add Q if input coefficient is negative. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* + * Name: freeze + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze(int32_t a) { + int64_t t = (int64_t)a * QREC; + t = t >> 32; + t = a - t * Q; // -2Q < t < 2Q + t += (t >> 31) & DQ; // 0 <= t < 2Q + t -= ~((t - Q) >> 31) & Q; // 0 <= t < Q + return t; +} + +/************************************************* + * Name: reduce32_2q + * + * Description: compute reduction with 2Q + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t reduce32_2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + t -= ~((t - Q) >> 31) & DQ; // centered representation + return (int32_t)t; +} + +/************************************************* + * Name: freeze2q + * + * Description: For finite field element a, compute standard + * representative r = a mod^+ 2Q. + * + * Arguments: - int32_t: finite field element a + * + * Returns r. + **************************************************/ +int32_t freeze2q(int32_t a) { + int64_t t = (int64_t)a * DQREC; + t >>= 32; + t = a - t * DQ; // -4Q < t < 4Q + t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q + t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q + return (int32_t)t; +} diff --git a/crypto_sign/haetae2/ref/reduce.h b/crypto_sign/haetae2/ref/reduce.h new file mode 100644 index 00000000..6f4a3a76 --- /dev/null +++ b/crypto_sign/haetae2/ref/reduce.h @@ -0,0 +1,28 @@ +#ifndef HAETAE_REDUCE_H +#define HAETAE_REDUCE_H + +#include "params.h" +#include + +#define MONT 14321 // 2^32 % Q +#define MONTSQ 4214 // 2^64 % Q +#define QINV 940508161 // q^(-1) mod 2^32 +#define QREC 66575 // 2^32 / Q for Barrett +#define DQREC 33287 // 2^32 / DQ for Barrett + +#define montgomery_reduce HAETAE_NAMESPACE(montgomery_reduce) +int32_t montgomery_reduce(int64_t a); + +#define caddq HAETAE_NAMESPACE(caddq) +int32_t caddq(int32_t a); + +#define freeze HAETAE_NAMESPACE(freeze) +int32_t freeze(int32_t a); + +#define reduce32_2q HAETAE_NAMESPACE(reduce32_2q) +int32_t reduce32_2q(int32_t a); + +#define freeze2q HAETAE_NAMESPACE(freeze2q) +int32_t freeze2q(int32_t a); + +#endif diff --git a/crypto_sign/haetae2/ref/sampler.c b/crypto_sign/haetae2/ref/sampler.c new file mode 100644 index 00000000..4bb546b3 --- /dev/null +++ b/crypto_sign/haetae2/ref/sampler.c @@ -0,0 +1,272 @@ +#include "sampler.h" +#include "fixpoint.h" +#include "symmetric.h" +#include + +/************************************************* + * Name: rej_uniform + * + * Description: Sample uniformly random coefficients in [0, Q-1] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + uint32_t t; + + ctr = pos = 0; + while (ctr < len && pos + 2 <= buflen) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + + if (t < Q) + a[ctr++] = t; + } + return ctr; +} + +/************************************************* + * Name: rej_eta + * + * Description: Sample uniformly random coefficients in [-ETA, ETA] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +static int32_t mod3(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq26(uint8_t t) { + int32_t r; + r = (t >> 4) + (t & 0xf); + r = (r >> 2) + (r & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +static int32_t mod3_leq8(uint8_t t) { + int32_t r; + r = (t >> 2) + (t & 3); + r = (r >> 2) + (r & 3); + return r - (3 * (r >> 1)); +} +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + + ctr = pos = 0; + while (ctr < len && pos < buflen) { +#if ETA == 1 + uint32_t t = buf[pos++]; + if (t < 243) { + // reduce mod 3 + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; // 171*3 = 1 mod 256 + t >>= 9; + a[ctr++] = mod3(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq26(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = mod3_leq8(t); + + if (ctr >= len) + break; + + t *= 171; + t >>= 9; + a[ctr++] = (int32_t)t - (int32_t)3 * (t >> 1); + } +#elif ETA == 2 + uint32_t t0, t1; + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + if (t0 < 15) { + t0 = t0 - (205 * t0 >> 10) * 5; + a[ctr++] = 2 - t0; + } + if (t1 < 15 && ctr < len) { + t1 = t1 - (205 * t1 >> 10) * 5; + a[ctr++] = 2 - t1; + } +#endif + } + return ctr; +} + +static uint64_t approx_exp(const uint64_t x) { + int64_t result; + result = -0x0000B6C6340925AELL; + result = ((smulh48(result, x) + (1LL << 2)) >> 3) + 0x0000B4BD4DF85227LL; + result = ((smulh48(result, x) + (1LL << 2)) >> 3) - 0x0000887F727491E2LL; + result = ((smulh48(result, x) + (1LL << 1)) >> 2) + 0x0000AAAA643C7E8DLL; + result = ((smulh48(result, x) + (1LL << 1)) >> 2) - 0x0000AAAAA98179E6LL; + result = ((smulh48(result, x) + 1LL) >> 1) + 0x0000FFFFFFFB2E7ALL; + result = ((smulh48(result, x) + 1LL) >> 1) - 0x0000FFFFFFFFF85FLL; + result = ((smulh48(result, x))) + 0x0000FFFFFFFFFFFCLL; + return result; +} + +#define CDTLEN 64 +static const uint32_t CDT[CDTLEN] = { + 3266, 6520, 9748, 12938, 16079, 19159, 22168, 25096, +27934, 30674, 33309, 35833, 38241, 40531, 42698, 44742, +46663, 48460, 50135, 51690, 53128, 54454, 55670, 56781, +57794, 58712, 59541, 60287, 60956, 61554, 62085, 62556, +62972, 63337, 63657, 63936, 64178, 64388, 64569, 64724, +64857, 64970, 65066, 65148, 65216, 65273, 65321, 65361, +65394, 65422, 65444, 65463, 65478, 65490, 65500, 65508, +65514, 65519, 65523, 65527, 65529, 65531, 65533, 65534 +}; + + +static uint64_t sample_gauss16(const uint64_t rand16) { + unsigned int i; + uint64_t r = 0; + for (i = 0; i < CDTLEN; i++) { + r += (((uint64_t)CDT[i] - rand16) >> 63) & 1; + } + return r; +} + +#define GAUSS_RAND (72 + 16 + 48) +#define GAUSS_RAND_BYTES ((GAUSS_RAND + 7) / 8) +static int sample_gauss_sigma76(uint64_t *r, fp96_76 *sqr, + const uint8_t rand[GAUSS_RAND_BYTES]) { + const uint64_t *rand_gauss16_ptr = (uint64_t *)rand, + *rand_rej_ptr = (uint64_t *)(&rand[2]); + const uint64_t rand_gauss16 = (*rand_gauss16_ptr) & ((1ULL << 16) - 1); + const uint64_t rand_rej = (*rand_rej_ptr) & ((1ULL << 48) - 1); + uint64_t x, exp_in; + fp96_76 y; + + // sample x + x = sample_gauss16(rand_gauss16); + + // y := append x to y + // leave 16 bit for carries + y.limb48[0] = rand[8] | ((uint64_t)rand[9] << 8) | + ((uint64_t)rand[10] << 16) | ((uint64_t)rand[11] << 24) | + ((uint64_t)rand[12] << 32) | ((uint64_t)rand[13] << 40); + y.limb48[1] = + rand[14] | ((uint64_t)rand[15] << 8) | ((uint64_t)rand[16] << 16) | + (x << 24); + + // r := round y + *r = (y.limb48[0] >> 15) ^ (y.limb48[1] << 33); + *r += 1; // rounding + *r >>= 1; + + // sqr := y*y + fixpoint_square(sqr, &y); + + // sqr[1] = y^2 >> (76+48) // 34 bit + // sqr[0] = (y^2 >> 76) & ((1UL<<48)-1) // 48 bit + // exp_in := sqr - ((x*x) << 68) + exp_in = sqr->limb48[1] - ((x*x) << (68 - 48)); + exp_in <<= 20; + exp_in |= sqr->limb48[0] >> 28; + exp_in += 1; // rounding + exp_in >>= 1; + + return ((((int64_t)(rand_rej ^ + (rand_rej & 1)) // set lowest bit to zero in order to + // use it for rejection if sample==0 + - (int64_t)approx_exp(exp_in)) >> + 63) // reject with prob 1-approx_exp(exp_in) + & (((*r | -*r) >> 63) | rand_rej)) & + 1; // if the sample is zero, clear the return value with prob 1/2 +} + +int sample_gauss(uint64_t *r, fp96_76 *sqsum, const uint8_t *buf, const size_t buflen, const size_t len, const int dont_write_last) +{ + const uint8_t *pos = buf; + fp96_76 sqr; + size_t bytecnt = buflen, coefcnt = 0, cnt = 0; + int accepted; + uint64_t dummy; + + while (coefcnt < len) { + if (bytecnt < GAUSS_RAND_BYTES) { + renormalize(sqsum); + return coefcnt; + } + + if (dont_write_last && coefcnt == len-1) + { + accepted = sample_gauss_sigma76(&dummy, &sqr, pos); + } else { + accepted = sample_gauss_sigma76(&r[coefcnt], &sqr, pos); + } + cnt += 1; + coefcnt += accepted; + pos += GAUSS_RAND_BYTES; + bytecnt -= GAUSS_RAND_BYTES; + + sqsum->limb48[0] += sqr.limb48[0] & -(int64_t)accepted; + sqsum->limb48[1] += sqr.limb48[1] & -(int64_t)accepted; + } + + renormalize(sqsum); + return len; +} + +#define POLY_HYPERBALL_BUFLEN (GAUSS_RAND_BYTES * N) +#define POLY_HYPERBALL_NBLOCKS ((POLY_HYPERBALL_BUFLEN + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len) { + uint8_t buf[POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES]; + size_t bytecnt, coefcnt, firstflag = 1; + stream256_state state; + stream256_init(&state, seed, nonce); + + stream256_squeezeblocks(buf, POLY_HYPERBALL_NBLOCKS, &state); + for (size_t i = 0; i < len / 8; i++) { + signs[i] = buf[i]; + } + bytecnt = POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES - len / 8; + coefcnt = sample_gauss(r, sqsum, buf + len / 8, bytecnt, len, len%N); + while (coefcnt < len) { + size_t off = bytecnt % GAUSS_RAND_BYTES; + for (size_t i = 0; i < off; i++) { + buf[i] = buf[bytecnt + len/8*firstflag - off + i]; + } + stream256_squeezeblocks(buf + off, 1, &state); + bytecnt = STREAM256_BLOCKBYTES + off; + + coefcnt += sample_gauss(r + coefcnt, sqsum, buf, bytecnt, len - coefcnt, len%N); + firstflag = 0; + } +} diff --git a/crypto_sign/haetae2/ref/sampler.h b/crypto_sign/haetae2/ref/sampler.h new file mode 100644 index 00000000..adb71bfd --- /dev/null +++ b/crypto_sign/haetae2/ref/sampler.h @@ -0,0 +1,21 @@ +#ifndef HAETAE_SAMPLER_H +#define HAETAE_SAMPLER_H + +#include "fixpoint.h" +#include "params.h" +#include "reduce.h" +#include + +#define rej_uniform HAETAE_NAMESPACE(rej_uniform) +unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); +#define rej_eta HAETAE_NAMESPACE(rej_eta) +unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); + +#define sample_gauss_N HAETAE_NAMESPACE(sample_gauss_N) +void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, + const uint8_t seed[CRHBYTES], const uint16_t nonce, + const size_t len); + +#endif diff --git a/crypto_sign/haetae2/ref/sign.c b/crypto_sign/haetae2/ref/sign.c new file mode 100644 index 00000000..a53cac2b --- /dev/null +++ b/crypto_sign/haetae2/ref/sign.c @@ -0,0 +1,453 @@ +#include "sign.h" +#include "packing.h" +#include "params.h" +#include "poly.h" +#include "polyfix.h" +#include "polymat.h" +#include "polyvec.h" +#include "randombytes.h" +#include "symmetric.h" +#include +#include +#include +#include + +/************************************************* + * Name: crypto_sign_keypair + * + * Description: Generates public and private key. + * + * Arguments: - uint8_t *pk: pointer to output public key (allocated + * array of CRYPTO_PUBLICKEYBYTES bytes) + * - uint8_t *sk: pointer to output private key (allocated + * array of CRYPTO_SECRETKEYBYTES bytes) + * + * Returns 0 (success) + **************************************************/ + +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES] = {0}; + uint16_t nonce = 0; + const uint8_t *rhoprime, *sigma, *key; + polyvecm A[K], s1, s1hat; + polyveck b, s2; +#if D > 0 + polyveck a, b0; +#else + polyveck s2hat; +#endif + xof256_state state; + + // Get entropy \rho + randombytes(seedbuf, SEEDBYTES); + + // Sample seeds with entropy \rho + xof256_absorbe_once(&state, seedbuf, SEEDBYTES); + xof256_squeeze(seedbuf, 2 * SEEDBYTES + CRHBYTES, &state); + + rhoprime = seedbuf; + sigma = rhoprime + SEEDBYTES; + key = sigma + CRHBYTES; + + // Expand Matrix A0 and vector a + polymatkm_expand(A, rhoprime); + +#if D > 0 + /********************************************** + * If there is rounding (D > 0), we need another polyveck a. + * Then, b = a + A0 * s1 + s2 and the lower D bits are + * rounded from b. The lower D bits are subsequently + * subtracted from s2. + **********************************************/ + polyveck_expand(&a, rhoprime); + +reject: + // Sample secret vectors s1 and s2 + polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); + nonce += M + K; + + // b = a + A0 * s1 + s2 mod q + s1hat = s1; + polyvecm_ntt(&s1hat); + polymatkm_pointwise_montgomery(&b, A, &s1hat); + polyveck_invntt_tomont(&b); + polyveck_add(&b, &b, &s2); + polyveck_add(&b, &b, &a); + polyveck_freeze(&b); + + // round off D bits + polyveck_decompose_vk(&b0, &b); + polyveck_sub(&s2, &s2, &b0); + + int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } +#else + /********************************************** + * If there is no rounding (D == 0), we store + * -2b directly in NTT domain into the public key. + **********************************************/ +reject: + // Sample secret vectors s1 and s2 + polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); + nonce += M + K; + int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); + if (squared_singular_value > GAMMA * GAMMA * N) { + goto reject; + } + + // b = A0 * s1 + s2 mod q + s1hat = s1; + s2hat = s2; + polyvecm_ntt(&s1hat); + polyveck_ntt(&s2hat); + polymatkm_pointwise_montgomery(&b, A, &s1hat); + polyveck_frommont(&b); + polyveck_add(&b, &b, &s2hat); + polyveck_double_negate(&b); + polyveck_caddq(&b); // directly compute and store NTT(-2b) +#endif + + pack_pk(pk, &b, rhoprime); + pack_sk(sk, pk, &s1, &s2, key); + + return 0; +} + +/************************************************* + * Name: crypto_sign_signature + * + * Description: Computes signature. + * + * Arguments: - uint8_t *sig: pointer to output signature (of length + * CRYPTO_BYTES) + * - size_t *siglen: pointer to output length of signature + * - uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk) { + + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; + uint8_t mu[SEEDBYTES] = {0}; + uint8_t b = 0; // one bit + uint16_t counter = 0; + uint64_t reject1, reject2; + + polyvecm s1; + polyvecl A1[K], cs1; + polyveck s2, cs2, highbits, Ay; + polyfixvecl y1, z1, z1tmp; + polyfixveck y2, z2, z2tmp; + polyvecl z1rnd; // round of z1 + polyvecl hb_z1, lb_z1; + polyveck z2rnd, h, htmp; // round of z2 + poly c, chat, z1rnd0, lsb; + + xof256_state state; + + unsigned int i; + + // Unpack secret key + unpack_sk(A1, &s1, &s2, key, sk); + + xof256_absorbe_twice(&state, sk, CRYPTO_PUBLICKEYBYTES, m, mlen); + xof256_squeeze(mu, SEEDBYTES, &state); + xof256_absorbe_twice(&state, key, SEEDBYTES, mu, SEEDBYTES); + xof256_squeeze(seedbuf, CRHBYTES, &state); + + polyvecm_ntt(&s1); + polyveck_ntt(&s2); + +reject: + + /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ + counter = polyfixveclk_sample_hyperball(&y1, &y2, &b, seedbuf, counter); + + /*------------------- 2. Compute a chanllenge c --------------------------*/ + // Round y1 and y2 + polyfixvecl_round(&z1rnd, &y1); + polyfixveck_round(&z2rnd, &y2); + + // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q + z1rnd0 = z1rnd.vec[0]; + polyvecl_ntt(&z1rnd); + polymatkl_pointwise_montgomery(&Ay, A1, &z1rnd); + polyveck_invntt_tomont(&Ay); + polyveck_double(&z2rnd); + polyveck_add(&Ay, &Ay, &z2rnd); + + // recover A * round(y) mod 2q + polyveck_poly_fromcrt(&Ay, &Ay, &z1rnd0); + polyveck_freeze2q(&Ay); + + // HighBits of (A * round(y) mod 2q) + polyveck_highbits_hint(&highbits, &Ay); + + // LSB(round(y_0) * j) + poly_lsb(&lsb, &z1rnd0); + + // Pack HighBits of A * round(y) mod 2q and LSB of round(y0) + polyveck_pack_highbits(buf, &highbits); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); + + // c = challenge(highbits, lsb, mu) + poly_challenge(&c, buf, mu); + + /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ + // cs = c * s = c * (si1 || s2) + cs1.vec[0] = c; + chat = c; + poly_ntt(&chat); + + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery(&cs1.vec[i], &chat, &s1.vec[i - 1]); + poly_invntt_tomont(&cs1.vec[i]); + } + polyveck_poly_pointwise_montgomery(&cs2, &s2, &chat); + polyveck_invntt_tomont(&cs2); + + // z = y + (-1)^b cs = z1 + z2 + polyvecl_cneg(&cs1, b & 1); + polyveck_cneg(&cs2, b & 1); + polyfixvecl_add(&z1, &y1, &cs1); + polyfixveck_add(&z2, &y2, &cs2); + + // reject if norm(z) >= B' + reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&z1, &z2)) >> 63; + reject1 &= 1; + + polyfixvecl_double(&z1tmp, &z1); + polyfixveck_double(&z2tmp, &z2); + + polyfixfixvecl_sub(&z1tmp, &z1tmp, &y1); + polyfixfixveck_sub(&z2tmp, &z2tmp, &y2); + + // reject if norm(2z-y) < B and b' = 0 + reject2 = + (polyfixveclk_sqnorm2(&z1tmp, &z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; + reject2 &= 1; + reject2 &= (b & 0x2) >> 1; + + if (reject1 | reject2) { + goto reject; + } + + /*------------------- 4. Make a hint -------------------------------------*/ + // Round z1 and z2 + polyfixvecl_round(&z1rnd, &z1); + polyfixveck_round(&z2rnd, &z2); + + // recover A1 * round(z1) - qcj mod 2q + polyveck_double(&z2rnd); + polyveck_sub(&htmp, &Ay, &z2rnd); + polyveck_freeze2q(&htmp); + + // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) + polyveck_highbits_hint(&htmp, &htmp); + polyveck_sub(&h, &highbits, &htmp); + polyveck_caddDQ2ALPHA(&h); + + /*------------------ Decompose(z1) and Pack signature -------------------*/ + polyvecl_lowbits(&lb_z1, &z1rnd); // TODO do this in one function together! + polyvecl_highbits(&hb_z1, &z1rnd); + + if (pack_sig(sig, &c, &lb_z1, &hb_z1, + &h)) { // reject if signature is too big + goto reject; + } + *siglen = CRYPTO_BYTES; + + return 0; +} + +/************************************************* + * Name: crypto_sign + * + * Description: Compute signed message. + * + * Arguments: - uint8_t *sm: pointer to output signed message (allocated + * array with CRYPTO_BYTES + mlen bytes), + * can be equal to m + * - size_t *smlen: pointer to output length of signed + * message + * - const uint8_t *m: pointer to message to be signed + * - size_t mlen: length of message + * - const uint8_t *sk: pointer to bit-packed secret key + * + * Returns 0 (success) + **************************************************/ +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk) { + size_t i; + + for (i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + *smlen += mlen; + return 0; +} + +/************************************************* + * Name: crypto_sign_verify + * + * Description: Verifies signature. + * + * Arguments: - uint8_t *m: pointer to input signature + * - size_t siglen: length of signature + * - const uint8_t *m: pointer to message + * - size_t mlen: length of message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signature could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk) { + unsigned int i; + uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; + uint8_t rhoprime[SEEDBYTES] = {0}, mu[SEEDBYTES]; + uint64_t sqnorm2; + polyvecl A1[K], z1; + polyveck b, highbits, h, z2, w; +#if D > 0 + polyveck a; +#endif + poly c, cprime, wprime; + + xof256_state state; + + // Check signature length + if (siglen != CRYPTO_BYTES) { + return -1; + } + + // Unpack public key + unpack_pk(&b, rhoprime, pk); + + // Unpack signature and Check conditions -- A1 is used only as intermediate + // buffer for the low bits + if (unpack_sig(&c, A1, &z1, &h, sig)) { + return -1; + } + + // Compose z1 out of HighBits(z1) and LowBits(z1) + for (i = 0; i < L; ++i) { + poly_compose(&z1.vec[i], &z1.vec[i], &A1[0].vec[i]); + } + + /*------------------- 1. Recover A1 --------------------------------------*/ + // A1 = (-2b + qj || 2 * A0) + polymatkl_expand(A1, rhoprime); + polymatkl_double(A1); +#if D == 1 + polyveck_expand(&a, rhoprime); + polyveck_double(&b); + polyveck_sub(&b, &a, &b); + polyveck_double(&b); + polyveck_ntt(&b); +#elif D == 0 + // no action required as b already contains -2b in NTT domain +#else +#error "Not yet implemented." +#endif + + for (i = 0; i < K; ++i) { + A1[i].vec[0] = b.vec[i]; + } + + /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ + // compute squared norm of z1 and w' before NTT + sqnorm2 = polyvecl_sqnorm2(&z1); + poly_sub(&wprime, &z1.vec[0], &c); + poly_lsb(&wprime, &wprime); + + // A1 * round(z1) - qcj mod q + polyvecl_ntt(&z1); + polymatkl_pointwise_montgomery(&highbits, A1, &z1); + polyveck_invntt_tomont(&highbits); + + // recover A1 * round(z1) - qcj mod 2q + polyveck_poly_fromcrt(&highbits, &highbits, &wprime); + polyveck_freeze2q(&highbits); + + // recover w1 + polyveck_highbits_hint(&w, &highbits); + polyveck_add(&w, &w, &h); + polyveck_csubDQ2ALPHA(&w); + + // recover \tilde{z}_2 mod q + polyveck_mul_alpha(&z2, &w); + polyveck_sub(&z2, &z2, &highbits); + poly_add(&z2.vec[0], &z2.vec[0], &wprime); + polyveck_reduce2q(&z2); + polyveck_div2(&z2); + + // check final norm of \tilde{z} + if (sqnorm2 + polyveck_sqnorm2(&z2) > B2SQ) { + return -1; + } + + /*------------------- 3. Compute c_seed' and Compare ---------------------*/ + + // Pack highBits(A * round(z) - qcj mod 2q) and h' + polyveck_pack_highbits(buf, &w); + poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); + + xof256_absorbe_twice(&state, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); + xof256_squeeze(mu, SEEDBYTES, &state); + + // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) + poly_challenge(&cprime, buf, mu); + + for (i = 0; i < N; ++i) { + if (c.coeffs[i] != cprime.coeffs[i]) { + return -1; + } + } + return 0; +} + +/************************************************* + * Name: crypto_sign_open + * + * Description: Verify signed message. + * + * Arguments: - uint8_t *m: pointer to output message (allocated + * array with smlen bytes), can be equal to sm + * - size_t *mlen: pointer to output length of message + * - const uint8_t *sm: pointer to signed message + * - size_t smlen: length of signed message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signed message could be verified correctly and -1 otherwise + **************************************************/ +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk) { + size_t i; + + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if (crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for (i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + for (i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/crypto_sign/haetae2/ref/sign.h b/crypto_sign/haetae2/ref/sign.h new file mode 100644 index 00000000..edfc0e80 --- /dev/null +++ b/crypto_sign/haetae2/ref/sign.h @@ -0,0 +1,30 @@ +#ifndef HAETAE_SIGN_H +#define HAETAE_SIGN_H + +#include "params.h" +#include "poly.h" +#include "polymat.h" +#include "polyvec.h" +#include +#include + +#define crypto_sign_keypair HAETAE_NAMESPACE(keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature HAETAE_NAMESPACE(signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, + size_t mlen, const uint8_t *sk); + +#define crypto_sign HAETAE_NAMESPACE(sign) +int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify HAETAE_NAMESPACE(verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, + size_t mlen, const uint8_t *pk); + +#define crypto_sign_open HAETAE_NAMESPACE(open) +int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif // HAETAE_SIGN_H diff --git a/crypto_sign/haetae2/ref/symmetric-shake.c b/crypto_sign/haetae2/ref/symmetric-shake.c new file mode 100644 index 00000000..c9aeadd3 --- /dev/null +++ b/crypto_sign/haetae2/ref/symmetric-shake.c @@ -0,0 +1,38 @@ +#include "fips202.h" +#include "params.h" +#include "symmetric.h" +#include + +void haetae_shake128_stream_init(keccak_state *state, + const uint8_t seed[SEEDBYTES], + uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake128_init(state); + shake128_absorb(state, seed, SEEDBYTES); + shake128_absorb(state, t, 2); + shake128_finalize(state); +} + +void haetae_shake256_stream_init(keccak_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce) { + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake256_init(state); + shake256_absorb(state, seed, CRHBYTES); + shake256_absorb(state, t, 2); + shake256_finalize(state); +} + +void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, + size_t in2len) { + shake256_init(state); + shake256_absorb(state, in1, in1len); + shake256_absorb(state, in2, in2len); + shake256_finalize(state); +} diff --git a/crypto_sign/haetae2/ref/symmetric.h b/crypto_sign/haetae2/ref/symmetric.h new file mode 100644 index 00000000..b3b9c37d --- /dev/null +++ b/crypto_sign/haetae2/ref/symmetric.h @@ -0,0 +1,78 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include "params.h" +#include +#include "fips202.h" + +// Cryptographic XOF function: shake256 +typedef keccak_state xof256_state; + +#define haetae_shake256_absorb_twice \ + HAETAE_NAMESPACE(haetae_shake256_absorb_twice) +void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, + size_t in1len, const uint8_t *in2, size_t in2len); + +#define XOF256_BLOCKBYTES SHAKE256_RATE + +#define xof256_absorbe_once(STATE, IN, IN_LEN) \ + shake256_absorb_once(STATE, IN, IN_LEN) +#define xof256_absorbe_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) \ + haetae_shake256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) +#define xof256_squeeze(OUT, OUT_LEN, STATE) \ + shake256_squeeze(OUT, OUT_LEN, STATE) +#define xof256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + + +// Stream function: aes256 or shake128|256 +#ifdef HAETAE_USE_AES // stream: aes256 + +#include "aes256ctr.h" + +typedef aes256ctr_ctx stream128_state; +typedef aes256ctr_ctx stream256_state; + +#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES +#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES + +#define stream128_init(STATE, SEED, NONCE) \ + aes256ctr_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + aes256ctr_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#else // stream: shake128 and shake256 + +typedef keccak_state stream128_state; +typedef keccak_state stream256_state; + +#define haetae_shake128_stream_init \ + HAETAE_NAMESPACE(haetae_shake128_stream_init) +void haetae_shake128_stream_init(keccak_state *state, + const uint8_t seed[SEEDBYTES], uint16_t nonce); + +#define haetae_shake256_stream_init \ + HAETAE_NAMESPACE(haetae_shake256_stream_init) +void haetae_shake256_stream_init(keccak_state *state, + const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) \ + haetae_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + haetae_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#endif // stream + +#endif //SYMMETRIC_H + From e122421d0ce033fbeabe217e1bae4e1a5f17b756 Mon Sep 17 00:00:00 2001 From: Marc <134507752+mmoeller23@users.noreply.github.com> Date: Fri, 1 Dec 2023 09:17:04 +0100 Subject: [PATCH 045/107] add low-mem ref implementation to all schemes Add slightly modified reference implementations to haetae2, Add slightly modified reference implementations to haetae2, haetae3 and haetae5 with lower stack memory footprint than the original reference implementation. This enables the test vector comparison for all schemes. CAVEAT: This commit modifies the following PQM4 core files * ldscripts/stm32f4discovery.ld * ldscripts/stm32f4discovery_fullram.ld * mk/stm32f4discovery.mk The two load scripts are modified as recommended in [issue 310](https://github.com/mupq/pqm4/issues/310#issuecomment-1810255939). The make file is modified to use full ram for the implementations m4f and ref of scheme haetae5, as they would run out of memory otherwise, similar to dilithium5. The stack memory footprint was reduced by: * Storing A1 using uint16 instead of int32, halving its footprint * Grouping some vectors inside `crypto_sign_signature()`, whose periods of liveliness do not overlap, into unions. The modification is light enough to easily verify consistency with the reference implementation. --- crypto_sign/haetae2/ref/config.h | 5 +- crypto_sign/haetae2/ref/packing.c | 17 ++--- crypto_sign/haetae2/ref/packing.h | 2 +- crypto_sign/haetae2/ref/poly.c | 51 +++++++++++++ crypto_sign/haetae2/ref/poly.h | 19 +++++ crypto_sign/haetae2/ref/polymat.c | 40 +++++++++++ crypto_sign/haetae2/ref/polymat.h | 11 +++ crypto_sign/haetae2/ref/polyvec.c | 23 ++++++ crypto_sign/haetae2/ref/polyvec.h | 9 +++ crypto_sign/haetae2/ref/sampler.c | 30 ++++++++ crypto_sign/haetae2/ref/sampler.h | 3 + crypto_sign/haetae2/ref/sign.c | 87 ++++++++++++----------- crypto_sign/haetae2/ref/sign.h | 33 +++++++++ crypto_sign/haetae3/ref/api.h | 1 + crypto_sign/haetae3/ref/config.h | 20 ++++++ crypto_sign/haetae3/ref/decompose.c | 1 + crypto_sign/haetae3/ref/decompose.h | 1 + crypto_sign/haetae3/ref/encoding.c | 1 + crypto_sign/haetae3/ref/encoding.h | 1 + crypto_sign/haetae3/ref/fft.c | 1 + crypto_sign/haetae3/ref/fft.h | 1 + crypto_sign/haetae3/ref/fips202.c | 1 + crypto_sign/haetae3/ref/fips202.h | 1 + crypto_sign/haetae3/ref/fixpoint.c | 1 + crypto_sign/haetae3/ref/fixpoint.h | 1 + crypto_sign/haetae3/ref/ntt.c | 1 + crypto_sign/haetae3/ref/ntt.h | 1 + crypto_sign/haetae3/ref/packing.c | 1 + crypto_sign/haetae3/ref/packing.h | 1 + crypto_sign/haetae3/ref/params.h | 1 + crypto_sign/haetae3/ref/poly.c | 1 + crypto_sign/haetae3/ref/poly.h | 1 + crypto_sign/haetae3/ref/polyfix.c | 1 + crypto_sign/haetae3/ref/polyfix.h | 1 + crypto_sign/haetae3/ref/polymat.c | 1 + crypto_sign/haetae3/ref/polymat.h | 1 + crypto_sign/haetae3/ref/polyvec.c | 1 + crypto_sign/haetae3/ref/polyvec.h | 1 + crypto_sign/haetae3/ref/rans_byte.h | 1 + crypto_sign/haetae3/ref/reduce.c | 1 + crypto_sign/haetae3/ref/reduce.h | 1 + crypto_sign/haetae3/ref/sampler.c | 1 + crypto_sign/haetae3/ref/sampler.h | 1 + crypto_sign/haetae3/ref/sign.c | 1 + crypto_sign/haetae3/ref/sign.h | 1 + crypto_sign/haetae3/ref/symmetric-shake.c | 1 + crypto_sign/haetae3/ref/symmetric.h | 1 + crypto_sign/haetae5/ref/api.h | 1 + crypto_sign/haetae5/ref/config.h | 20 ++++++ crypto_sign/haetae5/ref/decompose.c | 1 + crypto_sign/haetae5/ref/decompose.h | 1 + crypto_sign/haetae5/ref/encoding.c | 1 + crypto_sign/haetae5/ref/encoding.h | 1 + crypto_sign/haetae5/ref/fft.c | 1 + crypto_sign/haetae5/ref/fft.h | 1 + crypto_sign/haetae5/ref/fips202.c | 1 + crypto_sign/haetae5/ref/fips202.h | 1 + crypto_sign/haetae5/ref/fixpoint.c | 1 + crypto_sign/haetae5/ref/fixpoint.h | 1 + crypto_sign/haetae5/ref/ntt.c | 1 + crypto_sign/haetae5/ref/ntt.h | 1 + crypto_sign/haetae5/ref/packing.c | 1 + crypto_sign/haetae5/ref/packing.h | 1 + crypto_sign/haetae5/ref/params.h | 1 + crypto_sign/haetae5/ref/poly.c | 1 + crypto_sign/haetae5/ref/poly.h | 1 + crypto_sign/haetae5/ref/polyfix.c | 1 + crypto_sign/haetae5/ref/polyfix.h | 1 + crypto_sign/haetae5/ref/polymat.c | 1 + crypto_sign/haetae5/ref/polymat.h | 1 + crypto_sign/haetae5/ref/polyvec.c | 1 + crypto_sign/haetae5/ref/polyvec.h | 1 + crypto_sign/haetae5/ref/rans_byte.h | 1 + crypto_sign/haetae5/ref/reduce.c | 1 + crypto_sign/haetae5/ref/reduce.h | 1 + crypto_sign/haetae5/ref/sampler.c | 1 + crypto_sign/haetae5/ref/sampler.h | 1 + crypto_sign/haetae5/ref/sign.c | 1 + crypto_sign/haetae5/ref/sign.h | 1 + crypto_sign/haetae5/ref/symmetric-shake.c | 1 + crypto_sign/haetae5/ref/symmetric.h | 1 + ldscripts/stm32f4discovery.ld | 2 +- ldscripts/stm32f4discovery_fullram.ld | 2 +- mk/stm32f4discovery.mk | 2 + 84 files changed, 387 insertions(+), 55 deletions(-) create mode 120000 crypto_sign/haetae3/ref/api.h create mode 100644 crypto_sign/haetae3/ref/config.h create mode 120000 crypto_sign/haetae3/ref/decompose.c create mode 120000 crypto_sign/haetae3/ref/decompose.h create mode 120000 crypto_sign/haetae3/ref/encoding.c create mode 120000 crypto_sign/haetae3/ref/encoding.h create mode 120000 crypto_sign/haetae3/ref/fft.c create mode 120000 crypto_sign/haetae3/ref/fft.h create mode 120000 crypto_sign/haetae3/ref/fips202.c create mode 120000 crypto_sign/haetae3/ref/fips202.h create mode 120000 crypto_sign/haetae3/ref/fixpoint.c create mode 120000 crypto_sign/haetae3/ref/fixpoint.h create mode 120000 crypto_sign/haetae3/ref/ntt.c create mode 120000 crypto_sign/haetae3/ref/ntt.h create mode 120000 crypto_sign/haetae3/ref/packing.c create mode 120000 crypto_sign/haetae3/ref/packing.h create mode 120000 crypto_sign/haetae3/ref/params.h create mode 120000 crypto_sign/haetae3/ref/poly.c create mode 120000 crypto_sign/haetae3/ref/poly.h create mode 120000 crypto_sign/haetae3/ref/polyfix.c create mode 120000 crypto_sign/haetae3/ref/polyfix.h create mode 120000 crypto_sign/haetae3/ref/polymat.c create mode 120000 crypto_sign/haetae3/ref/polymat.h create mode 120000 crypto_sign/haetae3/ref/polyvec.c create mode 120000 crypto_sign/haetae3/ref/polyvec.h create mode 120000 crypto_sign/haetae3/ref/rans_byte.h create mode 120000 crypto_sign/haetae3/ref/reduce.c create mode 120000 crypto_sign/haetae3/ref/reduce.h create mode 120000 crypto_sign/haetae3/ref/sampler.c create mode 120000 crypto_sign/haetae3/ref/sampler.h create mode 120000 crypto_sign/haetae3/ref/sign.c create mode 120000 crypto_sign/haetae3/ref/sign.h create mode 120000 crypto_sign/haetae3/ref/symmetric-shake.c create mode 120000 crypto_sign/haetae3/ref/symmetric.h create mode 120000 crypto_sign/haetae5/ref/api.h create mode 100644 crypto_sign/haetae5/ref/config.h create mode 120000 crypto_sign/haetae5/ref/decompose.c create mode 120000 crypto_sign/haetae5/ref/decompose.h create mode 120000 crypto_sign/haetae5/ref/encoding.c create mode 120000 crypto_sign/haetae5/ref/encoding.h create mode 120000 crypto_sign/haetae5/ref/fft.c create mode 120000 crypto_sign/haetae5/ref/fft.h create mode 120000 crypto_sign/haetae5/ref/fips202.c create mode 120000 crypto_sign/haetae5/ref/fips202.h create mode 120000 crypto_sign/haetae5/ref/fixpoint.c create mode 120000 crypto_sign/haetae5/ref/fixpoint.h create mode 120000 crypto_sign/haetae5/ref/ntt.c create mode 120000 crypto_sign/haetae5/ref/ntt.h create mode 120000 crypto_sign/haetae5/ref/packing.c create mode 120000 crypto_sign/haetae5/ref/packing.h create mode 120000 crypto_sign/haetae5/ref/params.h create mode 120000 crypto_sign/haetae5/ref/poly.c create mode 120000 crypto_sign/haetae5/ref/poly.h create mode 120000 crypto_sign/haetae5/ref/polyfix.c create mode 120000 crypto_sign/haetae5/ref/polyfix.h create mode 120000 crypto_sign/haetae5/ref/polymat.c create mode 120000 crypto_sign/haetae5/ref/polymat.h create mode 120000 crypto_sign/haetae5/ref/polyvec.c create mode 120000 crypto_sign/haetae5/ref/polyvec.h create mode 120000 crypto_sign/haetae5/ref/rans_byte.h create mode 120000 crypto_sign/haetae5/ref/reduce.c create mode 120000 crypto_sign/haetae5/ref/reduce.h create mode 120000 crypto_sign/haetae5/ref/sampler.c create mode 120000 crypto_sign/haetae5/ref/sampler.h create mode 120000 crypto_sign/haetae5/ref/sign.c create mode 120000 crypto_sign/haetae5/ref/sign.h create mode 120000 crypto_sign/haetae5/ref/symmetric-shake.c create mode 120000 crypto_sign/haetae5/ref/symmetric.h diff --git a/crypto_sign/haetae2/ref/config.h b/crypto_sign/haetae2/ref/config.h index 52c9e87b..2461ffa5 100644 --- a/crypto_sign/haetae2/ref/config.h +++ b/crypto_sign/haetae2/ref/config.h @@ -15,5 +15,6 @@ #define CRYPTO_ALGNAME "HAETAE5" #define HAETAE_NAMESPACETOP haetae5 #define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s -#endif -#endif +#endif /* if HAETAE_MODE */ + +#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae2/ref/packing.c b/crypto_sign/haetae2/ref/packing.c index 4fd76e2f..b32508a9 100644 --- a/crypto_sign/haetae2/ref/packing.c +++ b/crypto_sign/haetae2/ref/packing.c @@ -89,12 +89,12 @@ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], * * Description: Unpack secret key sk = (A, s). * - * Arguments: - polyvecl A[K]: output polyvecl array for A + * Arguments: - polyvecl A[K]: output polyvecl_frozen array for A * - polyvecl s0: output polyvecl pointer for s0 * - polyveck s1: output polyveck pointer for s1 * - const uint8_t sk[]: byte array containing bit-packed sk **************************************************/ -void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, +void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { unsigned int i; uint8_t rhoprime[SEEDBYTES]; @@ -126,8 +126,8 @@ void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, memcpy(key, sk, SEEDBYTES); // A' = PRG(rhoprime) - polymatkl_expand(A, rhoprime); - polymatkl_double(A); + polymatkl_expand_frozen(A, rhoprime); + polymatkl_double_frozen(A); #if D > 0 polyveck_expand(&a, rhoprime); #endif @@ -144,7 +144,9 @@ void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, #endif // append b into A for (i = 0; i < K; ++i) { - A[i].vec[0] = b1.vec[i]; + for (size_t j = 0; j < N; j++) { + A[i].vec[0].coeffs[j] = (uint16_t) freeze(b1.vec[i].coeffs[j]); + } } } @@ -241,16 +243,15 @@ int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]) { - unsigned int i; uint16_t size_enc_hb_z1, size_enc_h; - for (i = 0; i < N; i++) + for (unsigned int i = 0; i < N; i++) { c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; } sig += N / 8; - for (i = 0; i < L; ++i) + for (unsigned int i = 0; i < L; ++i) poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); sig += L * N; diff --git a/crypto_sign/haetae2/ref/packing.h b/crypto_sign/haetae2/ref/packing.h index ff9eb03b..152ba75a 100644 --- a/crypto_sign/haetae2/ref/packing.h +++ b/crypto_sign/haetae2/ref/packing.h @@ -14,7 +14,7 @@ void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUB #define pack_sk HAETAE_NAMESPACE(pack_sk) void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); #define unpack_sk HAETAE_NAMESPACE(unpack_sk) -void unpack_sk(polyvecl A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); +void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); #define pack_sig HAETAE_NAMESPACE(pack_sig) int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); diff --git a/crypto_sign/haetae2/ref/poly.c b/crypto_sign/haetae2/ref/poly.c index 70ebe816..39c1bae3 100644 --- a/crypto_sign/haetae2/ref/poly.c +++ b/crypto_sign/haetae2/ref/poly.c @@ -58,6 +58,24 @@ void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); } +/************************************************* + * Name: poly_pointwise_montgomery_frozen + * + * Description: Pointwise multiplication of polynomials in NTT domain + * representation and multiplication of resulting polynomial + * by 2^{-32}. + * + * Arguments: - poly *c: pointer to output polynomial + * - const poly_frozen *a: pointer to first input polynomial + * - const poly *b: pointer to second input polynomial + **************************************************/ +void poly_pointwise_montgomery_frozen(poly *c, const poly_frozen *a, const poly *b) { + unsigned int i; + + for (i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); +} + /************************************************* * Name: poly_reduce2q * @@ -202,6 +220,39 @@ void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { } } +/************************************************* + * Name: poly_uniform_frozen + * + * Description: Sample polynomial with uniformly random coefficients + * in [0,Q-1] by performing rejection sampling on the + * output stream of SHAKE256(seed|nonce) + * + * Arguments: - poly *a: pointer to output polynomial + * - const uint8_t seed[]: byte array with seed of length SEEDBYTES + * - uint16_t nonce: 2-byte nonce + **************************************************/ +void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = rej_uniform_frozen(a->coeffs, N, buf, buflen); + + while (ctr < N) { + off = buflen % 2; + for (i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += rej_uniform_frozen(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + /************************************************* * Name: poly_uniform_eta * diff --git a/crypto_sign/haetae2/ref/poly.h b/crypto_sign/haetae2/ref/poly.h index 3c801b3b..b9049607 100644 --- a/crypto_sign/haetae2/ref/poly.h +++ b/crypto_sign/haetae2/ref/poly.h @@ -7,16 +7,33 @@ #include "sampler.h" #include +/********************************************************************** + * Name: poly + * Description: Holds the coefficients of a polynomial. + **********************************************************************/ typedef struct { int32_t coeffs[N]; } poly; +/********************************************************************** + * Name: poly_frozen + * Description: Holds the fully reduced coefficients of a polynomial, + * i.e. all coefficients are in the interval [0,q-1]. + * Typically used for polynomials which are used as + * read-only after initial computation. + **********************************************************************/ +typedef struct { + uint16_t coeffs[N]; +} poly_frozen; + #define poly_add HAETAE_NAMESPACE(poly_add) void poly_add(poly *c, const poly *a, const poly *b); #define poly_sub HAETAE_NAMESPACE(poly_sub) void poly_sub(poly *c, const poly *a, const poly *b); #define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); +#define poly_pointwise_montgomery_frozen HAETAE_NAMESPACE(poly_pointwise_montgomery_frozen) +void poly_pointwise_montgomery_frozen(poly *c, const poly_frozen *a, const poly *b); #define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) void poly_reduce2q(poly *a); @@ -36,6 +53,8 @@ void poly_lsb(poly *a0, const poly *a); #define poly_uniform HAETAE_NAMESPACE(poly_uniform) void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); +#define poly_uniform_frozen HAETAE_NAMESPACE(poly_uniform_frozen) +void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); #define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); #define poly_challenge HAETAE_NAMESPACE(poly_challenge) diff --git a/crypto_sign/haetae2/ref/polymat.c b/crypto_sign/haetae2/ref/polymat.c index c97f4dfb..9802e98a 100644 --- a/crypto_sign/haetae2/ref/polymat.c +++ b/crypto_sign/haetae2/ref/polymat.c @@ -23,6 +23,25 @@ void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); } +/************************************************* + * Name: polymat_expand + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|j|i) + * or AES256CTR(rho,j|i). + * + * Arguments: - polyvecm mat[K]: output matrix k \times m + * - const uint8_t rho[]: byte array containing seed rho + **************************************************/ +void polymatkl_expand_frozen(polyvecl_frozen mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for (i = 0; i < K; ++i) + for (j = 0; j < M; ++j) + poly_uniform_frozen(&mat[i].vec[j + 1], rho, (i << 8) + j); +} + /************************************************* * Name: polymat_expand * @@ -54,6 +73,18 @@ void polymatkl_double(polyvecl mat[K]) { } } +// doubles k * m sub-matrix of k * l mat +void polymatkl_double_frozen(polyvecl_frozen mat[K]) { + unsigned int i, j, k; + for (i = 0; i < K; ++i) { + for (j = 1; j < L; ++j) { + for (k = 0; k < N; ++k) { + mat[i].vec[j].coeffs[k] = (uint16_t) freeze(2 * ((int32_t) mat[i].vec[j].coeffs[k])); + } + } + } +} + void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { unsigned int i; @@ -63,6 +94,15 @@ void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], } } +void polymatkl_pointwise_montgomery_frozen(polyveck *t, const polyvecl_frozen mat[K], + const polyvecl *v) { + unsigned int i; + + for (i = 0; i < K; ++i) { + polyvecl_pointwise_acc_montgomery_frozen(&t->vec[i], &mat[i], v); + } +} + void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], const polyvecm *v) { unsigned int i; diff --git a/crypto_sign/haetae2/ref/polymat.h b/crypto_sign/haetae2/ref/polymat.h index c12bc28a..9aaa1e08 100644 --- a/crypto_sign/haetae2/ref/polymat.h +++ b/crypto_sign/haetae2/ref/polymat.h @@ -9,6 +9,9 @@ #define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); +#define polymatkl_expand_frozen HAETAE_NAMESPACE(polymatkl_expand_frozen) +void polymatkl_expand_frozen(polyvecl_frozen mat[K], const uint8_t rho[SEEDBYTES]); + #define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); @@ -22,7 +25,15 @@ void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); +#define polymatkl_pointwise_montgomery_frozen \ + HAETAE_NAMESPACE(polymatkl_pointwise_montgomery_frozen) +void polymatkl_pointwise_montgomery_frozen(polyveck *t, const polyvecl_frozen mat[K], + const polyvecl *v); + #define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) void polymatkl_double(polyvecl mat[K]); +#define polymatkl_double_frozen HAETAE_NAMESPACE(polymatkl_double_frozen) +void polymatkl_double_frozen(polyvecl_frozen mat[K]); + #endif diff --git a/crypto_sign/haetae2/ref/polyvec.c b/crypto_sign/haetae2/ref/polyvec.c index 3b8b0336..cec77b3f 100644 --- a/crypto_sign/haetae2/ref/polyvec.c +++ b/crypto_sign/haetae2/ref/polyvec.c @@ -412,6 +412,29 @@ void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, } } +/************************************************* + * Name: polyvecl_pointwise_acc_montgomery_frozen + * + * Description: Pointwise multiply vectors of polynomials of length L, multiply + * resulting vector by 2^{-32} and add (accumulate) polynomials + * in it. Input/output vectors are in NTT domain representation. + * + * Arguments: - poly *w: output polynomial + * - const polyvecl *u: pointer to first input vector + * - const polyvecl *v: pointer to second input vector + **************************************************/ +void polyvecl_pointwise_acc_montgomery_frozen(poly *w, const polyvecl_frozen *u, + const polyvecl *v) { + unsigned int i; + poly t; + + poly_pointwise_montgomery_frozen(w, &u->vec[0], &v->vec[0]); + for (i = 1; i < L; ++i) { + poly_pointwise_montgomery_frozen(&t, &u->vec[i], &v->vec[i]); + poly_add(w, w, &t); + } +} + void polyvecl_ntt(polyvecl *x) { unsigned int i; for (i = 0; i < L; i++) { diff --git a/crypto_sign/haetae2/ref/polyvec.h b/crypto_sign/haetae2/ref/polyvec.h index 8d48aa40..38659f0f 100644 --- a/crypto_sign/haetae2/ref/polyvec.h +++ b/crypto_sign/haetae2/ref/polyvec.h @@ -83,6 +83,11 @@ typedef struct { poly vec[L]; } polyvecl; +/* Vectors of frozen polynomials of length L */ +typedef struct { + poly_frozen vec[L]; +} polyvecl_frozen; + #define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) void polyvecl_cneg(polyvecl *v, const uint8_t b); @@ -102,6 +107,10 @@ void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, const polyvecl *v); +#define polyvecl_pointwise_acc_montgomery_frozen HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery_frozen) +void polyvecl_pointwise_acc_montgomery_frozen(poly *w, + const polyvecl_frozen *u, + const polyvecl *v); /* Vectors of polynomials of length M */ typedef struct { diff --git a/crypto_sign/haetae2/ref/sampler.c b/crypto_sign/haetae2/ref/sampler.c index 4bb546b3..35a3691f 100644 --- a/crypto_sign/haetae2/ref/sampler.c +++ b/crypto_sign/haetae2/ref/sampler.c @@ -33,6 +33,36 @@ unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, return ctr; } +/************************************************* + * Name: rej_uniform_frozen + * + * Description: Sample uniformly random coefficients in [0, Q-1] by + * performing rejection sampling on array of random bytes. + * + * Arguments: - int32_t *a: pointer to output array (allocated) + * - unsigned int len: number of coefficients to be sampled + * - const uint8_t *buf: array of random bytes + * - unsigned int buflen: length of array of random bytes + * + * Returns number of sampled coefficients. Can be smaller than len if not enough + * random bytes were given. + **************************************************/ +unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen) { + unsigned int ctr, pos; + uint16_t t; + + ctr = pos = 0; + while (ctr < len && pos + 2 <= buflen) { + t = buf[pos++]; + t |= (uint16_t)buf[pos++] << 8; + + if (t < Q) + a[ctr++] = t; + } + return ctr; +} + /************************************************* * Name: rej_eta * diff --git a/crypto_sign/haetae2/ref/sampler.h b/crypto_sign/haetae2/ref/sampler.h index adb71bfd..4f636775 100644 --- a/crypto_sign/haetae2/ref/sampler.h +++ b/crypto_sign/haetae2/ref/sampler.h @@ -9,6 +9,9 @@ #define rej_uniform HAETAE_NAMESPACE(rej_uniform) unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, unsigned int buflen); +#define rej_uniform_frozen HAETAE_NAMESPACE(rej_uniform_frozen) +unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, + unsigned int buflen); #define rej_eta HAETAE_NAMESPACE(rej_eta) unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, unsigned int buflen); diff --git a/crypto_sign/haetae2/ref/sign.c b/crypto_sign/haetae2/ref/sign.c index a53cac2b..438ae415 100644 --- a/crypto_sign/haetae2/ref/sign.c +++ b/crypto_sign/haetae2/ref/sign.c @@ -140,15 +140,18 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, uint64_t reject1, reject2; polyvecm s1; - polyvecl A1[K], cs1; - polyveck s2, cs2, highbits, Ay; - polyfixvecl y1, z1, z1tmp; - polyfixveck y2, z2, z2tmp; - polyvecl z1rnd; // round of z1 - polyvecl hb_z1, lb_z1; - polyveck z2rnd, h, htmp; // round of z2 + polyvecl_frozen A1[K]; + polyveck s2, highbits, Ay; poly c, chat, z1rnd0, lsb; + vecl1 vl1; // cs1, z1rnd, z1tmp + vecl2 vl2; // y1, lb_z1 + veck1 vk1; // cs2, z2rnd, z2tmp + veck2 vk2; // y2, htmp + vecl3 vl3; // z1, hb_z1 + veck3 vk3; // z2, h + + xof256_state state; unsigned int i; @@ -167,20 +170,20 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, reject: /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ - counter = polyfixveclk_sample_hyperball(&y1, &y2, &b, seedbuf, counter); + counter = polyfixveclk_sample_hyperball(&vl2.y1, &vk2.y2, &b, seedbuf, counter); /*------------------- 2. Compute a chanllenge c --------------------------*/ // Round y1 and y2 - polyfixvecl_round(&z1rnd, &y1); - polyfixveck_round(&z2rnd, &y2); + polyfixvecl_round(&vl1.z1rnd, &vl2.y1); + polyfixveck_round(&vk1.z2rnd, &vk2.y2); // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q - z1rnd0 = z1rnd.vec[0]; - polyvecl_ntt(&z1rnd); - polymatkl_pointwise_montgomery(&Ay, A1, &z1rnd); + z1rnd0 = vl1.z1rnd.vec[0]; + polyvecl_ntt(&vl1.z1rnd); + polymatkl_pointwise_montgomery_frozen(&Ay, A1, &vl1.z1rnd); polyveck_invntt_tomont(&Ay); - polyveck_double(&z2rnd); - polyveck_add(&Ay, &Ay, &z2rnd); + polyveck_double(&vk1.z2rnd); + polyveck_add(&Ay, &Ay, &vk1.z2rnd); // recover A * round(y) mod 2q polyveck_poly_fromcrt(&Ay, &Ay, &z1rnd0); @@ -201,36 +204,36 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ // cs = c * s = c * (si1 || s2) - cs1.vec[0] = c; + vl1.cs1.vec[0] = c; chat = c; poly_ntt(&chat); for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&cs1.vec[i], &chat, &s1.vec[i - 1]); - poly_invntt_tomont(&cs1.vec[i]); + poly_pointwise_montgomery(&vl1.cs1.vec[i], &chat, &s1.vec[i - 1]); + poly_invntt_tomont(&vl1.cs1.vec[i]); } - polyveck_poly_pointwise_montgomery(&cs2, &s2, &chat); - polyveck_invntt_tomont(&cs2); + polyveck_poly_pointwise_montgomery(&vk1.cs2, &s2, &chat); + polyveck_invntt_tomont(&vk1.cs2); // z = y + (-1)^b cs = z1 + z2 - polyvecl_cneg(&cs1, b & 1); - polyveck_cneg(&cs2, b & 1); - polyfixvecl_add(&z1, &y1, &cs1); - polyfixveck_add(&z2, &y2, &cs2); + polyvecl_cneg(&vl1.cs1, b & 1); + polyveck_cneg(&vk1.cs2, b & 1); + polyfixvecl_add(&vl3.z1, &vl2.y1, &vl1.cs1); + polyfixveck_add(&vk3.z2, &vk2.y2, &vk1.cs2); // reject if norm(z) >= B' - reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&z1, &z2)) >> 63; + reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&vl3.z1, &vk3.z2)) >> 63; reject1 &= 1; - polyfixvecl_double(&z1tmp, &z1); - polyfixveck_double(&z2tmp, &z2); + polyfixvecl_double(&vl1.z1tmp, &vl3.z1); + polyfixveck_double(&vk1.z2tmp, &vk3.z2); - polyfixfixvecl_sub(&z1tmp, &z1tmp, &y1); - polyfixfixveck_sub(&z2tmp, &z2tmp, &y2); + polyfixfixvecl_sub(&vl1.z1tmp, &vl1.z1tmp, &vl2.y1); + polyfixfixveck_sub(&vk1.z2tmp, &vk1.z2tmp, &vk2.y2); // reject if norm(2z-y) < B and b' = 0 reject2 = - (polyfixveclk_sqnorm2(&z1tmp, &z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; + (polyfixveclk_sqnorm2(&vl1.z1tmp, &vk1.z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; reject2 &= 1; reject2 &= (b & 0x2) >> 1; @@ -240,25 +243,25 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, /*------------------- 4. Make a hint -------------------------------------*/ // Round z1 and z2 - polyfixvecl_round(&z1rnd, &z1); - polyfixveck_round(&z2rnd, &z2); + polyfixvecl_round(&vl1.z1rnd, &vl3.z1); + polyfixveck_round(&vk1.z2rnd, &vk3.z2); // recover A1 * round(z1) - qcj mod 2q - polyveck_double(&z2rnd); - polyveck_sub(&htmp, &Ay, &z2rnd); - polyveck_freeze2q(&htmp); + polyveck_double(&vk1.z2rnd); + polyveck_sub(&vk2.htmp, &Ay, &vk1.z2rnd); + polyveck_freeze2q(&vk2.htmp); // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) - polyveck_highbits_hint(&htmp, &htmp); - polyveck_sub(&h, &highbits, &htmp); - polyveck_caddDQ2ALPHA(&h); + polyveck_highbits_hint(&vk2.htmp, &vk2.htmp); + polyveck_sub(&vk3.h, &highbits, &vk2.htmp); + polyveck_caddDQ2ALPHA(&vk3.h); /*------------------ Decompose(z1) and Pack signature -------------------*/ - polyvecl_lowbits(&lb_z1, &z1rnd); // TODO do this in one function together! - polyvecl_highbits(&hb_z1, &z1rnd); + polyvecl_lowbits(&vl2.lb_z1, &vl1.z1rnd); // TODO do this in one function together! + polyvecl_highbits(&vl3.hb_z1, &vl1.z1rnd); - if (pack_sig(sig, &c, &lb_z1, &hb_z1, - &h)) { // reject if signature is too big + if (pack_sig(sig, &c, &vl2.lb_z1, &vl3.hb_z1, + &vk3.h)) { // reject if signature is too big goto reject; } *siglen = CRYPTO_BYTES; diff --git a/crypto_sign/haetae2/ref/sign.h b/crypto_sign/haetae2/ref/sign.h index edfc0e80..27e6a0b0 100644 --- a/crypto_sign/haetae2/ref/sign.h +++ b/crypto_sign/haetae2/ref/sign.h @@ -5,9 +5,42 @@ #include "poly.h" #include "polymat.h" #include "polyvec.h" +#include "polyfix.h" #include #include +typedef union { + polyvecl cs1; + polyvecl z1rnd; + polyfixvecl z1tmp; +} vecl1; + +typedef union { + polyveck cs2; + polyveck z2rnd; + polyfixveck z2tmp; +} veck1; + +typedef union { + polyfixvecl y1; + polyvecl lb_z1; +} vecl2; + +typedef union { + polyfixveck y2; + polyveck htmp; +} veck2; + +typedef union { + polyfixvecl z1; + polyvecl hb_z1; +} vecl3; + +typedef union { + polyfixveck z2; + polyveck h; +} veck3; + #define crypto_sign_keypair HAETAE_NAMESPACE(keypair) int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); diff --git a/crypto_sign/haetae3/ref/api.h b/crypto_sign/haetae3/ref/api.h new file mode 120000 index 00000000..4cc87a52 --- /dev/null +++ b/crypto_sign/haetae3/ref/api.h @@ -0,0 +1 @@ +../../haetae2/ref/api.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/config.h b/crypto_sign/haetae3/ref/config.h new file mode 100644 index 00000000..0748c077 --- /dev/null +++ b/crypto_sign/haetae3/ref/config.h @@ -0,0 +1,20 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 3 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif /* if HAETAE_MODE */ + +#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae3/ref/decompose.c b/crypto_sign/haetae3/ref/decompose.c new file mode 120000 index 00000000..ae51ead9 --- /dev/null +++ b/crypto_sign/haetae3/ref/decompose.c @@ -0,0 +1 @@ +../../haetae2/ref/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/decompose.h b/crypto_sign/haetae3/ref/decompose.h new file mode 120000 index 00000000..a0b57cf4 --- /dev/null +++ b/crypto_sign/haetae3/ref/decompose.h @@ -0,0 +1 @@ +../../haetae2/ref/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/encoding.c b/crypto_sign/haetae3/ref/encoding.c new file mode 120000 index 00000000..21c33670 --- /dev/null +++ b/crypto_sign/haetae3/ref/encoding.c @@ -0,0 +1 @@ +../../haetae2/ref/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/encoding.h b/crypto_sign/haetae3/ref/encoding.h new file mode 120000 index 00000000..228432d5 --- /dev/null +++ b/crypto_sign/haetae3/ref/encoding.h @@ -0,0 +1 @@ +../../haetae2/ref/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fft.c b/crypto_sign/haetae3/ref/fft.c new file mode 120000 index 00000000..1e693203 --- /dev/null +++ b/crypto_sign/haetae3/ref/fft.c @@ -0,0 +1 @@ +../../haetae2/ref/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fft.h b/crypto_sign/haetae3/ref/fft.h new file mode 120000 index 00000000..8c5f7907 --- /dev/null +++ b/crypto_sign/haetae3/ref/fft.h @@ -0,0 +1 @@ +../../haetae2/ref/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fips202.c b/crypto_sign/haetae3/ref/fips202.c new file mode 120000 index 00000000..40cab797 --- /dev/null +++ b/crypto_sign/haetae3/ref/fips202.c @@ -0,0 +1 @@ +../../haetae2/ref/fips202.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fips202.h b/crypto_sign/haetae3/ref/fips202.h new file mode 120000 index 00000000..3845b909 --- /dev/null +++ b/crypto_sign/haetae3/ref/fips202.h @@ -0,0 +1 @@ +../../haetae2/ref/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fixpoint.c b/crypto_sign/haetae3/ref/fixpoint.c new file mode 120000 index 00000000..600c0752 --- /dev/null +++ b/crypto_sign/haetae3/ref/fixpoint.c @@ -0,0 +1 @@ +../../haetae2/ref/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fixpoint.h b/crypto_sign/haetae3/ref/fixpoint.h new file mode 120000 index 00000000..03e6dbb7 --- /dev/null +++ b/crypto_sign/haetae3/ref/fixpoint.h @@ -0,0 +1 @@ +../../haetae2/ref/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/ntt.c b/crypto_sign/haetae3/ref/ntt.c new file mode 120000 index 00000000..1ac478b5 --- /dev/null +++ b/crypto_sign/haetae3/ref/ntt.c @@ -0,0 +1 @@ +../../haetae2/ref/ntt.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/ntt.h b/crypto_sign/haetae3/ref/ntt.h new file mode 120000 index 00000000..7d8e40b8 --- /dev/null +++ b/crypto_sign/haetae3/ref/ntt.h @@ -0,0 +1 @@ +../../haetae2/ref/ntt.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/packing.c b/crypto_sign/haetae3/ref/packing.c new file mode 120000 index 00000000..ed6a9940 --- /dev/null +++ b/crypto_sign/haetae3/ref/packing.c @@ -0,0 +1 @@ +../../haetae2/ref/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/packing.h b/crypto_sign/haetae3/ref/packing.h new file mode 120000 index 00000000..bfc421a3 --- /dev/null +++ b/crypto_sign/haetae3/ref/packing.h @@ -0,0 +1 @@ +../../haetae2/ref/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/params.h b/crypto_sign/haetae3/ref/params.h new file mode 120000 index 00000000..b60911fc --- /dev/null +++ b/crypto_sign/haetae3/ref/params.h @@ -0,0 +1 @@ +../../haetae2/ref/params.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/poly.c b/crypto_sign/haetae3/ref/poly.c new file mode 120000 index 00000000..39ccd75a --- /dev/null +++ b/crypto_sign/haetae3/ref/poly.c @@ -0,0 +1 @@ +../../haetae2/ref/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/poly.h b/crypto_sign/haetae3/ref/poly.h new file mode 120000 index 00000000..a0ae8937 --- /dev/null +++ b/crypto_sign/haetae3/ref/poly.h @@ -0,0 +1 @@ +../../haetae2/ref/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyfix.c b/crypto_sign/haetae3/ref/polyfix.c new file mode 120000 index 00000000..f5de52c9 --- /dev/null +++ b/crypto_sign/haetae3/ref/polyfix.c @@ -0,0 +1 @@ +../../haetae2/ref/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyfix.h b/crypto_sign/haetae3/ref/polyfix.h new file mode 120000 index 00000000..7fd30789 --- /dev/null +++ b/crypto_sign/haetae3/ref/polyfix.h @@ -0,0 +1 @@ +../../haetae2/ref/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polymat.c b/crypto_sign/haetae3/ref/polymat.c new file mode 120000 index 00000000..6437bb1a --- /dev/null +++ b/crypto_sign/haetae3/ref/polymat.c @@ -0,0 +1 @@ +../../haetae2/ref/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polymat.h b/crypto_sign/haetae3/ref/polymat.h new file mode 120000 index 00000000..65909b3d --- /dev/null +++ b/crypto_sign/haetae3/ref/polymat.h @@ -0,0 +1 @@ +../../haetae2/ref/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyvec.c b/crypto_sign/haetae3/ref/polyvec.c new file mode 120000 index 00000000..a030bd9f --- /dev/null +++ b/crypto_sign/haetae3/ref/polyvec.c @@ -0,0 +1 @@ +../../haetae2/ref/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyvec.h b/crypto_sign/haetae3/ref/polyvec.h new file mode 120000 index 00000000..8737f657 --- /dev/null +++ b/crypto_sign/haetae3/ref/polyvec.h @@ -0,0 +1 @@ +../../haetae2/ref/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/rans_byte.h b/crypto_sign/haetae3/ref/rans_byte.h new file mode 120000 index 00000000..56556a86 --- /dev/null +++ b/crypto_sign/haetae3/ref/rans_byte.h @@ -0,0 +1 @@ +../../haetae2/ref/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/reduce.c b/crypto_sign/haetae3/ref/reduce.c new file mode 120000 index 00000000..2c77824c --- /dev/null +++ b/crypto_sign/haetae3/ref/reduce.c @@ -0,0 +1 @@ +../../haetae2/ref/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/reduce.h b/crypto_sign/haetae3/ref/reduce.h new file mode 120000 index 00000000..beaf84e3 --- /dev/null +++ b/crypto_sign/haetae3/ref/reduce.h @@ -0,0 +1 @@ +../../haetae2/ref/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sampler.c b/crypto_sign/haetae3/ref/sampler.c new file mode 120000 index 00000000..db1ffe9c --- /dev/null +++ b/crypto_sign/haetae3/ref/sampler.c @@ -0,0 +1 @@ +../../haetae2/ref/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sampler.h b/crypto_sign/haetae3/ref/sampler.h new file mode 120000 index 00000000..cca2cc46 --- /dev/null +++ b/crypto_sign/haetae3/ref/sampler.h @@ -0,0 +1 @@ +../../haetae2/ref/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sign.c b/crypto_sign/haetae3/ref/sign.c new file mode 120000 index 00000000..f7d3d524 --- /dev/null +++ b/crypto_sign/haetae3/ref/sign.c @@ -0,0 +1 @@ +../../haetae2/ref/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sign.h b/crypto_sign/haetae3/ref/sign.h new file mode 120000 index 00000000..7c12c2e9 --- /dev/null +++ b/crypto_sign/haetae3/ref/sign.h @@ -0,0 +1 @@ +../../haetae2/ref/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/symmetric-shake.c b/crypto_sign/haetae3/ref/symmetric-shake.c new file mode 120000 index 00000000..0cf4a8a9 --- /dev/null +++ b/crypto_sign/haetae3/ref/symmetric-shake.c @@ -0,0 +1 @@ +../../haetae2/ref/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/symmetric.h b/crypto_sign/haetae3/ref/symmetric.h new file mode 120000 index 00000000..341745bf --- /dev/null +++ b/crypto_sign/haetae3/ref/symmetric.h @@ -0,0 +1 @@ +../../haetae2/ref/symmetric.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/api.h b/crypto_sign/haetae5/ref/api.h new file mode 120000 index 00000000..4cc87a52 --- /dev/null +++ b/crypto_sign/haetae5/ref/api.h @@ -0,0 +1 @@ +../../haetae2/ref/api.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/config.h b/crypto_sign/haetae5/ref/config.h new file mode 100644 index 00000000..4ea01f5c --- /dev/null +++ b/crypto_sign/haetae5/ref/config.h @@ -0,0 +1,20 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define HAETAE_MODE 5 + +#if HAETAE_MODE == 2 +#define CRYPTO_ALGNAME "HAETAE2" +#define HAETAE_NAMESPACETOP haetae2 +#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s +#elif HAETAE_MODE == 3 +#define CRYPTO_ALGNAME "HAETAE3" +#define HAETAE_NAMESPACETOP haetae3 +#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s +#elif HAETAE_MODE == 5 +#define CRYPTO_ALGNAME "HAETAE5" +#define HAETAE_NAMESPACETOP haetae5 +#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s +#endif /* if HAETAE_MODE */ + +#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae5/ref/decompose.c b/crypto_sign/haetae5/ref/decompose.c new file mode 120000 index 00000000..ae51ead9 --- /dev/null +++ b/crypto_sign/haetae5/ref/decompose.c @@ -0,0 +1 @@ +../../haetae2/ref/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/decompose.h b/crypto_sign/haetae5/ref/decompose.h new file mode 120000 index 00000000..a0b57cf4 --- /dev/null +++ b/crypto_sign/haetae5/ref/decompose.h @@ -0,0 +1 @@ +../../haetae2/ref/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/encoding.c b/crypto_sign/haetae5/ref/encoding.c new file mode 120000 index 00000000..21c33670 --- /dev/null +++ b/crypto_sign/haetae5/ref/encoding.c @@ -0,0 +1 @@ +../../haetae2/ref/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/encoding.h b/crypto_sign/haetae5/ref/encoding.h new file mode 120000 index 00000000..228432d5 --- /dev/null +++ b/crypto_sign/haetae5/ref/encoding.h @@ -0,0 +1 @@ +../../haetae2/ref/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fft.c b/crypto_sign/haetae5/ref/fft.c new file mode 120000 index 00000000..1e693203 --- /dev/null +++ b/crypto_sign/haetae5/ref/fft.c @@ -0,0 +1 @@ +../../haetae2/ref/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fft.h b/crypto_sign/haetae5/ref/fft.h new file mode 120000 index 00000000..8c5f7907 --- /dev/null +++ b/crypto_sign/haetae5/ref/fft.h @@ -0,0 +1 @@ +../../haetae2/ref/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fips202.c b/crypto_sign/haetae5/ref/fips202.c new file mode 120000 index 00000000..40cab797 --- /dev/null +++ b/crypto_sign/haetae5/ref/fips202.c @@ -0,0 +1 @@ +../../haetae2/ref/fips202.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fips202.h b/crypto_sign/haetae5/ref/fips202.h new file mode 120000 index 00000000..3845b909 --- /dev/null +++ b/crypto_sign/haetae5/ref/fips202.h @@ -0,0 +1 @@ +../../haetae2/ref/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fixpoint.c b/crypto_sign/haetae5/ref/fixpoint.c new file mode 120000 index 00000000..600c0752 --- /dev/null +++ b/crypto_sign/haetae5/ref/fixpoint.c @@ -0,0 +1 @@ +../../haetae2/ref/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fixpoint.h b/crypto_sign/haetae5/ref/fixpoint.h new file mode 120000 index 00000000..03e6dbb7 --- /dev/null +++ b/crypto_sign/haetae5/ref/fixpoint.h @@ -0,0 +1 @@ +../../haetae2/ref/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/ntt.c b/crypto_sign/haetae5/ref/ntt.c new file mode 120000 index 00000000..1ac478b5 --- /dev/null +++ b/crypto_sign/haetae5/ref/ntt.c @@ -0,0 +1 @@ +../../haetae2/ref/ntt.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/ntt.h b/crypto_sign/haetae5/ref/ntt.h new file mode 120000 index 00000000..7d8e40b8 --- /dev/null +++ b/crypto_sign/haetae5/ref/ntt.h @@ -0,0 +1 @@ +../../haetae2/ref/ntt.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/packing.c b/crypto_sign/haetae5/ref/packing.c new file mode 120000 index 00000000..ed6a9940 --- /dev/null +++ b/crypto_sign/haetae5/ref/packing.c @@ -0,0 +1 @@ +../../haetae2/ref/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/packing.h b/crypto_sign/haetae5/ref/packing.h new file mode 120000 index 00000000..bfc421a3 --- /dev/null +++ b/crypto_sign/haetae5/ref/packing.h @@ -0,0 +1 @@ +../../haetae2/ref/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/params.h b/crypto_sign/haetae5/ref/params.h new file mode 120000 index 00000000..b60911fc --- /dev/null +++ b/crypto_sign/haetae5/ref/params.h @@ -0,0 +1 @@ +../../haetae2/ref/params.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/poly.c b/crypto_sign/haetae5/ref/poly.c new file mode 120000 index 00000000..39ccd75a --- /dev/null +++ b/crypto_sign/haetae5/ref/poly.c @@ -0,0 +1 @@ +../../haetae2/ref/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/poly.h b/crypto_sign/haetae5/ref/poly.h new file mode 120000 index 00000000..a0ae8937 --- /dev/null +++ b/crypto_sign/haetae5/ref/poly.h @@ -0,0 +1 @@ +../../haetae2/ref/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyfix.c b/crypto_sign/haetae5/ref/polyfix.c new file mode 120000 index 00000000..f5de52c9 --- /dev/null +++ b/crypto_sign/haetae5/ref/polyfix.c @@ -0,0 +1 @@ +../../haetae2/ref/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyfix.h b/crypto_sign/haetae5/ref/polyfix.h new file mode 120000 index 00000000..7fd30789 --- /dev/null +++ b/crypto_sign/haetae5/ref/polyfix.h @@ -0,0 +1 @@ +../../haetae2/ref/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polymat.c b/crypto_sign/haetae5/ref/polymat.c new file mode 120000 index 00000000..6437bb1a --- /dev/null +++ b/crypto_sign/haetae5/ref/polymat.c @@ -0,0 +1 @@ +../../haetae2/ref/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polymat.h b/crypto_sign/haetae5/ref/polymat.h new file mode 120000 index 00000000..65909b3d --- /dev/null +++ b/crypto_sign/haetae5/ref/polymat.h @@ -0,0 +1 @@ +../../haetae2/ref/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyvec.c b/crypto_sign/haetae5/ref/polyvec.c new file mode 120000 index 00000000..a030bd9f --- /dev/null +++ b/crypto_sign/haetae5/ref/polyvec.c @@ -0,0 +1 @@ +../../haetae2/ref/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyvec.h b/crypto_sign/haetae5/ref/polyvec.h new file mode 120000 index 00000000..8737f657 --- /dev/null +++ b/crypto_sign/haetae5/ref/polyvec.h @@ -0,0 +1 @@ +../../haetae2/ref/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/rans_byte.h b/crypto_sign/haetae5/ref/rans_byte.h new file mode 120000 index 00000000..56556a86 --- /dev/null +++ b/crypto_sign/haetae5/ref/rans_byte.h @@ -0,0 +1 @@ +../../haetae2/ref/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/reduce.c b/crypto_sign/haetae5/ref/reduce.c new file mode 120000 index 00000000..2c77824c --- /dev/null +++ b/crypto_sign/haetae5/ref/reduce.c @@ -0,0 +1 @@ +../../haetae2/ref/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/reduce.h b/crypto_sign/haetae5/ref/reduce.h new file mode 120000 index 00000000..beaf84e3 --- /dev/null +++ b/crypto_sign/haetae5/ref/reduce.h @@ -0,0 +1 @@ +../../haetae2/ref/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sampler.c b/crypto_sign/haetae5/ref/sampler.c new file mode 120000 index 00000000..db1ffe9c --- /dev/null +++ b/crypto_sign/haetae5/ref/sampler.c @@ -0,0 +1 @@ +../../haetae2/ref/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sampler.h b/crypto_sign/haetae5/ref/sampler.h new file mode 120000 index 00000000..cca2cc46 --- /dev/null +++ b/crypto_sign/haetae5/ref/sampler.h @@ -0,0 +1 @@ +../../haetae2/ref/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sign.c b/crypto_sign/haetae5/ref/sign.c new file mode 120000 index 00000000..f7d3d524 --- /dev/null +++ b/crypto_sign/haetae5/ref/sign.c @@ -0,0 +1 @@ +../../haetae2/ref/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sign.h b/crypto_sign/haetae5/ref/sign.h new file mode 120000 index 00000000..7c12c2e9 --- /dev/null +++ b/crypto_sign/haetae5/ref/sign.h @@ -0,0 +1 @@ +../../haetae2/ref/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/symmetric-shake.c b/crypto_sign/haetae5/ref/symmetric-shake.c new file mode 120000 index 00000000..0cf4a8a9 --- /dev/null +++ b/crypto_sign/haetae5/ref/symmetric-shake.c @@ -0,0 +1 @@ +../../haetae2/ref/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/symmetric.h b/crypto_sign/haetae5/ref/symmetric.h new file mode 120000 index 00000000..341745bf --- /dev/null +++ b/crypto_sign/haetae5/ref/symmetric.h @@ -0,0 +1 @@ +../../haetae2/ref/symmetric.h \ No newline at end of file diff --git a/ldscripts/stm32f4discovery.ld b/ldscripts/stm32f4discovery.ld index a3fb9f17..fb18aec5 100644 --- a/ldscripts/stm32f4discovery.ld +++ b/ldscripts/stm32f4discovery.ld @@ -58,6 +58,7 @@ SECTIONS *(COMMON) . = ALIGN(4); _ebss = .; + end = .; } >ram .ram2 : { *(.ram2*) @@ -69,6 +70,5 @@ SECTIONS } >ccm /DISCARD/ : { *(.eh_frame) } . = ALIGN(4); - end = .; } PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/ldscripts/stm32f4discovery_fullram.ld b/ldscripts/stm32f4discovery_fullram.ld index c1477e8d..c2f11263 100644 --- a/ldscripts/stm32f4discovery_fullram.ld +++ b/ldscripts/stm32f4discovery_fullram.ld @@ -57,6 +57,7 @@ SECTIONS *(COMMON) . = ALIGN(4); _ebss = .; + end = .; } >ram .ccm : { *(.ccmram*) @@ -64,6 +65,5 @@ SECTIONS } >ccm /DISCARD/ : { *(.eh_frame) } . = ALIGN(4); - end = .; } PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 41862137..4142b008 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -13,3 +13,5 @@ elf/boardtest-fast.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_CCM elf/crypto_kem_frodokem640aes_m4_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/mupq_pqclean_crypto_kem_frodokem640shake_opt_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/crypto_sign_dilithium5_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld +elf/crypto_sign_haetae5_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld +elf/crypto_sign_haetae5_ref_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld From 8719b8eae7767aa2ee64c1a643f468730245ca81 Mon Sep 17 00:00:00 2001 From: Marc Date: Fri, 1 Dec 2023 11:39:22 +0100 Subject: [PATCH 046/107] Move reference implementations to MUPQ/MUPQ The pure C reference implementations were removed from this pull request. A corresponding pull request in MUPQ/MUPQ has been initiated: https://github.com/mupq/mupq/pull/131 --- crypto_sign/haetae2/ref/api.h | 6 - crypto_sign/haetae2/ref/config.h | 20 - crypto_sign/haetae2/ref/decompose.c | 69 -- crypto_sign/haetae2/ref/decompose.h | 16 - crypto_sign/haetae2/ref/encoding.c | 227 ------- crypto_sign/haetae2/ref/encoding.h | 17 - crypto_sign/haetae2/ref/fft.c | 231 ------- crypto_sign/haetae2/ref/fft.h | 19 - crypto_sign/haetae2/ref/fips202.c | 746 ---------------------- crypto_sign/haetae2/ref/fips202.h | 57 -- crypto_sign/haetae2/ref/fixpoint.c | 140 ---- crypto_sign/haetae2/ref/fixpoint.h | 126 ---- crypto_sign/haetae2/ref/ntt.c | 95 --- crypto_sign/haetae2/ref/ntt.h | 13 - crypto_sign/haetae2/ref/packing.c | 281 -------- crypto_sign/haetae2/ref/packing.h | 25 - crypto_sign/haetae2/ref/params.h | 116 ---- crypto_sign/haetae2/ref/poly.c | 710 -------------------- crypto_sign/haetae2/ref/poly.h | 99 --- crypto_sign/haetae2/ref/polyfix.c | 292 --------- crypto_sign/haetae2/ref/polyfix.h | 61 -- crypto_sign/haetae2/ref/polymat.c | 113 ---- crypto_sign/haetae2/ref/polymat.h | 39 -- crypto_sign/haetae2/ref/polyvec.c | 566 ---------------- crypto_sign/haetae2/ref/polyvec.h | 138 ---- crypto_sign/haetae2/ref/rans_byte.h | 333 ---------- crypto_sign/haetae2/ref/reduce.c | 92 --- crypto_sign/haetae2/ref/reduce.h | 28 - crypto_sign/haetae2/ref/sampler.c | 302 --------- crypto_sign/haetae2/ref/sampler.h | 24 - crypto_sign/haetae2/ref/sign.c | 456 ------------- crypto_sign/haetae2/ref/sign.h | 63 -- crypto_sign/haetae2/ref/symmetric-shake.c | 38 -- crypto_sign/haetae2/ref/symmetric.h | 78 --- crypto_sign/haetae3/ref/api.h | 1 - crypto_sign/haetae3/ref/config.h | 20 - crypto_sign/haetae3/ref/decompose.c | 1 - crypto_sign/haetae3/ref/decompose.h | 1 - crypto_sign/haetae3/ref/encoding.c | 1 - crypto_sign/haetae3/ref/encoding.h | 1 - crypto_sign/haetae3/ref/fft.c | 1 - crypto_sign/haetae3/ref/fft.h | 1 - crypto_sign/haetae3/ref/fips202.c | 1 - crypto_sign/haetae3/ref/fips202.h | 1 - crypto_sign/haetae3/ref/fixpoint.c | 1 - crypto_sign/haetae3/ref/fixpoint.h | 1 - crypto_sign/haetae3/ref/ntt.c | 1 - crypto_sign/haetae3/ref/ntt.h | 1 - crypto_sign/haetae3/ref/packing.c | 1 - crypto_sign/haetae3/ref/packing.h | 1 - crypto_sign/haetae3/ref/params.h | 1 - crypto_sign/haetae3/ref/poly.c | 1 - crypto_sign/haetae3/ref/poly.h | 1 - crypto_sign/haetae3/ref/polyfix.c | 1 - crypto_sign/haetae3/ref/polyfix.h | 1 - crypto_sign/haetae3/ref/polymat.c | 1 - crypto_sign/haetae3/ref/polymat.h | 1 - crypto_sign/haetae3/ref/polyvec.c | 1 - crypto_sign/haetae3/ref/polyvec.h | 1 - crypto_sign/haetae3/ref/rans_byte.h | 1 - crypto_sign/haetae3/ref/reduce.c | 1 - crypto_sign/haetae3/ref/reduce.h | 1 - crypto_sign/haetae3/ref/sampler.c | 1 - crypto_sign/haetae3/ref/sampler.h | 1 - crypto_sign/haetae3/ref/sign.c | 1 - crypto_sign/haetae3/ref/sign.h | 1 - crypto_sign/haetae3/ref/symmetric-shake.c | 1 - crypto_sign/haetae3/ref/symmetric.h | 1 - crypto_sign/haetae5/ref/api.h | 1 - crypto_sign/haetae5/ref/config.h | 20 - crypto_sign/haetae5/ref/decompose.c | 1 - crypto_sign/haetae5/ref/decompose.h | 1 - crypto_sign/haetae5/ref/encoding.c | 1 - crypto_sign/haetae5/ref/encoding.h | 1 - crypto_sign/haetae5/ref/fft.c | 1 - crypto_sign/haetae5/ref/fft.h | 1 - crypto_sign/haetae5/ref/fips202.c | 1 - crypto_sign/haetae5/ref/fips202.h | 1 - crypto_sign/haetae5/ref/fixpoint.c | 1 - crypto_sign/haetae5/ref/fixpoint.h | 1 - crypto_sign/haetae5/ref/ntt.c | 1 - crypto_sign/haetae5/ref/ntt.h | 1 - crypto_sign/haetae5/ref/packing.c | 1 - crypto_sign/haetae5/ref/packing.h | 1 - crypto_sign/haetae5/ref/params.h | 1 - crypto_sign/haetae5/ref/poly.c | 1 - crypto_sign/haetae5/ref/poly.h | 1 - crypto_sign/haetae5/ref/polyfix.c | 1 - crypto_sign/haetae5/ref/polyfix.h | 1 - crypto_sign/haetae5/ref/polymat.c | 1 - crypto_sign/haetae5/ref/polymat.h | 1 - crypto_sign/haetae5/ref/polyvec.c | 1 - crypto_sign/haetae5/ref/polyvec.h | 1 - crypto_sign/haetae5/ref/rans_byte.h | 1 - crypto_sign/haetae5/ref/reduce.c | 1 - crypto_sign/haetae5/ref/reduce.h | 1 - crypto_sign/haetae5/ref/sampler.c | 1 - crypto_sign/haetae5/ref/sampler.h | 1 - crypto_sign/haetae5/ref/sign.c | 1 - crypto_sign/haetae5/ref/sign.h | 1 - crypto_sign/haetae5/ref/symmetric-shake.c | 1 - crypto_sign/haetae5/ref/symmetric.h | 1 - 102 files changed, 5742 deletions(-) delete mode 100644 crypto_sign/haetae2/ref/api.h delete mode 100644 crypto_sign/haetae2/ref/config.h delete mode 100644 crypto_sign/haetae2/ref/decompose.c delete mode 100644 crypto_sign/haetae2/ref/decompose.h delete mode 100644 crypto_sign/haetae2/ref/encoding.c delete mode 100644 crypto_sign/haetae2/ref/encoding.h delete mode 100644 crypto_sign/haetae2/ref/fft.c delete mode 100644 crypto_sign/haetae2/ref/fft.h delete mode 100644 crypto_sign/haetae2/ref/fips202.c delete mode 100644 crypto_sign/haetae2/ref/fips202.h delete mode 100644 crypto_sign/haetae2/ref/fixpoint.c delete mode 100644 crypto_sign/haetae2/ref/fixpoint.h delete mode 100644 crypto_sign/haetae2/ref/ntt.c delete mode 100644 crypto_sign/haetae2/ref/ntt.h delete mode 100644 crypto_sign/haetae2/ref/packing.c delete mode 100644 crypto_sign/haetae2/ref/packing.h delete mode 100644 crypto_sign/haetae2/ref/params.h delete mode 100644 crypto_sign/haetae2/ref/poly.c delete mode 100644 crypto_sign/haetae2/ref/poly.h delete mode 100644 crypto_sign/haetae2/ref/polyfix.c delete mode 100644 crypto_sign/haetae2/ref/polyfix.h delete mode 100644 crypto_sign/haetae2/ref/polymat.c delete mode 100644 crypto_sign/haetae2/ref/polymat.h delete mode 100644 crypto_sign/haetae2/ref/polyvec.c delete mode 100644 crypto_sign/haetae2/ref/polyvec.h delete mode 100644 crypto_sign/haetae2/ref/rans_byte.h delete mode 100644 crypto_sign/haetae2/ref/reduce.c delete mode 100644 crypto_sign/haetae2/ref/reduce.h delete mode 100644 crypto_sign/haetae2/ref/sampler.c delete mode 100644 crypto_sign/haetae2/ref/sampler.h delete mode 100644 crypto_sign/haetae2/ref/sign.c delete mode 100644 crypto_sign/haetae2/ref/sign.h delete mode 100644 crypto_sign/haetae2/ref/symmetric-shake.c delete mode 100644 crypto_sign/haetae2/ref/symmetric.h delete mode 120000 crypto_sign/haetae3/ref/api.h delete mode 100644 crypto_sign/haetae3/ref/config.h delete mode 120000 crypto_sign/haetae3/ref/decompose.c delete mode 120000 crypto_sign/haetae3/ref/decompose.h delete mode 120000 crypto_sign/haetae3/ref/encoding.c delete mode 120000 crypto_sign/haetae3/ref/encoding.h delete mode 120000 crypto_sign/haetae3/ref/fft.c delete mode 120000 crypto_sign/haetae3/ref/fft.h delete mode 120000 crypto_sign/haetae3/ref/fips202.c delete mode 120000 crypto_sign/haetae3/ref/fips202.h delete mode 120000 crypto_sign/haetae3/ref/fixpoint.c delete mode 120000 crypto_sign/haetae3/ref/fixpoint.h delete mode 120000 crypto_sign/haetae3/ref/ntt.c delete mode 120000 crypto_sign/haetae3/ref/ntt.h delete mode 120000 crypto_sign/haetae3/ref/packing.c delete mode 120000 crypto_sign/haetae3/ref/packing.h delete mode 120000 crypto_sign/haetae3/ref/params.h delete mode 120000 crypto_sign/haetae3/ref/poly.c delete mode 120000 crypto_sign/haetae3/ref/poly.h delete mode 120000 crypto_sign/haetae3/ref/polyfix.c delete mode 120000 crypto_sign/haetae3/ref/polyfix.h delete mode 120000 crypto_sign/haetae3/ref/polymat.c delete mode 120000 crypto_sign/haetae3/ref/polymat.h delete mode 120000 crypto_sign/haetae3/ref/polyvec.c delete mode 120000 crypto_sign/haetae3/ref/polyvec.h delete mode 120000 crypto_sign/haetae3/ref/rans_byte.h delete mode 120000 crypto_sign/haetae3/ref/reduce.c delete mode 120000 crypto_sign/haetae3/ref/reduce.h delete mode 120000 crypto_sign/haetae3/ref/sampler.c delete mode 120000 crypto_sign/haetae3/ref/sampler.h delete mode 120000 crypto_sign/haetae3/ref/sign.c delete mode 120000 crypto_sign/haetae3/ref/sign.h delete mode 120000 crypto_sign/haetae3/ref/symmetric-shake.c delete mode 120000 crypto_sign/haetae3/ref/symmetric.h delete mode 120000 crypto_sign/haetae5/ref/api.h delete mode 100644 crypto_sign/haetae5/ref/config.h delete mode 120000 crypto_sign/haetae5/ref/decompose.c delete mode 120000 crypto_sign/haetae5/ref/decompose.h delete mode 120000 crypto_sign/haetae5/ref/encoding.c delete mode 120000 crypto_sign/haetae5/ref/encoding.h delete mode 120000 crypto_sign/haetae5/ref/fft.c delete mode 120000 crypto_sign/haetae5/ref/fft.h delete mode 120000 crypto_sign/haetae5/ref/fips202.c delete mode 120000 crypto_sign/haetae5/ref/fips202.h delete mode 120000 crypto_sign/haetae5/ref/fixpoint.c delete mode 120000 crypto_sign/haetae5/ref/fixpoint.h delete mode 120000 crypto_sign/haetae5/ref/ntt.c delete mode 120000 crypto_sign/haetae5/ref/ntt.h delete mode 120000 crypto_sign/haetae5/ref/packing.c delete mode 120000 crypto_sign/haetae5/ref/packing.h delete mode 120000 crypto_sign/haetae5/ref/params.h delete mode 120000 crypto_sign/haetae5/ref/poly.c delete mode 120000 crypto_sign/haetae5/ref/poly.h delete mode 120000 crypto_sign/haetae5/ref/polyfix.c delete mode 120000 crypto_sign/haetae5/ref/polyfix.h delete mode 120000 crypto_sign/haetae5/ref/polymat.c delete mode 120000 crypto_sign/haetae5/ref/polymat.h delete mode 120000 crypto_sign/haetae5/ref/polyvec.c delete mode 120000 crypto_sign/haetae5/ref/polyvec.h delete mode 120000 crypto_sign/haetae5/ref/rans_byte.h delete mode 120000 crypto_sign/haetae5/ref/reduce.c delete mode 120000 crypto_sign/haetae5/ref/reduce.h delete mode 120000 crypto_sign/haetae5/ref/sampler.c delete mode 120000 crypto_sign/haetae5/ref/sampler.h delete mode 120000 crypto_sign/haetae5/ref/sign.c delete mode 120000 crypto_sign/haetae5/ref/sign.h delete mode 120000 crypto_sign/haetae5/ref/symmetric-shake.c delete mode 120000 crypto_sign/haetae5/ref/symmetric.h diff --git a/crypto_sign/haetae2/ref/api.h b/crypto_sign/haetae2/ref/api.h deleted file mode 100644 index 28d58fca..00000000 --- a/crypto_sign/haetae2/ref/api.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef API_H -#define API_H - -#include "sign.h" - -#endif diff --git a/crypto_sign/haetae2/ref/config.h b/crypto_sign/haetae2/ref/config.h deleted file mode 100644 index 2461ffa5..00000000 --- a/crypto_sign/haetae2/ref/config.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define HAETAE_MODE 2 - -#if HAETAE_MODE == 2 -#define CRYPTO_ALGNAME "HAETAE2" -#define HAETAE_NAMESPACETOP haetae2 -#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s -#elif HAETAE_MODE == 3 -#define CRYPTO_ALGNAME "HAETAE3" -#define HAETAE_NAMESPACETOP haetae3 -#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s -#elif HAETAE_MODE == 5 -#define CRYPTO_ALGNAME "HAETAE5" -#define HAETAE_NAMESPACETOP haetae5 -#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s -#endif /* if HAETAE_MODE */ - -#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae2/ref/decompose.c b/crypto_sign/haetae2/ref/decompose.c deleted file mode 100644 index 467767e5..00000000 --- a/crypto_sign/haetae2/ref/decompose.c +++ /dev/null @@ -1,69 +0,0 @@ -#include "decompose.h" -#include "params.h" -#include - -/************************************************* - * Name: decompose_z1 - * - * Description: For finite field element r, compute high and lowbits - * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. - * - * Arguments: - int32_t r: input element - * - int32_t *lowbits: pointer to output element lb - * - int32_t *highbits: pointer to output element hb - **************************************************/ -void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r) { - const int alpha = 256; // TODO magic numbers! - const int log_alpha = 8; - - int32_t lb, center; - uint32_t alpha_mask = alpha - 1; - - lb = r & alpha_mask; - center = ((alpha >> 1) - (lb + 1)) >> 31; // if lb >= HALF_ALPHA - lb -= alpha & center; - *lowbits = lb; - *highbits = (r + (alpha >> 1)) >> log_alpha; -} - -/************************************************* - * Name: decompose_hint - * - * Description: For finite field element r, compute highbits - * hb, lb such that r = hb * b + lb with -b/4 < lb <= b/4. - * - * Arguments: - int32_t r: input element - * - int32_t *highbits: pointer to output element hb - **************************************************/ - -void decompose_hint(int32_t *highbits, const int32_t r) { - int32_t hb, edgecase; - - hb = (r + HALF_ALPHA_HINT) >> LOG_ALPHA_HINT; - edgecase = - ((DQ - 2) / ALPHA_HINT - (hb + 1)) >> 31; // if hb == (DQ-2)/ALPHA - hb -= (DQ - 2) / ALPHA_HINT & edgecase; // hb = 0 - - *highbits = hb; -} - -/************************************************* - * Name: decompose_vk - * - * Description: For finite field element a, compute a0, a1 such that - * a mod^+ Q = a1*2^D + a0 with -2^{D-1} <= a0 < 2^{D-1}. - * Assumes a to be standard representative. - * - * Arguments: - int32_t a: input element - * - int32_t *a0: pointer to output element a0 - * - * Returns a1 - **************************************************/ -int32_t decompose_vk(int32_t *a0, const int32_t a) { -#if D > 1 -#error "Only implemented for D = 1" -#endif - *a0 = a & 1; - *a0 -= ((a >> 1) & *a0) << 1; - return (a - *a0) >> 1; -} diff --git a/crypto_sign/haetae2/ref/decompose.h b/crypto_sign/haetae2/ref/decompose.h deleted file mode 100644 index 67146cf1..00000000 --- a/crypto_sign/haetae2/ref/decompose.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef HAETAE_ROUNDING_H -#define HAETAE_ROUNDING_H - -#include "params.h" -#include - -#define decompose_z1 HAETAE_NAMESPACE(decompose_z1) -void decompose_z1(int32_t *highbits, int32_t *lowbits, const int32_t r); - -#define decompose_hint HAETAE_NAMESPACE(decompose_hint) -void decompose_hint(int32_t *highbits, const int32_t r); - -#define decompose_vk HAETAE_NAMESPACE(decompose_vk) -int32_t decompose_vk(int32_t *a0, const int32_t a); - -#endif diff --git a/crypto_sign/haetae2/ref/encoding.c b/crypto_sign/haetae2/ref/encoding.c deleted file mode 100644 index ca6a182f..00000000 --- a/crypto_sign/haetae2/ref/encoding.c +++ /dev/null @@ -1,227 +0,0 @@ -#include "encoding.h" -#include "params.h" -#include "rans_byte.h" - -#include -#include -#include - -#define SCALE_BITS 10 -#define SCALE (1u << SCALE_BITS) - -#if HAETAE_MODE == 2 -#define M_H 13 -#define OFFSET_H 239 -#define M_HB_Z1 13 -#define OFFSET_HB_Z1 6 -static RansEncSymbol esyms_h[M_H] = {{801112064, -1416664605, 0, 642, 8}, {515899392, -2060187564, 382, 778, 7}, {136314880, -66076419, 628, 959, 6}, {14680064, -1840700269, 693, 1017, 2}, {2097152, -1, 1723, 1023, 0}, {2097152, -1, 1724, 1023, 0}, {2097152, -1, 1725, 1023, 0}, {2097152, -1, 1726, 1023, 0}, {2097152, -1, 1727, 1023, 0}, {2097152, -1, 1728, 1023, 0}, {14680064, -1840700269, 706, 1017, 2}, {136314880, -66076419, 713, 959, 6}, {515899392, -2060187564, 778, 778, 7}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 382}, {382, 246}, {628, 65}, {693, 7}, {700, 1}, {701, 1}, {702, 1}, {703, 1}, {704, 1}, {705, 1}, {706, 7}, {713, 65}, {778, 246}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {10485760, -858993459, 3, 1019, 2}, {121634816, -1925330167, 8, 966, 5}, {515899392, -2060187564, 66, 778, 7}, {834666496, -1532375266, 312, 626, 8}, {517996544, -2069235255, 710, 777, 7}, {123731968, -1965493508, 957, 965, 5}, {10485760, -858993459, 1016, 1019, 2}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 5}, {8, 58}, {66, 246}, {312, 398}, {710, 247}, {957, 59}, {1016, 5}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 11, 12, }; - -#elif HAETAE_MODE == 3 -#define M_H 17 -#define OFFSET_H 235 -#define M_HB_Z1 17 -#define OFFSET_HB_Z1 8 -static RansEncSymbol esyms_h[M_H] = {{557842432, -161464935, 0, 758, 8}, {446693376, -1713954085, 266, 811, 7}, {236978176, -1862419446, 479, 911, 6}, {83886080, -858993459, 592, 984, 5}, {18874368, -477218588, 632, 1015, 3}, {2097152, -1, 1664, 1023, 0}, {2097152, -1, 1665, 1023, 0}, {2097152, -1, 1666, 1023, 0}, {2097152, -1, 1667, 1023, 0}, {2097152, -1, 1668, 1023, 0}, {2097152, -1, 1669, 1023, 0}, {2097152, -1, 1670, 1023, 0}, {2097152, -1, 1671, 1023, 0}, {18874368, -477218588, 649, 1015, 3}, {83886080, -858993459, 658, 984, 5}, {236978176, -1862419446, 698, 911, 6}, {446693376, -1713954085, 811, 811, 7}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 266}, {266, 213}, {479, 113}, {592, 40}, {632, 9}, {641, 1}, {642, 1}, {643, 1}, {644, 1}, {645, 1}, {646, 1}, {647, 1}, {648, 1}, {649, 9}, {658, 40}, {698, 113}, {811, 213}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {16777216, -2147483648, 4, 1016, 2}, {77594624, -580400985, 12, 987, 5}, {234881024, -1840700269, 49, 912, 6}, {452984832, -1749801490, 161, 808, 7}, {564133888, -207563475, 377, 755, 8}, {452984832, -1749801490, 646, 808, 7}, {234881024, -1840700269, 862, 912, 6}, {79691776, -678152730, 974, 986, 5}, {16777216, -2147483648, 1012, 1016, 2}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 8}, {12, 37}, {49, 112}, {161, 216}, {377, 269}, {646, 216}, {862, 112}, {974, 38}, {1012, 8}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 14, 15, 16, }; - -#elif HAETAE_MODE == 5 -#define M_H 33 -#define OFFSET_H 471 -#define M_HB_Z1 19 -#define OFFSET_HB_Z1 9 -static RansEncSymbol esyms_h[M_H] = {{255852544, -2041869698, 0, 902, 6}, {245366784, -1945583475, 122, 907, 6}, {213909504, -1600085855, 239, 922, 6}, {169869312, -901412889, 341, 943, 6}, {123731968, -1965493508, 422, 965, 5}, {81788928, -770891565, 481, 985, 5}, {48234496, -1307163959, 520, 1001, 4}, {27262976, -1651910498, 543, 1011, 3}, {12582912, -1431655765, 556, 1018, 2}, {6291456, -1431655765, 562, 1021, 1}, {2097152, -1, 1588, 1023, 0}, {2097152, -1, 1589, 1023, 0}, {2097152, -1, 1590, 1023, 0}, {2097152, -1, 1591, 1023, 0}, {2097152, -1, 1592, 1023, 0}, {2097152, -1, 1593, 1023, 0}, {2097152, -1, 1594, 1023, 0}, {2097152, -1, 1595, 1023, 0}, {2097152, -1, 1596, 1023, 0}, {2097152, -1, 1597, 1023, 0}, {2097152, -1, 1598, 1023, 0}, {2097152, -1, 1599, 1023, 0}, {2097152, -1, 1600, 1023, 0}, {2097152, -1, 1601, 1023, 0}, {6291456, -1431655765, 579, 1021, 1}, {12582912, -1431655765, 582, 1018, 2}, {27262976, -1651910498, 588, 1011, 3}, {50331648, -1431655765, 601, 1000, 4}, {81788928, -770891565, 625, 985, 5}, {123731968, -1965493508, 664, 965, 5}, {169869312, -901412889, 723, 943, 6}, {213909504, -1600085855, 804, 922, 6}, {247463936, -1965493508, 906, 906, 6}, }; -static RansDecSymbol dsyms_h[M_H] = {{0, 122}, {122, 117}, {239, 102}, {341, 81}, {422, 59}, {481, 39}, {520, 23}, {543, 13}, {556, 6}, {562, 3}, {565, 1}, {566, 1}, {567, 1}, {568, 1}, {569, 1}, {570, 1}, {571, 1}, {572, 1}, {573, 1}, {574, 1}, {575, 1}, {576, 1}, {577, 1}, {578, 1}, {579, 3}, {582, 6}, {588, 13}, {601, 24}, {625, 39}, {664, 59}, {723, 81}, {804, 102}, {906, 118}, }; -static uint16_t symbol_h[SCALE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, }; -static RansEncSymbol esyms_hb_z1[M_HB_Z1] = {{2097152, -1, 1023, 1023, 0}, {2097152, -1, 1024, 1023, 0}, {2097152, -1, 1025, 1023, 0}, {2097152, -1, 1026, 1023, 0}, {4194304, -2147483648, 4, 1022, 0}, {27262976, -1651910498, 6, 1011, 3}, {100663296, -1431655765, 19, 976, 5}, {247463936, -1965493508, 67, 906, 6}, {427819008, -1600085855, 185, 820, 7}, {513802240, -2051066014, 389, 779, 7}, {427819008, -1600085855, 634, 820, 7}, {247463936, -1965493508, 838, 906, 6}, {100663296, -1431655765, 956, 976, 5}, {29360128, -1840700269, 1004, 1010, 3}, {4194304, -2147483648, 1018, 1022, 0}, {2097152, -1, 2043, 1023, 0}, {2097152, -1, 2044, 1023, 0}, {2097152, -1, 2045, 1023, 0}, {2097152, -1, 2046, 1023, 0}, }; -static RansDecSymbol dsyms_hb_z1[M_HB_Z1] = {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 2}, {6, 13}, {19, 48}, {67, 118}, {185, 204}, {389, 245}, {634, 204}, {838, 118}, {956, 48}, {1004, 14}, {1018, 2}, {1020, 1}, {1021, 1}, {1022, 1}, {1023, 1}, }; -static uint16_t symbol_hb_z1[SCALE] = {0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 15, 16, 17, 18, }; - -#endif // HAETAE_MODE -#define H_CUT ((M_H -1) >>1) - -/************************************************* - * Name: encode_h - * - * Description: rANS encode polynomial vector h - * - * Arguments: - uint8_t *buf: pointer to output buffer - * - const int32_t *h: pointer to polynomial vector h - **************************************************/ -uint16_t encode_h(uint8_t *buf, const int32_t *h) { - size_t size_encoded; - RansState rans; - uint8_t *ptr; - size_t size_h = N * K; - uint32_t tmp; - uint8_t s; - uint8_t encoding[size_h]; // size_h is a loose upper bound - - RansEncInit(&rans); - ptr = encoding + size_h; // end of encoding buffer - - for (size_t i = size_h; i > 0; i--) { - tmp = h[i - 1]; - // check for very unlikely values that we do not encode - // to make the encoding cheaper : - if(H_CUT < tmp && tmp <= H_CUT + OFFSET_H) { - return 0; - } - // map the upper likely part of symbols next to the lower part - // to have a dense and compact distribution: - tmp = (tmp > (H_CUT + OFFSET_H)) ? tmp - OFFSET_H : tmp; - s = (uint8_t) tmp; - - RansEncPutSymbol(&rans, &ptr, &esyms_h[s]); - // check that at least 4 byte remain for memory safety: - if (ptr < encoding + 4) - { - return 0; - } - } - - RansEncFlush(&rans, &ptr); - - size_encoded = encoding + size_h - ptr; - memcpy(buf, ptr, size_encoded); - return size_encoded; -} - -/************************************************* - * Name: decode_h - * - * Description: rANS decode polynomial vector h - * - * Arguments: - int32_t *h: pointer to polynomial vector h - * - uint8_t *buf: pointer to output buffer - **************************************************/ -uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in) { - size_t size_used; - RansState rans; - size_t size_h = N * K; - uint32_t tmp; - uint8_t s; - const uint8_t *buf_start = buf; - const uint8_t *buf_end = buf + size_in; - - if(RansDecInit(&rans, (uint8_t **) &buf)) { - return 1; // corrupted initial state - } - - for (size_t i = 0; i < size_h; i++) { - s = symbol_h[RansDecGet(&rans, SCALE_BITS)]; - tmp = (uint32_t) s; - if(tmp >= M_H) { - return 1; // invalid symbol - } - tmp = (H_CUT < tmp) ? (tmp + OFFSET_H) : tmp; - h[i] = tmp; - RansDecAdvanceSymbol(&rans, (uint8_t **) &buf, buf_end, &dsyms_h[s], SCALE_BITS); - } - - if(RansDecVerify(&rans)) { - return 1; // final state not correct - } - - size_used = buf - buf_start; - if(size_used != size_in) { - return 1; // size does not match - } - return 0; -} - -/************************************************* - * Name: encode_hb_z1 - * - * Description: rANS encode polynomial vector HighBits(z1) - * - * Arguments: - uint8_t *buf: pointer to output buffer - * - const int32_t *hb_z1: pointer to polynomial vector - *HighBits(z1) - **************************************************/ -uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1) { - size_t size_encoded; - RansState rans; - uint8_t *ptr; - size_t size_hb_z1 = N * L; - int8_t s; - int32_t tmp; - uint8_t encoding[size_hb_z1]; // size_hb_z1 is a loose upper bound - - RansEncInit(&rans); - ptr = encoding + size_hb_z1; // end of output buffer - - for (size_t i = size_hb_z1; i > 0; i--) { - // from centered to positive representation: - tmp = hb_z1[i - 1] + OFFSET_HB_Z1; - // check for very unlikely values that we do not encode - // to make the encoding cheaper : - if(tmp < 0 || M_HB_Z1 <= tmp) { - return 0; - } - s = (uint8_t) tmp; - - RansEncPutSymbol(&rans, &ptr, &esyms_hb_z1[s]); - // check that at least 4 byte remain for memory safety: - if (ptr < encoding + 4) - { - return 0; - } - } - RansEncFlush(&rans, &ptr); - - size_encoded = encoding + size_hb_z1 - ptr; - memcpy(buf, ptr, size_encoded); - return size_encoded; -} - -/************************************************* - * Name: decode_hb_z1 - * - * Description: rANS decode polynomial vector HighBits(z1) - * - * Arguments: - int32_t *hb_z1: pointer to polynomial vector HighBits(z1) - * - uint8_t *buf: pointer to output buffer - **************************************************/ -uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in) { - size_t size_used; - RansState rans; - size_t size_hb_z1 = N * L; - uint32_t tmp; - uint8_t s; - const uint8_t *buf_start = buf; - const uint8_t *buf_end = buf + size_in; - - if(RansDecInit(&rans, (uint8_t **) &buf)) { - return 1; // corrupted initial state - } - - for (size_t i = 0; i < size_hb_z1; i++) { - s = symbol_hb_z1[RansDecGet(&rans, SCALE_BITS)]; - tmp = (uint32_t) s; - if(tmp >= M_HB_Z1) { - return 1; // invalid symbol - } - // from positive to centered representation: - hb_z1[i] = tmp - OFFSET_HB_Z1; - RansDecAdvanceSymbol(&rans, (uint8_t **)&buf, buf_end, &dsyms_hb_z1[s], SCALE_BITS); - } - - if(RansDecVerify(&rans)) { - return 1; // final state not correct - } - - size_used = buf - buf_start; - if(size_used != size_in) { - return 1; // size does not match - } - return 0; -} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/encoding.h b/crypto_sign/haetae2/ref/encoding.h deleted file mode 100644 index b1e6239d..00000000 --- a/crypto_sign/haetae2/ref/encoding.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HAETAE_ENCODING_H -#define HAETAE_ENCODING_H - -#include "params.h" -#include -#include - -#define encode_h HAETAE_NAMESPACE(encode_h) -uint16_t encode_h(uint8_t *buf, const int32_t *h); -#define decode_h HAETAE_NAMESPACE(decode_h) -uint16_t decode_h(int32_t *h, const uint8_t *buf, uint16_t size_in); -#define encode_hb_z1 HAETAE_NAMESPACE(encode_hb_z1) -uint16_t encode_hb_z1(uint8_t *buf, const int32_t *hb_z1); -#define decode_hb_z1 HAETAE_NAMESPACE(decode_hb_z1) -uint16_t decode_hb_z1(int32_t *hb_z1, const uint8_t *buf, uint16_t size_in); - -#endif // HAETAE_ENCODING_H diff --git a/crypto_sign/haetae2/ref/fft.c b/crypto_sign/haetae2/ref/fft.c deleted file mode 100644 index f625ad79..00000000 --- a/crypto_sign/haetae2/ref/fft.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "fft.h" - -static const complex_fp32_16 roots[] = { - {.real = +65536L, .imag = +0L}, {.real = +65531L, .imag = -804L}, - {.real = +65516L, .imag = -1608L}, {.real = +65492L, .imag = -2412L}, - {.real = +65457L, .imag = -3216L}, {.real = +65413L, .imag = -4019L}, - {.real = +65358L, .imag = -4821L}, {.real = +65294L, .imag = -5623L}, - {.real = +65220L, .imag = -6424L}, {.real = +65137L, .imag = -7224L}, - {.real = +65043L, .imag = -8022L}, {.real = +64940L, .imag = -8820L}, - {.real = +64827L, .imag = -9616L}, {.real = +64704L, .imag = -10411L}, - {.real = +64571L, .imag = -11204L}, {.real = +64429L, .imag = -11996L}, - {.real = +64277L, .imag = -12785L}, {.real = +64115L, .imag = -13573L}, - {.real = +63944L, .imag = -14359L}, {.real = +63763L, .imag = -15143L}, - {.real = +63572L, .imag = -15924L}, {.real = +63372L, .imag = -16703L}, - {.real = +63162L, .imag = -17479L}, {.real = +62943L, .imag = -18253L}, - {.real = +62714L, .imag = -19024L}, {.real = +62476L, .imag = -19792L}, - {.real = +62228L, .imag = -20557L}, {.real = +61971L, .imag = -21320L}, - {.real = +61705L, .imag = -22078L}, {.real = +61429L, .imag = -22834L}, - {.real = +61145L, .imag = -23586L}, {.real = +60851L, .imag = -24335L}, - {.real = +60547L, .imag = -25080L}, {.real = +60235L, .imag = -25821L}, - {.real = +59914L, .imag = -26558L}, {.real = +59583L, .imag = -27291L}, - {.real = +59244L, .imag = -28020L}, {.real = +58896L, .imag = -28745L}, - {.real = +58538L, .imag = -29466L}, {.real = +58172L, .imag = -30182L}, - {.real = +57798L, .imag = -30893L}, {.real = +57414L, .imag = -31600L}, - {.real = +57022L, .imag = -32303L}, {.real = +56621L, .imag = -33000L}, - {.real = +56212L, .imag = -33692L}, {.real = +55794L, .imag = -34380L}, - {.real = +55368L, .imag = -35062L}, {.real = +54934L, .imag = -35738L}, - {.real = +54491L, .imag = -36410L}, {.real = +54040L, .imag = -37076L}, - {.real = +53581L, .imag = -37736L}, {.real = +53114L, .imag = -38391L}, - {.real = +52639L, .imag = -39040L}, {.real = +52156L, .imag = -39683L}, - {.real = +51665L, .imag = -40320L}, {.real = +51166L, .imag = -40951L}, - {.real = +50660L, .imag = -41576L}, {.real = +50146L, .imag = -42194L}, - {.real = +49624L, .imag = -42806L}, {.real = +49095L, .imag = -43412L}, - {.real = +48559L, .imag = -44011L}, {.real = +48015L, .imag = -44604L}, - {.real = +47464L, .imag = -45190L}, {.real = +46906L, .imag = -45769L}, - {.real = +46341L, .imag = -46341L}, {.real = +45769L, .imag = -46906L}, - {.real = +45190L, .imag = -47464L}, {.real = +44604L, .imag = -48015L}, - {.real = +44011L, .imag = -48559L}, {.real = +43412L, .imag = -49095L}, - {.real = +42806L, .imag = -49624L}, {.real = +42194L, .imag = -50146L}, - {.real = +41576L, .imag = -50660L}, {.real = +40951L, .imag = -51166L}, - {.real = +40320L, .imag = -51665L}, {.real = +39683L, .imag = -52156L}, - {.real = +39040L, .imag = -52639L}, {.real = +38391L, .imag = -53114L}, - {.real = +37736L, .imag = -53581L}, {.real = +37076L, .imag = -54040L}, - {.real = +36410L, .imag = -54491L}, {.real = +35738L, .imag = -54934L}, - {.real = +35062L, .imag = -55368L}, {.real = +34380L, .imag = -55794L}, - {.real = +33692L, .imag = -56212L}, {.real = +33000L, .imag = -56621L}, - {.real = +32303L, .imag = -57022L}, {.real = +31600L, .imag = -57414L}, - {.real = +30893L, .imag = -57798L}, {.real = +30182L, .imag = -58172L}, - {.real = +29466L, .imag = -58538L}, {.real = +28745L, .imag = -58896L}, - {.real = +28020L, .imag = -59244L}, {.real = +27291L, .imag = -59583L}, - {.real = +26558L, .imag = -59914L}, {.real = +25821L, .imag = -60235L}, - {.real = +25080L, .imag = -60547L}, {.real = +24335L, .imag = -60851L}, - {.real = +23586L, .imag = -61145L}, {.real = +22834L, .imag = -61429L}, - {.real = +22078L, .imag = -61705L}, {.real = +21320L, .imag = -61971L}, - {.real = +20557L, .imag = -62228L}, {.real = +19792L, .imag = -62476L}, - {.real = +19024L, .imag = -62714L}, {.real = +18253L, .imag = -62943L}, - {.real = +17479L, .imag = -63162L}, {.real = +16703L, .imag = -63372L}, - {.real = +15924L, .imag = -63572L}, {.real = +15143L, .imag = -63763L}, - {.real = +14359L, .imag = -63944L}, {.real = +13573L, .imag = -64115L}, - {.real = +12785L, .imag = -64277L}, {.real = +11996L, .imag = -64429L}, - {.real = +11204L, .imag = -64571L}, {.real = +10411L, .imag = -64704L}, - {.real = +9616L, .imag = -64827L}, {.real = +8820L, .imag = -64940L}, - {.real = +8022L, .imag = -65043L}, {.real = +7224L, .imag = -65137L}, - {.real = +6424L, .imag = -65220L}, {.real = +5623L, .imag = -65294L}, - {.real = +4821L, .imag = -65358L}, {.real = +4019L, .imag = -65413L}, - {.real = +3216L, .imag = -65457L}, {.real = +2412L, .imag = -65492L}, - {.real = +1608L, .imag = -65516L}, {.real = +804L, .imag = -65531L}, - {.real = +0L, .imag = -65536L}, {.real = -804L, .imag = -65531L}, - {.real = -1608L, .imag = -65516L}, {.real = -2412L, .imag = -65492L}, - {.real = -3216L, .imag = -65457L}, {.real = -4019L, .imag = -65413L}, - {.real = -4821L, .imag = -65358L}, {.real = -5623L, .imag = -65294L}, - {.real = -6424L, .imag = -65220L}, {.real = -7224L, .imag = -65137L}, - {.real = -8022L, .imag = -65043L}, {.real = -8820L, .imag = -64940L}, - {.real = -9616L, .imag = -64827L}, {.real = -10411L, .imag = -64704L}, - {.real = -11204L, .imag = -64571L}, {.real = -11996L, .imag = -64429L}, - {.real = -12785L, .imag = -64277L}, {.real = -13573L, .imag = -64115L}, - {.real = -14359L, .imag = -63944L}, {.real = -15143L, .imag = -63763L}, - {.real = -15924L, .imag = -63572L}, {.real = -16703L, .imag = -63372L}, - {.real = -17479L, .imag = -63162L}, {.real = -18253L, .imag = -62943L}, - {.real = -19024L, .imag = -62714L}, {.real = -19792L, .imag = -62476L}, - {.real = -20557L, .imag = -62228L}, {.real = -21320L, .imag = -61971L}, - {.real = -22078L, .imag = -61705L}, {.real = -22834L, .imag = -61429L}, - {.real = -23586L, .imag = -61145L}, {.real = -24335L, .imag = -60851L}, - {.real = -25080L, .imag = -60547L}, {.real = -25821L, .imag = -60235L}, - {.real = -26558L, .imag = -59914L}, {.real = -27291L, .imag = -59583L}, - {.real = -28020L, .imag = -59244L}, {.real = -28745L, .imag = -58896L}, - {.real = -29466L, .imag = -58538L}, {.real = -30182L, .imag = -58172L}, - {.real = -30893L, .imag = -57798L}, {.real = -31600L, .imag = -57414L}, - {.real = -32303L, .imag = -57022L}, {.real = -33000L, .imag = -56621L}, - {.real = -33692L, .imag = -56212L}, {.real = -34380L, .imag = -55794L}, - {.real = -35062L, .imag = -55368L}, {.real = -35738L, .imag = -54934L}, - {.real = -36410L, .imag = -54491L}, {.real = -37076L, .imag = -54040L}, - {.real = -37736L, .imag = -53581L}, {.real = -38391L, .imag = -53114L}, - {.real = -39040L, .imag = -52639L}, {.real = -39683L, .imag = -52156L}, - {.real = -40320L, .imag = -51665L}, {.real = -40951L, .imag = -51166L}, - {.real = -41576L, .imag = -50660L}, {.real = -42194L, .imag = -50146L}, - {.real = -42806L, .imag = -49624L}, {.real = -43412L, .imag = -49095L}, - {.real = -44011L, .imag = -48559L}, {.real = -44604L, .imag = -48015L}, - {.real = -45190L, .imag = -47464L}, {.real = -45769L, .imag = -46906L}, - {.real = -46341L, .imag = -46341L}, {.real = -46906L, .imag = -45769L}, - {.real = -47464L, .imag = -45190L}, {.real = -48015L, .imag = -44604L}, - {.real = -48559L, .imag = -44011L}, {.real = -49095L, .imag = -43412L}, - {.real = -49624L, .imag = -42806L}, {.real = -50146L, .imag = -42194L}, - {.real = -50660L, .imag = -41576L}, {.real = -51166L, .imag = -40951L}, - {.real = -51665L, .imag = -40320L}, {.real = -52156L, .imag = -39683L}, - {.real = -52639L, .imag = -39040L}, {.real = -53114L, .imag = -38391L}, - {.real = -53581L, .imag = -37736L}, {.real = -54040L, .imag = -37076L}, - {.real = -54491L, .imag = -36410L}, {.real = -54934L, .imag = -35738L}, - {.real = -55368L, .imag = -35062L}, {.real = -55794L, .imag = -34380L}, - {.real = -56212L, .imag = -33692L}, {.real = -56621L, .imag = -33000L}, - {.real = -57022L, .imag = -32303L}, {.real = -57414L, .imag = -31600L}, - {.real = -57798L, .imag = -30893L}, {.real = -58172L, .imag = -30182L}, - {.real = -58538L, .imag = -29466L}, {.real = -58896L, .imag = -28745L}, - {.real = -59244L, .imag = -28020L}, {.real = -59583L, .imag = -27291L}, - {.real = -59914L, .imag = -26558L}, {.real = -60235L, .imag = -25821L}, - {.real = -60547L, .imag = -25080L}, {.real = -60851L, .imag = -24335L}, - {.real = -61145L, .imag = -23586L}, {.real = -61429L, .imag = -22834L}, - {.real = -61705L, .imag = -22078L}, {.real = -61971L, .imag = -21320L}, - {.real = -62228L, .imag = -20557L}, {.real = -62476L, .imag = -19792L}, - {.real = -62714L, .imag = -19024L}, {.real = -62943L, .imag = -18253L}, - {.real = -63162L, .imag = -17479L}, {.real = -63372L, .imag = -16703L}, - {.real = -63572L, .imag = -15924L}, {.real = -63763L, .imag = -15143L}, - {.real = -63944L, .imag = -14359L}, {.real = -64115L, .imag = -13573L}, - {.real = -64277L, .imag = -12785L}, {.real = -64429L, .imag = -11996L}, - {.real = -64571L, .imag = -11204L}, {.real = -64704L, .imag = -10411L}, - {.real = -64827L, .imag = -9616L}, {.real = -64940L, .imag = -8820L}, - {.real = -65043L, .imag = -8022L}, {.real = -65137L, .imag = -7224L}, - {.real = -65220L, .imag = -6424L}, {.real = -65294L, .imag = -5623L}, - {.real = -65358L, .imag = -4821L}, {.real = -65413L, .imag = -4019L}, - {.real = -65457L, .imag = -3216L}, {.real = -65492L, .imag = -2412L}, - {.real = -65516L, .imag = -1608L}, {.real = -65531L, .imag = -804L}}; - -static inline int32_t _mulrnd16(const int32_t x, const int32_t y) { - int64_t r = ((int64_t)x * (int64_t)y) + (1 << 15); - return r >> 16; -} - -static inline int32_t _complex_mul_real(const complex_fp32_16 x, - const complex_fp32_16 y) { - return _mulrnd16(x.real, y.real) - _mulrnd16(x.imag, y.imag); -} - -static inline int32_t _complex_mul_imag(const complex_fp32_16 x, - const complex_fp32_16 y) { - return _mulrnd16(x.real, y.imag) + _mulrnd16(x.imag, y.real); -} - -static void _complex_mul(complex_fp32_16 *r, const complex_fp32_16 x, - const complex_fp32_16 y) { - r->real = _complex_mul_real(x, y); - r->imag = _complex_mul_imag(x, y); -} - -const uint16_t brv9[] = { - 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, - 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, - 240, 496, 8, 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, - 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, - 120, 376, 248, 504, 4, 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, - 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, - 180, 436, 116, 372, 244, 500, 12, 268, 140, 396, 76, 332, 204, 460, 44, - 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, - 60, 316, 188, 444, 124, 380, 252, 508, 2, 258, 130, 386, 66, 322, 194, - 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, - 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, 266, 138, 394, 74, - 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, - 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, 262, 134, - 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, - 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, - 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, - 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, - 510, 1, 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, - 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, - 369, 241, 497, 9, 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, - 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, - 441, 121, 377, 249, 505, 5, 261, 133, 389, 69, 325, 197, 453, 37, 293, - 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, - 309, 181, 437, 117, 373, 245, 501, 13, 269, 141, 397, 77, 333, 205, 461, - 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, - 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, 259, 131, 387, 67, 323, - 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, - 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, 267, 139, 395, - 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, - 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, 263, - 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, - 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, - 15, 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, - 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, - 255, 511}; - -void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x) { - int i, inv_i; - for (i = 0; i < N; i++) { - inv_i = brv9[i]; - r[inv_i].imag = 0; - r[inv_i].real = x->coeffs[i] << 16; - } - for (i = N; i < FFT_N; i++) { - inv_i = brv9[i]; - r[inv_i].imag = 0; - r[inv_i].real = 0; - } -} - -int32_t complex_fp_sqabs(complex_fp32_16 x) { - return _mulrnd16(x.real, x.real) + _mulrnd16(x.imag, x.imag); -} - -void fft(complex_fp32_16 data[FFT_N]) { - unsigned int r, m, md2, n, k, even, odd, twid; - complex_fp32_16 u, t; - - for (r = 1; r <= FFT_LOGN; r++) { - m = 1 << r; - md2 = m >> 1; - for (n = 0; n < FFT_N; n += m) { - for (k = 0; k < md2; k++) { - even = n + k; - odd = even + md2; - twid = k << (FFT_LOGN - r); - - u = data[even]; - _complex_mul(&t, roots[twid], data[odd]); - data[even].real = u.real + t.real; - data[even].imag = u.imag + t.imag; - data[odd].real = u.real - t.real; - data[odd].imag = u.imag - t.imag; - } - } - } -} diff --git a/crypto_sign/haetae2/ref/fft.h b/crypto_sign/haetae2/ref/fft.h deleted file mode 100644 index 46a365ce..00000000 --- a/crypto_sign/haetae2/ref/fft.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FFT__H -#define FFT__H - -#include "poly.h" -#include - -#define FFT_N 512 -#define FFT_LOGN 9 - -typedef struct { - int32_t real; - int32_t imag; -} complex_fp32_16; - -void fft(complex_fp32_16 data[FFT_N]); -void fft_bitrev(complex_fp32_16 r[FFT_N], const poly *x); -int32_t complex_fp_sqabs(complex_fp32_16 x); - -#endif diff --git a/crypto_sign/haetae2/ref/fips202.c b/crypto_sign/haetae2/ref/fips202.c deleted file mode 100644 index e0ec2668..00000000 --- a/crypto_sign/haetae2/ref/fips202.c +++ /dev/null @@ -1,746 +0,0 @@ -/* Based on the public domain implementation in crypto_hash/keccakc512/simple/ - * from http://bench.cr.yp.to/supercop.html by Ronny Van Keer and the public - * domain "TweetFips202" implementation from https://twitter.com/tweetfips202 by - * Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ - -#include "fips202.h" -#include -#include - -#define NROUNDS 24 -#define ROL(a, offset) ((a << offset) ^ (a >> (64 - offset))) - -/************************************************* - * Name: load64 - * - * Description: Load 8 bytes into uint64_t in little-endian order - * - * Arguments: - const uint8_t *x: pointer to input byte array - * - * Returns the loaded 64-bit unsigned integer - **************************************************/ -static uint64_t load64(const uint8_t x[8]) { - unsigned int i; - uint64_t r = 0; - - for (i = 0; i < 8; ++i) - r |= (uint64_t)x[i] << 8 * i; - - return r; -} - -/************************************************* - * Name: store64 - * - * Description: Store a 64-bit integer to array of 8 bytes in little-endian - *order - * - * Arguments: - uint8_t *x: pointer to the output byte array (allocated) - * - uint64_t u: input 64-bit unsigned integer - **************************************************/ -static void store64(uint8_t x[8], uint64_t u) { - unsigned int i; - - for (i = 0; i < 8; ++i) - x[i] = u >> 8 * i; -} - -/* Keccak round constants */ -const uint64_t KeccakF_RoundConstants[NROUNDS] = { - (uint64_t)0x0000000000000001ULL, (uint64_t)0x0000000000008082ULL, - (uint64_t)0x800000000000808aULL, (uint64_t)0x8000000080008000ULL, - (uint64_t)0x000000000000808bULL, (uint64_t)0x0000000080000001ULL, - (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008009ULL, - (uint64_t)0x000000000000008aULL, (uint64_t)0x0000000000000088ULL, - (uint64_t)0x0000000080008009ULL, (uint64_t)0x000000008000000aULL, - (uint64_t)0x000000008000808bULL, (uint64_t)0x800000000000008bULL, - (uint64_t)0x8000000000008089ULL, (uint64_t)0x8000000000008003ULL, - (uint64_t)0x8000000000008002ULL, (uint64_t)0x8000000000000080ULL, - (uint64_t)0x000000000000800aULL, (uint64_t)0x800000008000000aULL, - (uint64_t)0x8000000080008081ULL, (uint64_t)0x8000000000008080ULL, - (uint64_t)0x0000000080000001ULL, (uint64_t)0x8000000080008008ULL}; - -/************************************************* - * Name: KeccakF1600_StatePermute - * - * Description: The Keccak F1600 Permutation - * - * Arguments: - uint64_t *state: pointer to input/output Keccak state - **************************************************/ -static void KeccakF1600_StatePermute(uint64_t state[25]) { - int round; - - uint64_t Aba, Abe, Abi, Abo, Abu; - uint64_t Aga, Age, Agi, Ago, Agu; - uint64_t Aka, Ake, Aki, Ako, Aku; - uint64_t Ama, Ame, Ami, Amo, Amu; - uint64_t Asa, Ase, Asi, Aso, Asu; - uint64_t BCa, BCe, BCi, BCo, BCu; - uint64_t Da, De, Di, Do, Du; - uint64_t Eba, Ebe, Ebi, Ebo, Ebu; - uint64_t Ega, Ege, Egi, Ego, Egu; - uint64_t Eka, Eke, Eki, Eko, Eku; - uint64_t Ema, Eme, Emi, Emo, Emu; - uint64_t Esa, Ese, Esi, Eso, Esu; - - // copyFromState(A, state) - Aba = state[0]; - Abe = state[1]; - Abi = state[2]; - Abo = state[3]; - Abu = state[4]; - Aga = state[5]; - Age = state[6]; - Agi = state[7]; - Ago = state[8]; - Agu = state[9]; - Aka = state[10]; - Ake = state[11]; - Aki = state[12]; - Ako = state[13]; - Aku = state[14]; - Ama = state[15]; - Ame = state[16]; - Ami = state[17]; - Amo = state[18]; - Amu = state[19]; - Asa = state[20]; - Ase = state[21]; - Asi = state[22]; - Aso = state[23]; - Asu = state[24]; - - for (round = 0; round < NROUNDS; round += 2) { - // prepareTheta - BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; - BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; - BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; - BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; - BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; - - // thetaRhoPiChiIotaPrepareTheta(round, A, E) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Aba ^= Da; - BCa = Aba; - Age ^= De; - BCe = ROL(Age, 44); - Aki ^= Di; - BCi = ROL(Aki, 43); - Amo ^= Do; - BCo = ROL(Amo, 21); - Asu ^= Du; - BCu = ROL(Asu, 14); - Eba = BCa ^ ((~BCe) & BCi); - Eba ^= (uint64_t)KeccakF_RoundConstants[round]; - Ebe = BCe ^ ((~BCi) & BCo); - Ebi = BCi ^ ((~BCo) & BCu); - Ebo = BCo ^ ((~BCu) & BCa); - Ebu = BCu ^ ((~BCa) & BCe); - - Abo ^= Do; - BCa = ROL(Abo, 28); - Agu ^= Du; - BCe = ROL(Agu, 20); - Aka ^= Da; - BCi = ROL(Aka, 3); - Ame ^= De; - BCo = ROL(Ame, 45); - Asi ^= Di; - BCu = ROL(Asi, 61); - Ega = BCa ^ ((~BCe) & BCi); - Ege = BCe ^ ((~BCi) & BCo); - Egi = BCi ^ ((~BCo) & BCu); - Ego = BCo ^ ((~BCu) & BCa); - Egu = BCu ^ ((~BCa) & BCe); - - Abe ^= De; - BCa = ROL(Abe, 1); - Agi ^= Di; - BCe = ROL(Agi, 6); - Ako ^= Do; - BCi = ROL(Ako, 25); - Amu ^= Du; - BCo = ROL(Amu, 8); - Asa ^= Da; - BCu = ROL(Asa, 18); - Eka = BCa ^ ((~BCe) & BCi); - Eke = BCe ^ ((~BCi) & BCo); - Eki = BCi ^ ((~BCo) & BCu); - Eko = BCo ^ ((~BCu) & BCa); - Eku = BCu ^ ((~BCa) & BCe); - - Abu ^= Du; - BCa = ROL(Abu, 27); - Aga ^= Da; - BCe = ROL(Aga, 36); - Ake ^= De; - BCi = ROL(Ake, 10); - Ami ^= Di; - BCo = ROL(Ami, 15); - Aso ^= Do; - BCu = ROL(Aso, 56); - Ema = BCa ^ ((~BCe) & BCi); - Eme = BCe ^ ((~BCi) & BCo); - Emi = BCi ^ ((~BCo) & BCu); - Emo = BCo ^ ((~BCu) & BCa); - Emu = BCu ^ ((~BCa) & BCe); - - Abi ^= Di; - BCa = ROL(Abi, 62); - Ago ^= Do; - BCe = ROL(Ago, 55); - Aku ^= Du; - BCi = ROL(Aku, 39); - Ama ^= Da; - BCo = ROL(Ama, 41); - Ase ^= De; - BCu = ROL(Ase, 2); - Esa = BCa ^ ((~BCe) & BCi); - Ese = BCe ^ ((~BCi) & BCo); - Esi = BCi ^ ((~BCo) & BCu); - Eso = BCo ^ ((~BCu) & BCa); - Esu = BCu ^ ((~BCa) & BCe); - - // prepareTheta - BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; - BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; - BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; - BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; - BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; - - // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) - Da = BCu ^ ROL(BCe, 1); - De = BCa ^ ROL(BCi, 1); - Di = BCe ^ ROL(BCo, 1); - Do = BCi ^ ROL(BCu, 1); - Du = BCo ^ ROL(BCa, 1); - - Eba ^= Da; - BCa = Eba; - Ege ^= De; - BCe = ROL(Ege, 44); - Eki ^= Di; - BCi = ROL(Eki, 43); - Emo ^= Do; - BCo = ROL(Emo, 21); - Esu ^= Du; - BCu = ROL(Esu, 14); - Aba = BCa ^ ((~BCe) & BCi); - Aba ^= (uint64_t)KeccakF_RoundConstants[round + 1]; - Abe = BCe ^ ((~BCi) & BCo); - Abi = BCi ^ ((~BCo) & BCu); - Abo = BCo ^ ((~BCu) & BCa); - Abu = BCu ^ ((~BCa) & BCe); - - Ebo ^= Do; - BCa = ROL(Ebo, 28); - Egu ^= Du; - BCe = ROL(Egu, 20); - Eka ^= Da; - BCi = ROL(Eka, 3); - Eme ^= De; - BCo = ROL(Eme, 45); - Esi ^= Di; - BCu = ROL(Esi, 61); - Aga = BCa ^ ((~BCe) & BCi); - Age = BCe ^ ((~BCi) & BCo); - Agi = BCi ^ ((~BCo) & BCu); - Ago = BCo ^ ((~BCu) & BCa); - Agu = BCu ^ ((~BCa) & BCe); - - Ebe ^= De; - BCa = ROL(Ebe, 1); - Egi ^= Di; - BCe = ROL(Egi, 6); - Eko ^= Do; - BCi = ROL(Eko, 25); - Emu ^= Du; - BCo = ROL(Emu, 8); - Esa ^= Da; - BCu = ROL(Esa, 18); - Aka = BCa ^ ((~BCe) & BCi); - Ake = BCe ^ ((~BCi) & BCo); - Aki = BCi ^ ((~BCo) & BCu); - Ako = BCo ^ ((~BCu) & BCa); - Aku = BCu ^ ((~BCa) & BCe); - - Ebu ^= Du; - BCa = ROL(Ebu, 27); - Ega ^= Da; - BCe = ROL(Ega, 36); - Eke ^= De; - BCi = ROL(Eke, 10); - Emi ^= Di; - BCo = ROL(Emi, 15); - Eso ^= Do; - BCu = ROL(Eso, 56); - Ama = BCa ^ ((~BCe) & BCi); - Ame = BCe ^ ((~BCi) & BCo); - Ami = BCi ^ ((~BCo) & BCu); - Amo = BCo ^ ((~BCu) & BCa); - Amu = BCu ^ ((~BCa) & BCe); - - Ebi ^= Di; - BCa = ROL(Ebi, 62); - Ego ^= Do; - BCe = ROL(Ego, 55); - Eku ^= Du; - BCi = ROL(Eku, 39); - Ema ^= Da; - BCo = ROL(Ema, 41); - Ese ^= De; - BCu = ROL(Ese, 2); - Asa = BCa ^ ((~BCe) & BCi); - Ase = BCe ^ ((~BCi) & BCo); - Asi = BCi ^ ((~BCo) & BCu); - Aso = BCo ^ ((~BCu) & BCa); - Asu = BCu ^ ((~BCa) & BCe); - } - - // copyToState(state, A) - state[0] = Aba; - state[1] = Abe; - state[2] = Abi; - state[3] = Abo; - state[4] = Abu; - state[5] = Aga; - state[6] = Age; - state[7] = Agi; - state[8] = Ago; - state[9] = Agu; - state[10] = Aka; - state[11] = Ake; - state[12] = Aki; - state[13] = Ako; - state[14] = Aku; - state[15] = Ama; - state[16] = Ame; - state[17] = Ami; - state[18] = Amo; - state[19] = Amu; - state[20] = Asa; - state[21] = Ase; - state[22] = Asi; - state[23] = Aso; - state[24] = Asu; -} - -/************************************************* - * Name: keccak_init - * - * Description: Initializes the Keccak state. - * - * Arguments: - uint64_t *s: pointer to Keccak state - **************************************************/ -static void keccak_init(uint64_t s[25]) { - unsigned int i; - for (i = 0; i < 25; ++i) - s[i] = 0; -} - -/************************************************* - * Name: keccak_absorb - * - * Description: Absorb step of Keccak; incremental. - * - * Arguments: - uint64_t *s: pointer to Keccak state - * - unsigned int pos: position in current block to be absorbed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - * - * Returns new position pos in current block - **************************************************/ -static unsigned int keccak_absorb(uint64_t s[25], unsigned int pos, - unsigned int r, const uint8_t *in, - size_t inlen) { - unsigned int i; - - while (pos + inlen >= r) { - for (i = pos; i < r; ++i) - s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); - inlen -= r - pos; - KeccakF1600_StatePermute(s); - pos = 0; - } - - for (i = pos; i < pos + inlen; ++i) - s[i / 8] ^= (uint64_t)*in++ << 8 * (i % 8); - - return i; -} - -/************************************************* - * Name: keccak_finalize - * - * Description: Finalize absorb step. - * - * Arguments: - uint64_t *s: pointer to Keccak state - * - unsigned int pos: position in current block to be absorbed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - uint8_t p: domain separation byte - **************************************************/ -static void keccak_finalize(uint64_t s[25], unsigned int pos, unsigned int r, - uint8_t p) { - s[pos / 8] ^= (uint64_t)p << 8 * (pos % 8); - s[r / 8 - 1] ^= 1ULL << 63; -} - -/************************************************* - * Name: keccak_squeeze - * - * Description: Squeeze step of Keccak. Squeezes arbitratrily many bytes. - * Modifies the state. Can be called multiple times to keep - * squeezing, i.e., is incremental. - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: number of bytes to be squeezed (written to out) - * - uint64_t *s: pointer to input/output Keccak state - * - unsigned int pos: number of bytes in current block already - *squeezed - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - * Returns new position pos in current block - **************************************************/ -static unsigned int keccak_squeeze(uint8_t *out, size_t outlen, uint64_t s[25], - unsigned int pos, unsigned int r) { - unsigned int i; - - while (outlen) { - if (pos == r) { - KeccakF1600_StatePermute(s); - pos = 0; - } - for (i = pos; i < r && i < pos + outlen; ++i) - *out++ = s[i / 8] >> 8 * (i % 8); - outlen -= i - pos; - pos = i; - } - - return pos; -} - -/************************************************* - * Name: keccak_absorb_once - * - * Description: Absorb step of Keccak; - * non-incremental, starts by zeroeing the state. - * - * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - * - uint8_t p: domain-separation byte for different Keccak-derived - *functions - **************************************************/ -static void keccak_absorb_once(uint64_t s[25], unsigned int r, - const uint8_t *in, size_t inlen, uint8_t p) { - unsigned int i; - - for (i = 0; i < 25; ++i) - s[i] = 0; - - while (inlen >= r) { - for (i = 0; i < r / 8; ++i) - s[i] ^= load64(in + 8 * i); - in += r; - inlen -= r; - KeccakF1600_StatePermute(s); - } - - for (i = 0; i < inlen; ++i) - s[i / 8] ^= (uint64_t)in[i] << 8 * (i % 8); - - s[i / 8] ^= (uint64_t)p << 8 * (i % 8); - s[(r - 1) / 8] ^= 1ULL << 63; -} - -/************************************************* - * Name: keccak_squeezeblocks - * - * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. - * Modifies the state. Can be called multiple times to keep - * squeezing, i.e., is incremental. Assumes zero bytes of current - * block have already been squeezed. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *out) - * - uint64_t *s: pointer to input/output Keccak state - * - unsigned int r: rate in bytes (e.g., 168 for SHAKE128) - **************************************************/ -static void keccak_squeezeblocks(uint8_t *out, size_t nblocks, uint64_t s[25], - unsigned int r) { - unsigned int i; - - while (nblocks) { - KeccakF1600_StatePermute(s); - for (i = 0; i < r / 8; ++i) - store64(out + 8 * i, s[i]); - out += r; - nblocks -= 1; - } -} - -/************************************************* - * Name: shake128_init - * - * Description: Initilizes Keccak state for use as SHAKE128 XOF - * - * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state - **************************************************/ -void shake128_init(keccak_state *state) { - keccak_init(state->s); - state->pos = 0; -} - -/************************************************* - * Name: shake128_absorb - * - * Description: Absorb step of the SHAKE128 XOF; incremental. - * - * Arguments: - keccak_state *state: pointer to (initialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { - state->pos = keccak_absorb(state->s, state->pos, SHAKE128_RATE, in, inlen); -} - -/************************************************* - * Name: shake128_finalize - * - * Description: Finalize absorb step of the SHAKE128 XOF. - * - * Arguments: - keccak_state *state: pointer to Keccak state - **************************************************/ -void shake128_finalize(keccak_state *state) { - keccak_finalize(state->s, state->pos, SHAKE128_RATE, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* - * Name: shake128_squeeze - * - * Description: Squeeze step of SHAKE128 XOF. Squeezes arbitraily many - * bytes. Can be called multiple times to keep squeezing. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t outlen : number of bytes to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { - state->pos = - keccak_squeeze(out, outlen, state->s, state->pos, SHAKE128_RATE); -} - -/************************************************* - * Name: shake128_absorb_once - * - * Description: Initialize, absorb into and finalize SHAKE128 XOF; - *non-incremental. - * - * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128_absorb_once(keccak_state *state, const uint8_t *in, - size_t inlen) { - keccak_absorb_once(state->s, SHAKE128_RATE, in, inlen, 0x1F); - state->pos = SHAKE128_RATE; -} - -/************************************************* - * Name: shake128_squeezeblocks - * - * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of - * SHAKE128_RATE bytes each. Can be called multiple times - * to keep squeezing. Assumes new block has not yet been - * started (state->pos = SHAKE128_RATE). - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { - keccak_squeezeblocks(out, nblocks, state->s, SHAKE128_RATE); -} - -/************************************************* - * Name: shake256_init - * - * Description: Initilizes Keccak state for use as SHAKE256 XOF - * - * Arguments: - keccak_state *state: pointer to (uninitialized) Keccak state - **************************************************/ -void shake256_init(keccak_state *state) { - keccak_init(state->s); - state->pos = 0; -} - -/************************************************* - * Name: shake256_absorb - * - * Description: Absorb step of the SHAKE256 XOF; incremental. - * - * Arguments: - keccak_state *state: pointer to (initialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen) { - state->pos = keccak_absorb(state->s, state->pos, SHAKE256_RATE, in, inlen); -} - -/************************************************* - * Name: shake256_finalize - * - * Description: Finalize absorb step of the SHAKE256 XOF. - * - * Arguments: - keccak_state *state: pointer to Keccak state - **************************************************/ -void shake256_finalize(keccak_state *state) { - keccak_finalize(state->s, state->pos, SHAKE256_RATE, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* - * Name: shake256_squeeze - * - * Description: Squeeze step of SHAKE256 XOF. Squeezes arbitraily many - * bytes. Can be called multiple times to keep squeezing. - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t outlen : number of bytes to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state) { - state->pos = - keccak_squeeze(out, outlen, state->s, state->pos, SHAKE256_RATE); -} - -/************************************************* - * Name: shake256_absorb_once - * - * Description: Initialize, absorb into and finalize SHAKE256 XOF; - *non-incremental. - * - * Arguments: - keccak_state *state: pointer to (uninitialized) output Keccak - *state - * - const uint8_t *in: pointer to input to be absorbed into s - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256_absorb_once(keccak_state *state, const uint8_t *in, - size_t inlen) { - keccak_absorb_once(state->s, SHAKE256_RATE, in, inlen, 0x1F); - state->pos = SHAKE256_RATE; -} - -/************************************************* - * Name: shake256_squeezeblocks - * - * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of - * SHAKE256_RATE bytes each. Can be called multiple times - * to keep squeezing. Assumes next block has not yet been - * started (state->pos = SHAKE256_RATE). - * - * Arguments: - uint8_t *out: pointer to output blocks - * - size_t nblocks: number of blocks to be squeezed (written to - *output) - * - keccak_state *s: pointer to input/output Keccak state - **************************************************/ -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state) { - keccak_squeezeblocks(out, nblocks, state->s, SHAKE256_RATE); -} - -/************************************************* - * Name: shake128 - * - * Description: SHAKE128 XOF with non-incremental API - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: requested output length in bytes - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { - size_t nblocks; - keccak_state state; - - shake128_absorb_once(&state, in, inlen); - nblocks = outlen / SHAKE128_RATE; - shake128_squeezeblocks(out, nblocks, &state); - outlen -= nblocks * SHAKE128_RATE; - out += nblocks * SHAKE128_RATE; - shake128_squeeze(out, outlen, &state); -} - -/************************************************* - * Name: shake256 - * - * Description: SHAKE256 XOF with non-incremental API - * - * Arguments: - uint8_t *out: pointer to output - * - size_t outlen: requested output length in bytes - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { - size_t nblocks; - keccak_state state; - - shake256_absorb_once(&state, in, inlen); - nblocks = outlen / SHAKE256_RATE; - shake256_squeezeblocks(out, nblocks, &state); - outlen -= nblocks * SHAKE256_RATE; - out += nblocks * SHAKE256_RATE; - shake256_squeeze(out, outlen, &state); -} - -/************************************************* - * Name: sha3_256 - * - * Description: SHA3-256 with non-incremental API - * - * Arguments: - uint8_t *h: pointer to output (32 bytes) - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen) { - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_256_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for (i = 0; i < 4; ++i) - store64(h + 8 * i, s[i]); -} - -/************************************************* - * Name: sha3_512 - * - * Description: SHA3-512 with non-incremental API - * - * Arguments: - uint8_t *h: pointer to output (64 bytes) - * - const uint8_t *in: pointer to input - * - size_t inlen: length of input in bytes - **************************************************/ -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen) { - unsigned int i; - uint64_t s[25]; - - keccak_absorb_once(s, SHA3_512_RATE, in, inlen, 0x06); - KeccakF1600_StatePermute(s); - for (i = 0; i < 8; ++i) - store64(h + 8 * i, s[i]); -} diff --git a/crypto_sign/haetae2/ref/fips202.h b/crypto_sign/haetae2/ref/fips202.h deleted file mode 100644 index 58aa8ff2..00000000 --- a/crypto_sign/haetae2/ref/fips202.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FIPS202_H -#define FIPS202_H - -#include -#include - -#define SHAKE128_RATE 168 -#define SHAKE256_RATE 136 -#define SHA3_256_RATE 136 -#define SHA3_512_RATE 72 - -#define FIPS202_NAMESPACE(s) haetae_fips202_##s - -typedef struct { - uint64_t s[25]; - unsigned int pos; -} keccak_state; - -#define KeccakF_RoundConstants FIPS202_NAMESPACE(KeccakF_RoundConstants) -extern const uint64_t KeccakF_RoundConstants[]; - -#define shake128_init FIPS202_NAMESPACE(shake128_init) -void shake128_init(keccak_state *state); -#define shake128_absorb FIPS202_NAMESPACE(shake128_absorb) -void shake128_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_finalize FIPS202_NAMESPACE(shake128_finalize) -void shake128_finalize(keccak_state *state); -#define shake128_squeeze FIPS202_NAMESPACE(shake128_squeeze) -void shake128_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake128_absorb_once FIPS202_NAMESPACE(shake128_absorb_once) -void shake128_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake128_squeezeblocks FIPS202_NAMESPACE(shake128_squeezeblocks) -void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake256_init FIPS202_NAMESPACE(shake256_init) -void shake256_init(keccak_state *state); -#define shake256_absorb FIPS202_NAMESPACE(shake256_absorb) -void shake256_absorb(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_finalize FIPS202_NAMESPACE(shake256_finalize) -void shake256_finalize(keccak_state *state); -#define shake256_squeeze FIPS202_NAMESPACE(shake256_squeeze) -void shake256_squeeze(uint8_t *out, size_t outlen, keccak_state *state); -#define shake256_absorb_once FIPS202_NAMESPACE(shake256_absorb_once) -void shake256_absorb_once(keccak_state *state, const uint8_t *in, size_t inlen); -#define shake256_squeezeblocks FIPS202_NAMESPACE(shake256_squeezeblocks) -void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state); - -#define shake128 FIPS202_NAMESPACE(shake128) -void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define shake256 FIPS202_NAMESPACE(shake256) -void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); -#define sha3_256 FIPS202_NAMESPACE(sha3_256) -void sha3_256(uint8_t h[32], const uint8_t *in, size_t inlen); -#define sha3_512 FIPS202_NAMESPACE(sha3_512) -void sha3_512(uint8_t h[64], const uint8_t *in, size_t inlen); - -#endif diff --git a/crypto_sign/haetae2/ref/fixpoint.c b/crypto_sign/haetae2/ref/fixpoint.c deleted file mode 100644 index 831f15ec..00000000 --- a/crypto_sign/haetae2/ref/fixpoint.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "fixpoint.h" -#include "params.h" -#include -#include - -static void __cneg(fp96_76 *x, const uint8_t sign) { - x->limb48[0] ^= (-(int64_t)sign) & ((1ULL << 48) - 1); - x->limb48[1] ^= -(int64_t)sign; - x->limb48[0] += sign; - renormalize(x); -} - -static void __copy_cneg(fp96_76 *y, const fp96_76 *x, const uint8_t sign) { - y->limb48[0] = ((-(int64_t)sign) & ((1ULL << 48) - 1)) ^ x->limb48[0]; - ; - y->limb48[1] = x->limb48[1] ^ (-(int64_t)sign); - y->limb48[0] += sign; - renormalize(y); -} - -static void fixpoint_mul(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { - uint64_t tmp[2]; - mul48(&xy->limb48[0], x->limb48[0], y->limb48[0]); - - // shift right by 48, rounding - xy->limb48[0] = xy->limb48[1] + (((xy->limb48[0] >> 47) + 1) >> 1); - - mul48(tmp, x->limb48[0], y->limb48[1]); - xy->limb48[0] += tmp[0]; - xy->limb48[1] = tmp[1]; - mulacc48(&xy->limb48[0], x->limb48[1], y->limb48[0]); - - // shift right by 28, rounding - xy->limb48[0] += 1UL << 27; - xy->limb48[0] >>= 28; - xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] >>= 28; - - mul64(tmp, x->limb48[1], y->limb48[1]); - xy->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); - - renormalize(xy); -} - -static void fixpoint_unsigned_signed_mul(fp96_76 *xy, const fp96_76 *y) { - fp96_76 x, z; - uint8_t sign = (y->limb48[1] >> 63) & 1; - __copy_cneg(&x, y, sign); - fixpoint_mul(&z, &x, xy); - __copy_cneg(xy, &z, sign); -} - -static void fixpoint_sub(fp96_76 *xminy, const fp96_76 *x, const fp96_76 *y) { - fp96_76 yneg; - __copy_cneg(&yneg, y, 1); - fixpoint_add(xminy, x, &yneg); -} - -static void fixpoint_sub_from_threehalves(fp96_76 *x) { - __cneg(x, 1); - x->limb48[1] += 3ULL << 27; // left shift by 28 would be "3" - renormalize(x); -} - -void fixpoint_square(fp96_76 *sqx, const fp96_76 *x) { - uint64_t tmp[2]; - sq48(&sqx->limb48[0], x->limb48[0]); - - // shift right by 48, rounding - //sqx->limb48[0] += 1ULL << 47; - sqx->limb48[0] >>= 48; - sqx->limb48[0] += sqx->limb48[1]; - - // mul - mul48(tmp, x->limb48[0], x->limb48[1]); - sqx->limb48[0] += tmp[0] << 1; - sqx->limb48[1] = tmp[1] << 1; - - // shift right by 28, rounding - //sqx->limb48[0] += 1ULL << 27; - sqx->limb48[0] >>= 28; - sqx->limb48[0] += (sqx->limb48[1] << 20) & ((1ULL << 48) - 1); - sqx->limb48[1] >>= 28; - - sq64(tmp, x->limb48[1]); - sqx->limb48[0] += (tmp[0] << 20) & ((1ULL << 48) - 1); - sqx->limb48[1] += (tmp[0] >> 28) + (tmp[1] << 36); - - renormalize(sqx); -} - -// start_cube = hex(round(2^64/(sqrt((K + L)*N + 2)^3))) -// start_times_threehalfs = hex(round(2^64 * 2/(3 * sqrt((K + L)*N + 2)))) -#if L == 4 -const fp96_76 start_cube = {.limb48 = {0x770077e2e41aULL, 0x1162ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x693861ad937bULL, 0x9caa56ULL}}; -#elif L == 6 -const fp96_76 start_cube = {.limb48 = {0x1a2935cfae68ULL, 0x978ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x7ad215218533ULL, 0x7ff1c9ULL}}; -#elif L == 7 -const fp96_76 start_cube = {.limb48 = {0x700ff3e8890dULL, 0x702ULL}}; -const fp96_76 start_times_threehalves = { - .limb48 = {0x5768588eed31ULL, 0x73bd40ULL}}; -#endif - -// implements Newton's method -void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf) { - fp96_76 tmp, tmp2; - fixpoint_mul(&tmp, xhalf, &start_cube); // definitely two positive values - fixpoint_sub(invsqrtx, &start_times_threehalves, - &tmp); // first Newton iteration done, might be negative (very - // improbable) - - for (int i = 0; i < 6; i++) // 6 more iterations - { - fixpoint_square(&tmp, invsqrtx); // tmp = y^2, never negative - fixpoint_mul(&tmp2, xhalf, &tmp); // tmp2 = x/2 * y^2, never negative - fixpoint_sub_from_threehalves(&tmp2); // tmp = 3/2 - x/2 * y^2 - fixpoint_unsigned_signed_mul(invsqrtx, &tmp2); // y * (3/2 - x/2 * y^2) - } -} - -int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, - const uint8_t sign) { - int64_t res; - fp96_76 tmp, xx; - xx.limb48[1] = x >> 32; - xx.limb48[0] = (x & ((1ULL << 32) - 1)) << 16; - fixpoint_mul(&tmp, &xx, y); - res = (tmp.limb48[1] + (1UL << 14)) >> 15; // rounding - return (1 - 2 * (int32_t)sign) * res; -} - -void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y) { - xy->limb48[0] = x->limb48[0] + y->limb48[0]; - xy->limb48[1] = x->limb48[1] + y->limb48[1]; -} diff --git a/crypto_sign/haetae2/ref/fixpoint.h b/crypto_sign/haetae2/ref/fixpoint.h deleted file mode 100644 index 7e608aa0..00000000 --- a/crypto_sign/haetae2/ref/fixpoint.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef FP__H -#define FP__H - -#include "config.h" -#include -#include - -#ifdef __SIZEOF_INT128__ -__extension__ typedef __int128 int128; -__extension__ typedef unsigned __int128 uint128; -#endif - -typedef struct { - uint64_t limb48[2]; -} fp96_76; - -#define fixpoint_square HAETAE_NAMESPACE(fixpoint_square) -void fixpoint_square(fp96_76 *sqx, const fp96_76 *x); - -#define fixpoint_newton_invsqrt HAETAE_NAMESPACE(fixpoint_newton_invsqrt) -void fixpoint_newton_invsqrt(fp96_76 *invsqrtx, const fp96_76 *xhalf); - -#define fixpoint_mul_rnd13 HAETAE_NAMESPACE(fixpoint_mul_rnd13) -int32_t fixpoint_mul_rnd13(const uint64_t x, const fp96_76 *y, - const uint8_t sign); - -#define fixpoint_add HAETAE_NAMESPACE(fixpoint_add) -void fixpoint_add(fp96_76 *xy, const fp96_76 *x, const fp96_76 *y); - -static inline void renormalize(fp96_76 *x) { - x->limb48[1] += x->limb48[0] >> 48; - x->limb48[0] &= (1ULL << 48) - 1; -} - -static inline int64_t smulh48(int64_t a, uint64_t b) { -#ifndef __SIZEOF_INT128__ - int64_t ah = a >> 24; - int64_t al = a - (ah << 24); - int64_t bl = b & ((1<<24)-1); - int64_t bh = b >> 24; - - int64_t res = (al*bl) >> 24; - res += al * bh + ah * bl + (1 << 23); // rounding - res >>= 24; - return res + (ah * bh); -#else - return ((int128)a * (int128)b + (1ULL << 47)) >> 48; // rounding -#endif -} - -static inline void mul64(uint64_t r[2], const uint64_t b, const uint64_t a) { -#ifndef __SIZEOF_INT128__ - uint64_t al = a & ((1ULL << 32) - 1), bl = b & ((1ULL << 32) - 1), - ah = a >> 32, bh = b >> 32; - r[0] = a * b; - r[1] = ah * bl + al * bh + ((al * bl) >> 32); - r[1] >>= 32; - r[1] += ah * bh; -#else - uint128 res = ((uint128)a * (uint128)b); - r[0] = res; - r[1] = res >> 64; -#endif -} - -static inline void sq64(uint64_t r[2], const uint64_t a) { -#ifndef __SIZEOF_INT128__ - uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; - r[0] = a * a; - r[1] = ah * al * 2; - r[1] >>= 32; - r[1] += ah * ah; -#else - uint128 res = ((uint128)a * (uint128)a); - r[0] = res; - r[1] = res >> 64; -#endif -} - -static inline void mul48(uint64_t r[2], const uint64_t b, const uint64_t a) { - mul64(r, b, a); - r[1] <<= 16; - r[1] ^= r[0] >> 48; - r[0] &= (1ULL << 48) - 1; -} - -static inline void mulacc48(uint64_t r[2], const uint64_t b, const uint64_t a) { - uint64_t tmp[2]; - mul48(tmp, b, a); - r[0] += tmp[0]; - r[1] += tmp[1]; -} - -// (a0 + a1*2^32)^2 = a0^2 + 2^33*a0*a1 + 2^64*a1^2 -static inline void sq48(uint64_t r[2], const uint64_t a) { - uint64_t al = a & ((1ULL << 32) - 1), ah = a >> 32; - r[0] = a * a; - r[1] = al * ah << 1; - r[1] >>= 32; - r[1] += ah * ah; - - r[1] <<= 16; - r[1] ^= r[0] >> 48; - r[0] &= (1ULL << 48) - 1; -} - -static inline void fixpoint_mul_high(fp96_76 *xy, const fp96_76 *x, - const uint64_t y) { - uint64_t tmp[2]; - mul48(&xy->limb48[0], x->limb48[0], y); // implicitly shifted right by 48 - - mul48(tmp, x->limb48[1], y); - xy->limb48[1] += tmp[0]; - - // shift right by 28, rounding - xy->limb48[0] += 1UL << 27; - xy->limb48[0] >>= 28; - xy->limb48[0] += (xy->limb48[1] << 20) & ((1ULL << 48) - 1); - xy->limb48[1] >>= 28; - - xy->limb48[1] += tmp[1] << 20; - - renormalize(xy); -} - -#endif diff --git a/crypto_sign/haetae2/ref/ntt.c b/crypto_sign/haetae2/ref/ntt.c deleted file mode 100644 index 6b66d3f6..00000000 --- a/crypto_sign/haetae2/ref/ntt.c +++ /dev/null @@ -1,95 +0,0 @@ -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include - -static const int32_t zetas[N] = { - 0, 26964, -16505, 22229, 30746, 20243, 19064, -31218, 9395, - -30985, 22859, -8851, 32144, 13744, 21408, 17599, -16039, -22946, - 6241, -19553, 10681, 22935, 22431, -29104, 28147, -27527, -29133, - -20035, 20143, -11361, 30820, 25252, -22562, -6789, -10049, 9383, - 16304, -12296, 16446, 18239, -1296, -19725, -32076, 11782, -17941, - 29643, -8577, 7893, -21464, -19646, -15130, -2391, 30608, -23970, - -16608, 19616, -7941, 26533, -19129, 27690, 7597, -11459, 10615, - -9430, 11591, 7814, 12697, 32114, -3761, -9604, 19813, 20353, - 17456, -16267, -19555, 598, -29942, 4538, 835, 15546, 3970, - -27685, 1488, 8311, -12442, 31352, -17631, 1806, -5342, 9790, - 29068, 16507, -29051, 22131, 6759, 15510, -14941, 28710, 1160, - -31327, 24985, 11261, -10623, -27727, 21502, 18731, -16186, -4127, - -18832, 12050, -14501, 7929, 29563, -31064, 5913, 5322, -16405, - 2844, 29439, 5876, -9522, -18586, -9874, 23844, 30362, -21442, - 9560, 17671, -27989, 3350, 787, -13857, 1657, -21224, -7374, - -9190, 2464, 25555, -3529, -28772, 16588, -15739, 23475, 13666, - 5764, 30980, 13633, -7401, -30317, 28847, 7682, -11808, -8796, - 14864, -24162, -19194, 689, -1311, -31332, -16319, 1025, 10971, - -23016, -2648, -21900, -12543, -25921, 28254, 28521, -16160, 12380, - -12882, -30332, -16630, 23439, 7742, 17182, 17494, 5920, 13642, - 7382, -18166, 21422, -30274, -28190, 13283, -20316, -9939, 10672, - 21454, 6080, -17374, -29735, -25912, -10170, 3808, 10639, -26985, - -10865, 25636, 17261, -26851, -8253, -3304, 18282, -2202, -31368, - -22243, 13882, 12069, -11242, -7729, -10226, 1761, -27298, -4800, - -17737, -22805, -3528, 65, 10770, 8908, -23751, 26934, 21921, - -27010, -21944, 8889, -1035, 23224, -9488, -5823, -994, -20206, - 7655, -16251, -22820, -27740, 15822, 23078, 13803, -8099, 2931, - 9217, -21126, -14203, 25492, -12831, 7947, 17463, -12979, 29003, - 31612, 26554, 8241, -20175}; // q = 64513 - -/************************************************* - * Name: ntt - * - * Description: Forward NTT, in-place. No modular reduction is performed after - * additions or subtractions. Output vector is in bitreversed - *order. - * - * Arguments: - uint32_t p[N]: input/output coefficient array - **************************************************/ -void ntt(int32_t a[N]) { - unsigned int len, start, j, k; - int32_t zeta, t; - - k = 0; - for (len = 128; len > 0; len >>= 1) { - for (start = 0; start < N; start = j + len) { - zeta = zetas[++k]; - for (j = start; j < start + len; ++j) { - t = montgomery_reduce((int64_t)zeta * a[j + len]); - a[j + len] = a[j] - t; - a[j] = a[j] + t; - } - } - } -} - -/************************************************* - * Name: invntt_tomont - * - * Description: Inverse NTT and multiplication by Montgomery factor 2^32. - * In-place. No modular reductions after additions or - * subtractions; input coefficients need to be smaller than - * Q in absolute value. Output coefficient are smaller than Q in - * absolute value. - * - * Arguments: - uint32_t p[N]: input/output coefficient array - **************************************************/ -void invntt_tomont(int32_t a[N]) { - unsigned int start, len, j, k; - int32_t t, zeta; - const int32_t f = -29720; // mont^2/256 - - k = 256; - for (len = 1; len < N; len <<= 1) { - for (start = 0; start < N; start = j + len) { - zeta = -zetas[--k]; - for (j = start; j < start + len; ++j) { - t = a[j]; - a[j] = t + a[j + len]; - a[j + len] = t - a[j + len]; - a[j + len] = montgomery_reduce((int64_t)zeta * a[j + len]); - } - } - } - - for (j = 0; j < N; ++j) { - a[j] = montgomery_reduce((int64_t)f * a[j]); - } -} diff --git a/crypto_sign/haetae2/ref/ntt.h b/crypto_sign/haetae2/ref/ntt.h deleted file mode 100644 index c7732a34..00000000 --- a/crypto_sign/haetae2/ref/ntt.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include "params.h" -#include - -#define ntt HAETAE_NAMESPACE(ntt) -void ntt(int32_t a[N]); - -#define invntt_tomont HAETAE_NAMESPACE(invntt_tomont) -void invntt_tomont(int32_t a[N]); - -#endif \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.c b/crypto_sign/haetae2/ref/packing.c deleted file mode 100644 index b32508a9..00000000 --- a/crypto_sign/haetae2/ref/packing.c +++ /dev/null @@ -1,281 +0,0 @@ -#include "packing.h" -#include "encoding.h" -#include "params.h" -#include "poly.h" -#include "polymat.h" -#include "polyvec.h" -#include - -/************************************************* - * Name: pack_pk - * - * Description: Bit-pack public key pk = (seed, b). - * - * Arguments: - uint8_t pk[]: output byte array - * - const polyveck *b: polynomial vector of length K containg b - * - const uint8_t seed[]: seed for A' - **************************************************/ -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, - const uint8_t seed[SEEDBYTES]) { - unsigned int i; - - memcpy(pk, seed, SEEDBYTES); - - pk += SEEDBYTES; - for (i = 0; i < K; ++i) { - polyq_pack(pk + i * POLYQ_PACKEDBYTES, &b->vec[i]); - } -} - -/************************************************* - * Name: unpack_pk - * - * Description: Unpack public key pk = (seed, b). - * - * Arguments: - uint8_t seed[]: seed for A' - * - polyveck *b: polynomial vector of length K containg b - * - const uint8_t pk[]: output byte array - **************************************************/ -void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], - const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) { - unsigned int i; - - memcpy(seed, pk, SEEDBYTES); - - pk += SEEDBYTES; - for (i = 0; i < K; ++i) { - polyq_unpack(&b->vec[i], pk + i * POLYQ_PACKEDBYTES); - } -} - -/************************************************* - * Name: pack_sk - * - * Description: Bit-pack secret key sk = (pk, s). - * - * Arguments: - uint8_t sk[]: output byte array - * - const uint8_t pk[PUBLICKEYBYTES]: packed pk - * - const polyvecl *s0: polyvecl pointer containing s0 (encoding - *starting at offset 1) - * - const polyveck *s1: polyveck pointer containing s1 - **************************************************/ -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, - const polyveck *s1, const uint8_t key[SEEDBYTES]) { - unsigned int i; - memcpy(sk, pk, CRYPTO_PUBLICKEYBYTES); - - sk += CRYPTO_PUBLICKEYBYTES; - for (i = 0; i < M; ++i) - polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s0->vec[i]); - - sk += (L - 1) * POLYETA_PACKEDBYTES; -#if D == 1 - for (i = 0; i < K; ++i) - poly2eta_pack(sk + i * POLY2ETA_PACKEDBYTES, &s1->vec[i]); - sk += K * POLY2ETA_PACKEDBYTES; -#elif D == 0 - for (i = 0; i < K; ++i) - polyeta_pack(sk + i * POLYETA_PACKEDBYTES, &s1->vec[i]); - sk += K * POLYETA_PACKEDBYTES; -#else -#error "Not yet implemented." -#endif - memcpy(sk, key, SEEDBYTES); -} - -/************************************************* - * Name: unpack_sk - * - * Description: Unpack secret key sk = (A, s). - * - * Arguments: - polyvecl A[K]: output polyvecl_frozen array for A - * - polyvecl s0: output polyvecl pointer for s0 - * - polyveck s1: output polyveck pointer for s1 - * - const uint8_t sk[]: byte array containing bit-packed sk - **************************************************/ -void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) { - unsigned int i; - uint8_t rhoprime[SEEDBYTES]; - polyveck b1; -#if D > 0 - polyveck a; -#endif - - unpack_pk(&b1, rhoprime, sk); - - sk += CRYPTO_PUBLICKEYBYTES; - for (i = 0; i < M; ++i) - polyeta_unpack(&s0->vec[i], sk + i * POLYETA_PACKEDBYTES); - - sk += M * POLYETA_PACKEDBYTES; -#if D == 1 - for (i = 0; i < K; ++i) - poly2eta_unpack(&s1->vec[i], sk + i * POLY2ETA_PACKEDBYTES); - - sk += K * POLY2ETA_PACKEDBYTES; -#elif D == 0 - for (i = 0; i < K; ++i) - polyeta_unpack(&s1->vec[i], sk + i * POLYETA_PACKEDBYTES); - - sk += K * POLYETA_PACKEDBYTES; -#else -#error "Not yet implemented." -#endif - memcpy(key, sk, SEEDBYTES); - - // A' = PRG(rhoprime) - polymatkl_expand_frozen(A, rhoprime); - polymatkl_double_frozen(A); -#if D > 0 - polyveck_expand(&a, rhoprime); -#endif - -#if D == 1 - // first column of A = 2(a-b1*2^d) - polyveck_double(&b1); - polyveck_sub(&b1, &a, &b1); - polyveck_double(&b1); - polyveck_ntt(&b1); -#elif D == 0 -#else -#error "Not yet implemented." -#endif - // append b into A - for (i = 0; i < K; ++i) { - for (size_t j = 0; j < N; j++) { - A[i].vec[0].coeffs[j] = (uint16_t) freeze(b1.vec[i].coeffs[j]); - } - } -} - -/************************************************* - * Name: pack_sig - * - * Description: Bit-pack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), - *Enc(h)). - * - * Arguments: - uint8_t sig[]: output byte array - * - const poly *c: pointer to challenge polynomial - * - const polyvecl *lowbits_z1: pointer to vector LowBits(z1) of - *length L - * - const polyvecl *highbits_z1: pointer to vector HighBits(z1) of - *length L - * - const polyveck *h: pointer t vector h of length K - * Returns 1 in case the signature size is above the threshold; otherwise 0. - **************************************************/ -int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, - const polyvecl *lowbits_z1, const polyvecl *highbits_z1, - const polyveck *h) { - - uint8_t encoded_h[N * K]; - uint8_t encoded_hb_z1[N * L]; - uint16_t size_enc_h, size_enc_hb_z1; - uint8_t offset_enc_h, offset_enc_hb_z1; - - // init/padding with zeros: - memset(sig, 0, CRYPTO_BYTES); - - // encode challenge - for (size_t i = 0; i < N; i++) - { - sig[i/8] |= c->coeffs[i] << (i%8); - } - sig += N / 8; - - for (int i = 0; i < L; ++i) - poly_decomposed_pack(sig + N * i, &lowbits_z1->vec[i]); - sig += L * N; - - size_enc_hb_z1 = - encode_hb_z1(encoded_hb_z1, &highbits_z1->vec[0].coeffs[0]); - size_enc_h = encode_h(encoded_h, &h->vec[0].coeffs[0]); - - if(size_enc_h == 0 || size_enc_hb_z1 == 0) { - return 1; // encoding failed - } - - // The size of the encoded h and HB(z1) does not always fit in one byte, - // thus we output a one byte offset to a fixed baseline - if(size_enc_h < BASE_ENC_H || size_enc_hb_z1 < BASE_ENC_HB_Z1 || - size_enc_h > BASE_ENC_H + 255 || size_enc_hb_z1 > BASE_ENC_HB_Z1 + 255) { - return 1; // encoding size offset out of range - } - - offset_enc_hb_z1 = size_enc_hb_z1 - BASE_ENC_HB_Z1; - offset_enc_h = size_enc_h - BASE_ENC_H; - - if (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h > - CRYPTO_BYTES) { - return 1; // signature too big - } - - sig[0] = offset_enc_hb_z1; - sig[1] = offset_enc_h; - sig += 2; - - memcpy(sig, encoded_hb_z1, size_enc_hb_z1); - sig += size_enc_hb_z1; - - memcpy(sig, encoded_h, size_enc_h); - sig += size_enc_h; - - return 0; -} - -/************************************************* - * Name: unpack_sig - * - * Description: Unpack signature sig = (c, LB(z1), len(x), x= Enc(HB(z1)), - *Enc(h)). - * - * Arguments: - poly *c: pointer to challenge polynomial - * - polyvecl *lowbits_z1: pointer to output vector LowBits(z1) - * - polyvecl *highbits_z1: pointer to output vector HighBits(z1) - * - polyveck *h: pointer to output vector h - * - const uint8_t sig[]: byte array containing - * bit-packed signature - * - * Returns 1 in case of malformed signature; otherwise 0. - **************************************************/ -int unpack_sig(poly *c, polyvecl *lowbits_z1, - polyvecl *highbits_z1, polyveck *h, - const uint8_t sig[CRYPTO_BYTES]) { - - uint16_t size_enc_hb_z1, size_enc_h; - - for (unsigned int i = 0; i < N; i++) - { - c->coeffs[i] = (sig[i/8] >> (i%8)) & 1; - } - sig += N / 8; - - for (unsigned int i = 0; i < L; ++i) - poly_decomposed_unpack(&lowbits_z1->vec[i], sig + N * i); - sig += L * N; - - size_enc_hb_z1 = (uint16_t)sig[0] + BASE_ENC_HB_Z1; - size_enc_h = (uint16_t)sig[1] + BASE_ENC_H; - sig += 2; - - if(CRYPTO_BYTES < (2 + L*N + SEEDBYTES + size_enc_h + size_enc_hb_z1)) - return 1; // invalid size_enc_h and/or size_enc_hb_z1 - - if(decode_hb_z1(&highbits_z1->vec[0].coeffs[0], sig, size_enc_hb_z1)) { - return 1; // decoding failed - } - - sig += size_enc_hb_z1; - - if(decode_h(&h->vec[0].coeffs[0], sig, size_enc_h)) { - return 1; // decoding failed - } - - sig += size_enc_h; - - for(int i=0; i < CRYPTO_BYTES - (SEEDBYTES + L * N + 2 + size_enc_hb_z1 + size_enc_h); i++) - if(sig[i] != 0) return 1; // verify zero padding - - return 0; -} \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/packing.h b/crypto_sign/haetae2/ref/packing.h deleted file mode 100644 index 152ba75a..00000000 --- a/crypto_sign/haetae2/ref/packing.h +++ /dev/null @@ -1,25 +0,0 @@ -// clang-format off -#ifndef HAETAE_PACKING_H -#define HAETAE_PACKING_H - -#include "params.h" -#include "polyvec.h" -#include - -#define pack_pk HAETAE_NAMESPACE(pack_pk) -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], polyveck *b, const uint8_t seed[SEEDBYTES]); -#define unpack_pk HAETAE_NAMESPACE(unpack_pk) -void unpack_pk(polyveck *b, uint8_t seed[SEEDBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); - -#define pack_sk HAETAE_NAMESPACE(pack_sk) -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t pk[CRYPTO_PUBLICKEYBYTES], const polyvecm *s0, const polyveck *s1, const uint8_t key[SEEDBYTES]); -#define unpack_sk HAETAE_NAMESPACE(unpack_sk) -void unpack_sk(polyvecl_frozen A[K], polyvecm *s0, polyveck *s1, uint8_t *key, const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - -#define pack_sig HAETAE_NAMESPACE(pack_sig) -int pack_sig(uint8_t sig[CRYPTO_BYTES], const poly *c, const polyvecl *lowbits_z1, const polyvecl *highbits_z1, const polyveck *h); -#define unpack_sig HAETAE_NAMESPACE(unpack_sig) -int unpack_sig(poly *c, polyvecl *lowbits_z1, polyvecl *highbits_z1, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); - -#endif //HAETAE_PACKING_H -// clang-format on diff --git a/crypto_sign/haetae2/ref/params.h b/crypto_sign/haetae2/ref/params.h deleted file mode 100644 index c73e63f2..00000000 --- a/crypto_sign/haetae2/ref/params.h +++ /dev/null @@ -1,116 +0,0 @@ -// clang-format off -#ifndef HAETAE_PARAMS_H -#define HAETAE_PARAMS_H - -#include "config.h" - -#define SEEDBYTES 32 -#define CRHBYTES 64 -#define N 256 -#define ROOT_OF_UNITY 3 - -#define Q 64513 -#define DQ (Q << 1)// 2Q - -#if HAETAE_MODE == 2 -#define K 2 -#define L 4 -#define ETA 1 -#define TAU 58 -#define B0 9846.02 -#define B1 9838.99 -#define B2 12777.52 -#define GAMMA 48.858 -#define LN 8192 // Large N -#define SQNM 39.191835884530846 // \sqrt(n * m) -#define D 1 -#define CRYPTO_BYTES 1474 - -#define BASE_ENC_HB_Z1 132 -#define BASE_ENC_H 7 - -#define ALPHA_HINT 512 -#define LOG_ALPHA_HINT 9 - -#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits -#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits - -#elif HAETAE_MODE == 3 -#define K 3 -#define L 6 -#define ETA 1 -#define TAU 80 -#define B0 18314.98 -#define B1 18307.70 -#define B2 21906.65 -#define GAMMA 57.707 -#define LN 8192 // Large N -#define SQNM 48.0 -#define D 1 -#define CRYPTO_BYTES 2349 - -#define BASE_ENC_HB_Z1 376 -#define BASE_ENC_H 127 - -#define ALPHA_HINT 512 -#define LOG_ALPHA_HINT 9 - -#define POLYB1_PACKEDBYTES 480 // 15bits * N / 8bits -#define POLYQ_PACKEDBYTES 480 // 16bits * N / 8bits - -#elif HAETAE_MODE == 5 -#define K 4 -#define L 7 -#define ETA 1 -#define TAU 128 -#define B0 22343.66 -#define B1 22334.95 -#define B2 24441.49 -#define GAMMA 55.13 -#define LN 8192 // Large N -#define SQNM 53.0659966456864 -#define D 0 -#define CRYPTO_BYTES 2948 - -#define BASE_ENC_HB_Z1 501 -#define BASE_ENC_H 358 - -#define ALPHA_HINT 256 -#define LOG_ALPHA_HINT 8 - -#define POLYB1_PACKEDBYTES 512 // 16bits * N / 8bits -#define POLYQ_PACKEDBYTES 512 // 16bits * N / 8bits - -#endif // HAETAE_MODE - -#define HALF_ALPHA_HINT (ALPHA_HINT >> 1) // ALPHA / 2 - -#define B0SQ ((uint64_t)(B0*B0)) -#define B1SQ ((uint64_t)(B1*B1)) -#define B2SQ ((uint64_t)(B2*B2)) - -#define M (L-1) - -#if ETA == 1 -#define POLYETA_PACKEDBYTES 64 -#define POLY2ETA_PACKEDBYTES 96 -#elif ETA == 2 -#define POLYETA_PACKEDBYTES 96 -#endif - -#define POLYC_PACKEDBYTES 32 // 1bit * N / 8bits -#define POLY_HIGHBITS_PACKEDBYTES (N * 9 / 8) -#define POLYVECK_HIGHBITS_PACKEDBYTES (POLY_HIGHBITS_PACKEDBYTES * K) -#define POLYVECK_BYTES (K * N * sizeof(int32_t)) -#define POLYVECL_BYTES (L * N * sizeof(int32_t)) - -#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K * POLYQ_PACKEDBYTES) // seed + b -#if D == 1 -#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + M * POLYETA_PACKEDBYTES + K * POLY2ETA_PACKEDBYTES + SEEDBYTES) // pk + s + K -#elif D == 0 -#define CRYPTO_SECRETKEYBYTES (CRYPTO_PUBLICKEYBYTES + (M + K) * POLYETA_PACKEDBYTES + SEEDBYTES) // pk + s + K -#else -#error -#endif -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/poly.c b/crypto_sign/haetae2/ref/poly.c deleted file mode 100644 index 39c1bae3..00000000 --- a/crypto_sign/haetae2/ref/poly.c +++ /dev/null @@ -1,710 +0,0 @@ -#include "poly.h" -#include "decompose.h" -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: poly_add - * - * Description: Add polynomials. No modular reduction is performed. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first summand - * - const poly *b: pointer to second summand - **************************************************/ -void poly_add(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; -} - -/************************************************* - * Name: poly_sub - * - * Description: Subtract polynomials. No modular reduction is - * performed. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first input polynomial - * - const poly *b: pointer to second input polynomial to be - * subtraced from first input polynomial - **************************************************/ -void poly_sub(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; -} - -/************************************************* - * Name: poly_pointwise_montgomery - * - * Description: Pointwise multiplication of polynomials in NTT domain - * representation and multiplication of resulting polynomial - * by 2^{-32}. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly *a: pointer to first input polynomial - * - const poly *b: pointer to second input polynomial - **************************************************/ -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); -} - -/************************************************* - * Name: poly_pointwise_montgomery_frozen - * - * Description: Pointwise multiplication of polynomials in NTT domain - * representation and multiplication of resulting polynomial - * by 2^{-32}. - * - * Arguments: - poly *c: pointer to output polynomial - * - const poly_frozen *a: pointer to first input polynomial - * - const poly *b: pointer to second input polynomial - **************************************************/ -void poly_pointwise_montgomery_frozen(poly *c, const poly_frozen *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = montgomery_reduce((int64_t)a->coeffs[i] * b->coeffs[i]); -} - -/************************************************* - * Name: poly_reduce2q - * - * Description: Inplace reduction of all coefficients of polynomial to 2q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_reduce2q(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = reduce32_2q(a->coeffs[i]); -} - -/************************************************* - * Name: poly_freeze2q - * - * Description: For all coefficients of in/out polynomial compute standard - * representative r = a mod^+ 2Q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_freeze2q(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = freeze2q(a->coeffs[i]); -} - -/************************************************* - * Name: poly_freeze - * - * Description: For all coefficients of in/out polynomial compute standard - * representative r = a mod^+ Q - * - * Arguments: - poly *a: pointer to input/output polynomial - **************************************************/ -void poly_freeze(poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = freeze(a->coeffs[i]); -} - -/************************************************* - * Name: poly_highbits - * - * Description: Compute HighBits of polynomial - * - * Arguments: - poly *a2: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_highbits(poly *a2, const poly *a) { - unsigned int i; - int32_t a1tmp; - - for (i = 0; i < N; ++i) - decompose_z1(&a2->coeffs[i], &a1tmp, a->coeffs[i]); -} - -/************************************************* - * Name: poly_lowbits - * - * Description: Compute LowBits of polynomial - * - * Arguments: - poly *a1: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_lowbits(poly *a1, const poly *a) { - unsigned int i = 0; - int32_t a2tmp = 0; - - for (i = 0; i < N; ++i) - decompose_z1(&a2tmp, &a1->coeffs[i], a->coeffs[i]); -} - -/************************************************* - * Name: poly_compose - * - * Description: Compose HighBits and LowBits to recreate the polynomial - * - * Arguments: - poly *a3: pointer to output polynomial - * - const poly *ha: pointer to HighBits polynomial - * - const poly *la: pointer to HighBits polynomial - **************************************************/ -void poly_compose(poly *a, const poly *ha, const poly *la) { - unsigned int i = 0; - - for (i = 0; i < N; ++i) - a->coeffs[i] = (ha->coeffs[i] << 8) + la->coeffs[i]; -} - -/************************************************* - * Name: poly_lsb - * - * Description: Compute least significant bits of polynomial - * - * Arguments: - poly *a0: pointer to output polynomial - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly_lsb(poly *a0, const poly *a) { - unsigned int i; - - for (i = 0; i < N; ++i) - a0->coeffs[i] = a->coeffs[i] & 1; -} - -/************************************************* - * Name: poly_uniform - * - * Description: Sample polynomial with uniformly random coefficients - * in [0,Q-1] by performing rejection sampling on the - * output stream of SHAKE256(seed|nonce) - * - * Arguments: - poly *a: pointer to output polynomial - * - const uint8_t seed[]: byte array with seed of length SEEDBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -#define POLY_UNIFORM_NBLOCKS \ - ((512 + STREAM128_BLOCKBYTES - 1) / STREAM128_BLOCKBYTES) -// N * 2(random bytes for [0, Q - 1]) - -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { - unsigned int i, ctr, off; - unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; - stream128_state state; - - stream128_init(&state, seed, nonce); - stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); - - ctr = rej_uniform(a->coeffs, N, buf, buflen); - - while (ctr < N) { - off = buflen % 2; - for (i = 0; i < off; ++i) - buf[i] = buf[buflen - off + i]; - - stream128_squeezeblocks(buf + off, 1, &state); - buflen = STREAM128_BLOCKBYTES + off; - ctr += rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); - } -} - -/************************************************* - * Name: poly_uniform_frozen - * - * Description: Sample polynomial with uniformly random coefficients - * in [0,Q-1] by performing rejection sampling on the - * output stream of SHAKE256(seed|nonce) - * - * Arguments: - poly *a: pointer to output polynomial - * - const uint8_t seed[]: byte array with seed of length SEEDBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce) { - unsigned int i, ctr, off; - unsigned int buflen = POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_NBLOCKS * STREAM128_BLOCKBYTES + 1]; - stream128_state state; - - stream128_init(&state, seed, nonce); - stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); - - ctr = rej_uniform_frozen(a->coeffs, N, buf, buflen); - - while (ctr < N) { - off = buflen % 2; - for (i = 0; i < off; ++i) - buf[i] = buf[buflen - off + i]; - - stream128_squeezeblocks(buf + off, 1, &state); - buflen = STREAM128_BLOCKBYTES + off; - ctr += rej_uniform_frozen(a->coeffs + ctr, N - ctr, buf, buflen); - } -} - -/************************************************* - * Name: poly_uniform_eta - * - * Description: Sample polynomial with uniformly random coefficients - * in [-ETA,ETA] by performing rejection sampling on the - * output stream from SHAKE256(seed|nonce) - * - * Arguments: - poly *a: pointer to output polynomial - * - const uint8_t seed[]: byte array with seed of length CRHBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -#if ETA == 1 -#define POLY_UNIFORM_ETA_NBLOCKS \ - ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -#elif ETA == 2 -#define POLY_UNIFORM_ETA_NBLOCKS \ - ((136 + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -#endif - -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int ctr; - unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); - - ctr = rej_eta(a->coeffs, N, buf, buflen); - - while (ctr < N) { - stream256_squeezeblocks(buf, 1, &state); - ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); - } -} - -uint8_t hammingWeight_8(uint8_t x) { - x = (x & 0x55) + (x >> 1 & 0x55); - x = (x & 0x33) + (x >> 2 & 0x33); - x = (x & 0x0F) + (x >> 4 & 0x0F); - - return x; -} - -/************************************************* - * Name: poly_challenge - * - * Description: Implementation of challenge. Samples polynomial with TAU 1 - * coefficients using the output stream of SHAKE256(seed). - * - * Arguments: - poly *c: pointer to output polynomial - * - const uint8_t highbits_lsb[]: packed highbits and lsb - * - const uint8_t mu[]: hash of pk and message - **************************************************/ -void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]) { -#if (HAETAE_MODE == 2) || (HAETAE_MODE == 3) - unsigned int i, b, pos = 0; - uint8_t buf[XOF256_BLOCKBYTES]; - xof256_state state; - - // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, highbits_lsb, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, - SEEDBYTES); - xof256_squeezeblocks(buf, 1, &state); - - for (i = 0; i < N; ++i) - c->coeffs[i] = 0; - for (i = N - TAU; i < N; ++i) { - do { - if (pos >= XOF256_BLOCKBYTES) { - xof256_squeezeblocks(buf, 1, &state); - pos = 0; - } - - b = buf[pos++]; - } while (b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1; - } -#elif HAETAE_MODE == 5 - unsigned int i, hwt = 0, cond = 0; - uint8_t mask = 0, w0 = 0; - uint8_t buf[32] = {0}; - xof256_state state; - - // H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - xof256_absorbe_twice(&state, highbits_lsb, - POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES, mu, - SEEDBYTES); - xof256_squeeze(buf, 32, &state); - - for (i = 0; i < 32; ++i) - hwt += hammingWeight_8(buf[i]); - - cond = (128 - hwt); - mask = 0xff & (cond >> 8); - w0 = -(buf[0] & 1); - mask = w0 ^ ((-(!!cond & 1)) & (mask ^ w0)); // mask = !!cond ? mask : w0 - for (i = 0; i < 32; ++i) { - buf[i] ^= mask; - c->coeffs[8 * i] = buf[i] & 1; - c->coeffs[8 * i + 1] = (buf[i] >> 1) & 1; - c->coeffs[8 * i + 2] = (buf[i] >> 2) & 1; - c->coeffs[8 * i + 3] = (buf[i] >> 3) & 1; - c->coeffs[8 * i + 4] = (buf[i] >> 4) & 1; - c->coeffs[8 * i + 5] = (buf[i] >> 5) & 1; - c->coeffs[8 * i + 6] = (buf[i] >> 6) & 1; - c->coeffs[8 * i + 7] = (buf[i] >> 7) & 1; - } -#endif -} - -void poly_decomposed_pack(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N; i++) { - buf[i] = a->coeffs[i]; - } -} - -void poly_decomposed_unpack(poly *a, const uint8_t *buf) { - unsigned int i; - for (i = 0; i < N; i++) { - a->coeffs[i] = (int8_t)buf[i]; - } -} - -void poly_pack_highbits(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N / 8; i++) { - buf[9 * i + 0] = a->coeffs[8 * i + 0] & 0xff; - - buf[9 * i + 1] = (a->coeffs[8 * i + 0] >> 8) & 0x01; - buf[9 * i + 1] |= (a->coeffs[8 * i + 1] << 1) & 0xff; - - buf[9 * i + 2] = (a->coeffs[8 * i + 1] >> 7) & 0x03; - buf[9 * i + 2] |= (a->coeffs[8 * i + 2] << 2) & 0xff; - - buf[9 * i + 3] = (a->coeffs[8 * i + 2] >> 6) & 0x07; - buf[9 * i + 3] |= (a->coeffs[8 * i + 3] << 3) & 0xff; - - buf[9 * i + 4] = (a->coeffs[8 * i + 3] >> 5) & 0x0f; - buf[9 * i + 4] |= (a->coeffs[8 * i + 4] << 4) & 0xff; - - buf[9 * i + 5] = (a->coeffs[8 * i + 4] >> 4) & 0x1f; - buf[9 * i + 5] |= (a->coeffs[8 * i + 5] << 5) & 0xff; - - buf[9 * i + 6] = (a->coeffs[8 * i + 5] >> 3) & 0x3f; - buf[9 * i + 6] |= (a->coeffs[8 * i + 6] << 6) & 0xff; - - buf[9 * i + 7] = (a->coeffs[8 * i + 6] >> 2) & 0x7f; - buf[9 * i + 7] |= (a->coeffs[8 * i + 7] << 7) & 0xff; - - buf[9 * i + 8] = (a->coeffs[8 * i + 7] >> 1) & 0xff; - } -} - -void poly_pack_lsb(uint8_t *buf, const poly *a) { - unsigned int i; - for (i = 0; i < N; i++) { - if ((i % 8) == 0) { - buf[i / 8] = 0; - } - buf[i / 8] |= (a->coeffs[i] & 1) << (i % 8); - } -} - -/************************************************* - * Name: polyq_pack - * - * Description: Bit-pack polynomial with coefficients in [0, Q - 1]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYQ_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void polyq_pack(uint8_t *r, const poly *a) { - unsigned int i; -#if D == 1 - int b_idx = 0, d_idx = 0; - - for (i = 0; i < (N >> 3); ++i) { - b_idx = 15 * i; - d_idx = 8 * i; - - r[b_idx] = (a->coeffs[d_idx] & 0xff); - r[b_idx + 1] = ((a->coeffs[d_idx] >> 8) & 0x7f) | - ((a->coeffs[d_idx + 1] & 0x1) << 7); - r[b_idx + 2] = ((a->coeffs[d_idx + 1] >> 1) & 0xff); - r[b_idx + 3] = ((a->coeffs[d_idx + 1] >> 9) & 0x3f) | - ((a->coeffs[d_idx + 2] & 0x3) << 6); - r[b_idx + 4] = ((a->coeffs[d_idx + 2] >> 2) & 0xff); - r[b_idx + 5] = ((a->coeffs[d_idx + 2] >> 10) & 0x1f) | - ((a->coeffs[d_idx + 3] & 0x7) << 5); - r[b_idx + 6] = ((a->coeffs[d_idx + 3] >> 3) & 0xff); - r[b_idx + 7] = ((a->coeffs[d_idx + 3] >> 11) & 0xf) | - ((a->coeffs[d_idx + 4] & 0xf) << 4); - r[b_idx + 8] = ((a->coeffs[d_idx + 4] >> 4) & 0xff); - r[b_idx + 9] = ((a->coeffs[d_idx + 4] >> 12) & 0x7) | - ((a->coeffs[d_idx + 5] & 0x1f) << 3); - r[b_idx + 10] = ((a->coeffs[d_idx + 5] >> 5) & 0xff); - r[b_idx + 11] = ((a->coeffs[d_idx + 5] >> 13) & 0x3) | - ((a->coeffs[d_idx + 6] & 0x3f) << 2); - r[b_idx + 12] = ((a->coeffs[d_idx + 6] >> 6) & 0xff); - r[b_idx + 13] = ((a->coeffs[d_idx + 6] >> 14) & 0x1) | - (a->coeffs[d_idx + 7] & 0x7f) << 1; - r[b_idx + 14] = ((a->coeffs[d_idx + 7] >> 7) & 0xff); - } -#else - for (i = 0; i < N / 1; ++i) { - r[2 * i + 0] = a->coeffs[1 * i + 0] >> 0; - r[2 * i + 1] = a->coeffs[1 * i + 0] >> 8; - } -#endif -} - -/************************************************* - * Name: polyq_unpack - * - * Description: Unpack polynomial with coefficients in [0, Q - 1]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void polyq_unpack(poly *r, const uint8_t *a) { - unsigned int i; -#if D == 1 - int b_idx = 0, d_idx = 0; - - for (i = 0; i < (N >> 3); ++i) { - b_idx = 15 * i; - d_idx = 8 * i; - - r->coeffs[d_idx] = (a[b_idx] & 0xff) | ((a[b_idx + 1] & 0x7f) << 8); - r->coeffs[d_idx + 1] = ((a[b_idx + 1] >> 7) & 0x1) | - ((a[b_idx + 2] & 0xff) << 1) | - ((a[b_idx + 3] & 0x3f) << 9); - r->coeffs[d_idx + 2] = ((a[b_idx + 3] >> 6) & 0x3) | - ((a[b_idx + 4] & 0xff) << 2) | - ((a[b_idx + 5] & 0x1f) << 10); - r->coeffs[d_idx + 3] = ((a[b_idx + 5] >> 5) & 0x7) | - ((a[b_idx + 6] & 0xff) << 3) | - ((a[b_idx + 7] & 0xf) << 11); - r->coeffs[d_idx + 4] = ((a[b_idx + 7] >> 4) & 0xf) | - ((a[b_idx + 8] & 0xff) << 4) | - ((a[b_idx + 9] & 0x7) << 12); - r->coeffs[d_idx + 5] = ((a[b_idx + 9] >> 3) & 0x1f) | - ((a[b_idx + 10] & 0xff) << 5) | - ((a[b_idx + 11] & 0x3) << 13); - r->coeffs[d_idx + 6] = ((a[b_idx + 11] >> 2) & 0x3f) | - ((a[b_idx + 12] & 0xff) << 6) | - ((a[b_idx + 13] & 0x1) << 14); - r->coeffs[d_idx + 7] = - ((a[b_idx + 13] >> 1) & 0x7f) | ((a[b_idx + 14] & 0xff) << 7); - } - -#else - for (i = 0; i < N / 1; ++i) { - r->coeffs[1 * i + 0] = a[2 * i + 0] >> 0; - r->coeffs[1 * i + 0] |= (uint16_t)a[2 * i + 1] << 8; - r->coeffs[1 * i + 0] &= 0xffff; - } -#endif -} - -/************************************************* - * Name: polyeta_pack - * - * Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYETA_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void polyeta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - -#if ETA == 1 - for (i = 0; i < N / 4; ++i) { - t[0] = ETA - a->coeffs[4 * i + 0]; - t[1] = ETA - a->coeffs[4 * i + 1]; - t[2] = ETA - a->coeffs[4 * i + 2]; - t[3] = ETA - a->coeffs[4 * i + 3]; - r[i] = t[0] >> 0; - r[i] |= t[1] << 2; - r[i] |= t[2] << 4; - r[i] |= t[3] << 6; - } -#elif ETA == 2 - for (i = 0; i < N / 8; ++i) { - t[0] = ETA - a->coeffs[8 * i + 0]; - t[1] = ETA - a->coeffs[8 * i + 1]; - t[2] = ETA - a->coeffs[8 * i + 2]; - t[3] = ETA - a->coeffs[8 * i + 3]; - t[4] = ETA - a->coeffs[8 * i + 4]; - t[5] = ETA - a->coeffs[8 * i + 5]; - t[6] = ETA - a->coeffs[8 * i + 6]; - t[7] = ETA - a->coeffs[8 * i + 7]; - - r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#endif -} - -/************************************************* - * Name: polyeta_unpack - * - * Description: Unpack polynomial with coefficients in [-ETA,ETA]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void polyeta_unpack(poly *r, const uint8_t *a) { - unsigned int i; - -#if ETA == 1 - for (i = 0; i < N / 4; ++i) { - r->coeffs[4 * i + 0] = a[i] >> 0; - r->coeffs[4 * i + 0] &= 0x3; - - r->coeffs[4 * i + 1] = a[i] >> 2; - r->coeffs[4 * i + 1] &= 0x3; - - r->coeffs[4 * i + 2] = a[i] >> 4; - r->coeffs[4 * i + 2] &= 0x3; - - r->coeffs[4 * i + 3] = a[i] >> 6; - r->coeffs[4 * i + 3] &= 0x3; - - r->coeffs[4 * i + 0] = ETA - r->coeffs[4 * i + 0]; - r->coeffs[4 * i + 1] = ETA - r->coeffs[4 * i + 1]; - r->coeffs[4 * i + 2] = ETA - r->coeffs[4 * i + 2]; - r->coeffs[4 * i + 3] = ETA - r->coeffs[4 * i + 3]; - } - -#elif ETA == 2 - for (i = 0; i < N / 8; ++i) { - r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; - r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; - r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; - r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; - r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; - r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; - r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; - r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; - - r->coeffs[8 * i + 0] = ETA - r->coeffs[8 * i + 0]; - r->coeffs[8 * i + 1] = ETA - r->coeffs[8 * i + 1]; - r->coeffs[8 * i + 2] = ETA - r->coeffs[8 * i + 2]; - r->coeffs[8 * i + 3] = ETA - r->coeffs[8 * i + 3]; - r->coeffs[8 * i + 4] = ETA - r->coeffs[8 * i + 4]; - r->coeffs[8 * i + 5] = ETA - r->coeffs[8 * i + 5]; - r->coeffs[8 * i + 6] = ETA - r->coeffs[8 * i + 6]; - r->coeffs[8 * i + 7] = ETA - r->coeffs[8 * i + 7]; - } -#endif -} - -/************************************************* - * Name: poly2eta_pack - * - * Description: Bit-pack polynomial with coefficients in [-ETA-1,ETA+1]. - * - * Arguments: - uint8_t *r: pointer to output byte array with at least - * POLYETA_PACKEDBYTES bytes - * - const poly *a: pointer to input polynomial - **************************************************/ -void poly2eta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - -#if ETA == 1 - for (i = 0; i < N / 8; ++i) { - t[0] = 2 * ETA - a->coeffs[8 * i + 0]; - t[1] = 2 * ETA - a->coeffs[8 * i + 1]; - t[2] = 2 * ETA - a->coeffs[8 * i + 2]; - t[3] = 2 * ETA - a->coeffs[8 * i + 3]; - t[4] = 2 * ETA - a->coeffs[8 * i + 4]; - t[5] = 2 * ETA - a->coeffs[8 * i + 5]; - t[6] = 2 * ETA - a->coeffs[8 * i + 6]; - t[7] = 2 * ETA - a->coeffs[8 * i + 7]; - - r[3 * i + 0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3 * i + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3 * i + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#elif ETA == 2 -#error "not yet implemented" -#endif -} - -/************************************************* - * Name: poly2eta_unpack - * - * Description: Unpack polynomial with coefficients in [-ETA-1,ETA+1]. - * - * Arguments: - poly *r: pointer to output polynomial - * - const uint8_t *a: byte array with bit-packed polynomial - **************************************************/ -void poly2eta_unpack(poly *r, const uint8_t *a) { - unsigned int i; - -#if ETA == 1 - for (i = 0; i < N / 8; ++i) { - r->coeffs[8 * i + 0] = (a[3 * i + 0] >> 0) & 7; - r->coeffs[8 * i + 1] = (a[3 * i + 0] >> 3) & 7; - r->coeffs[8 * i + 2] = ((a[3 * i + 0] >> 6) | (a[3 * i + 1] << 2)) & 7; - r->coeffs[8 * i + 3] = (a[3 * i + 1] >> 1) & 7; - r->coeffs[8 * i + 4] = (a[3 * i + 1] >> 4) & 7; - r->coeffs[8 * i + 5] = ((a[3 * i + 1] >> 7) | (a[3 * i + 2] << 1)) & 7; - r->coeffs[8 * i + 6] = (a[3 * i + 2] >> 2) & 7; - r->coeffs[8 * i + 7] = (a[3 * i + 2] >> 5) & 7; - - r->coeffs[8 * i + 0] = 2 * ETA - r->coeffs[8 * i + 0]; - r->coeffs[8 * i + 1] = 2 * ETA - r->coeffs[8 * i + 1]; - r->coeffs[8 * i + 2] = 2 * ETA - r->coeffs[8 * i + 2]; - r->coeffs[8 * i + 3] = 2 * ETA - r->coeffs[8 * i + 3]; - r->coeffs[8 * i + 4] = 2 * ETA - r->coeffs[8 * i + 4]; - r->coeffs[8 * i + 5] = 2 * ETA - r->coeffs[8 * i + 5]; - r->coeffs[8 * i + 6] = 2 * ETA - r->coeffs[8 * i + 6]; - r->coeffs[8 * i + 7] = 2 * ETA - r->coeffs[8 * i + 7]; - } -#elif ETA == 2 -#error "not yet implemented" -#endif -} - -void poly_fromcrt(poly *w, const poly *u, const poly *v) { - unsigned int i; - int32_t xq, x2; - - for (i = 0; i < N; i++) { - xq = u->coeffs[i]; - x2 = v->coeffs[i]; - w->coeffs[i] = xq + (Q & -((xq ^ x2) & 1)); - } -} - -void poly_fromcrt0(poly *w, const poly *u) { - unsigned int i; - int32_t xq; - - for (i = 0; i < N; i++) { - xq = u->coeffs[i]; - w->coeffs[i] = xq + (Q & -(xq & 1)); - } -} - -void poly_ntt(poly *a) { ntt(&a->coeffs[0]); } - -void poly_invntt_tomont(poly *a) { invntt_tomont(&a->coeffs[0]); } diff --git a/crypto_sign/haetae2/ref/poly.h b/crypto_sign/haetae2/ref/poly.h deleted file mode 100644 index b9049607..00000000 --- a/crypto_sign/haetae2/ref/poly.h +++ /dev/null @@ -1,99 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLY_H -#define HAETAE_POLY_H - -#include "params.h" -#include "reduce.h" -#include "sampler.h" -#include - -/********************************************************************** - * Name: poly - * Description: Holds the coefficients of a polynomial. - **********************************************************************/ -typedef struct { - int32_t coeffs[N]; -} poly; - -/********************************************************************** - * Name: poly_frozen - * Description: Holds the fully reduced coefficients of a polynomial, - * i.e. all coefficients are in the interval [0,q-1]. - * Typically used for polynomials which are used as - * read-only after initial computation. - **********************************************************************/ -typedef struct { - uint16_t coeffs[N]; -} poly_frozen; - -#define poly_add HAETAE_NAMESPACE(poly_add) -void poly_add(poly *c, const poly *a, const poly *b); -#define poly_sub HAETAE_NAMESPACE(poly_sub) -void poly_sub(poly *c, const poly *a, const poly *b); -#define poly_pointwise_montgomery HAETAE_NAMESPACE(poly_pointwise_montgomery) -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); -#define poly_pointwise_montgomery_frozen HAETAE_NAMESPACE(poly_pointwise_montgomery_frozen) -void poly_pointwise_montgomery_frozen(poly *c, const poly_frozen *a, const poly *b); - -#define poly_reduce2q HAETAE_NAMESPACE(poly_reduce2q) -void poly_reduce2q(poly *a); -#define poly_freeze2q HAETAE_NAMESPACE(poly_freeze2q) -void poly_freeze2q(poly *a); -#define poly_freeze HAETAE_NAMESPACE(poly_freeze) -void poly_freeze(poly *a); - -#define poly_highbits HAETAE_NAMESPACE(poly_highbits) -void poly_highbits(poly *a2, const poly *a); -#define poly_lowbits HAETAE_NAMESPACE(poly_lowbits) -void poly_lowbits(poly *a1, const poly *a); -#define poly_compose HAETAE_NAMESPACE(poly_compose) -void poly_compose(poly *a, const poly *ha, const poly *la); -#define poly_lsb HAETAE_NAMESPACE(poly_lsb) -void poly_lsb(poly *a0, const poly *a); - -#define poly_uniform HAETAE_NAMESPACE(poly_uniform) -void poly_uniform(poly *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); -#define poly_uniform_frozen HAETAE_NAMESPACE(poly_uniform_frozen) -void poly_uniform_frozen(poly_frozen *a, const uint8_t seed[SEEDBYTES], uint16_t nonce); -#define poly_uniform_eta HAETAE_NAMESPACE(poly_uniform_eta) -void poly_uniform_eta(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define poly_challenge HAETAE_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t highbits_lsb[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES], const uint8_t mu[SEEDBYTES]); - -#define poly_decomposed_pack HAETAE_NAMESPACE(poly_decomposed_pack) -void poly_decomposed_pack(uint8_t *buf, const poly *a); -#define poly_decomposed_unpack HAETAE_NAMESPACE(poly_decomposed_unpack) -void poly_decomposed_unpack(poly *a, const uint8_t *buf); - -#define poly_pack_highbits HAETAE_NAMESPACE(poly_pack_highbits) -void poly_pack_highbits(uint8_t *buf, const poly *a); - -#define poly_pack_lsb HAETAE_NAMESPACE(poly_pack_lsb) -void poly_pack_lsb(uint8_t *buf, const poly *a); - -#define polyq_pack HAETAE_NAMESPACE(polyq_pack) -void polyq_pack(uint8_t *r, const poly *a); -#define polyq_unpack HAETAE_NAMESPACE(polyq_unpack) -void polyq_unpack(poly *r, const uint8_t *a); - -#define polyeta_pack HAETAE_NAMESPACE(polyeta_pack) -void polyeta_pack(uint8_t *r, const poly *a); -#define polyeta_unpack HAETAE_NAMESPACE(polyeta_unpack) -void polyeta_unpack(poly *r, const uint8_t *a); -#define poly2eta_pack HAETAE_NAMESPACE(poly2eta_pack) -void poly2eta_pack(uint8_t *r, const poly *a); -#define poly2eta_unpack HAETAE_NAMESPACE(poly2eta_unpack) -void poly2eta_unpack(poly *r, const uint8_t *a); - -#define poly_fromcrt HAETAE_NAMESPACE(poly_fromcrt) -void poly_fromcrt(poly *w, const poly *u, const poly *v); -#define poly_fromcrt0 HAETAE_NAMESPACE(poly_fromcrt0) -void poly_fromcrt0(poly *w, const poly *u); - -#define poly_ntt HAETAE_NAMESPACE(poly_ntt) -void poly_ntt(poly *a); -#define poly_invntt_tomont HAETAE_NAMESPACE(poly_invntt_tomont) -void poly_invntt_tomont(poly *a); - -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/polyfix.c b/crypto_sign/haetae2/ref/polyfix.c deleted file mode 100644 index c453d293..00000000 --- a/crypto_sign/haetae2/ref/polyfix.c +++ /dev/null @@ -1,292 +0,0 @@ -#include "polyfix.h" -#include "decompose.h" -#include "math.h" -#include "ntt.h" -#include "params.h" -#include "reduce.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: polyfix_add - * - * Description: Add double polynomial and integer polynomial. - * No modular reduction is performed. - * - * Arguments: - polyfix *c: pointer to output double polynomial - * - const polyfix *a: pointer to first summand - * - const poly *b: pointer to second summand - **************************************************/ -void polyfix_add(polyfix *c, const polyfix *a, const poly *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + LN * b->coeffs[i]; -} - -/************************************************* - * Name: polyfixfix_sub - * - * Description: Subtract fixed polynomial and fixed polynomial. - * No modular reduction is performed. - * - * Arguments: - polyfix *c: pointer to output fixed polynomial - * - const polyfix *a: pointer to first summand - * - const polyfix *b: pointer to second summand - **************************************************/ -void polyfixfix_sub(polyfix *c, const polyfix *a, const polyfix *b) { - unsigned int i; - - for (i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; -} - -int32_t fix_round(int32_t num) { - num += (num >> 31) & (-LN + 1); - num += - LN / - 2; // total \floor(LN / 2) if positive, -\floor(LN / 2) + 1 if negative - return num / LN; -} - -/************************************************* - * Name: polyfix_round - * - * Description: rounds a fixed polynomial to integer polynomial - * - * Arguments: - poly *a: output integer polynomial - * - poly *b: input fixed polynomial - **************************************************/ -void polyfix_round(poly *a, const polyfix *b) { - unsigned i; - - for (i = 0; i < N; ++i) - a->coeffs[i] = fix_round(b->coeffs[i]); -} - -/**************************************************************/ -/********* Double Vectors of polynomials of length K **********/ -/**************************************************************/ - -/************************************************* - * Name: polyfixveck_add - * - * Description: Add vector to a vector of double polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first summand - * - const polyveck *v: pointer to second summand - **************************************************/ -void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixfixveck_sub - * - * Description: subtract vector to a vector of fixed polynomials of length k. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyfixveck *u: pointer to first summand - * - const polyfixveck *v: pointer to second summand - **************************************************/ -void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, - const polyfixveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixveck_double - * - * Description: Double vector of polynomials of length K. - * - * Arguments: - polyveck *b: pointer to output vector - * - polyveck *a: pointer to input vector - **************************************************/ -void polyfixveck_double(polyfixveck *b, const polyfixveck *a) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; -} - -/************************************************* - * Name: polyfixveck_round - * - * Description: rounds a fixed polynomial vector of length K - * - * Arguments: - polyveck *a: output integer polynomial vector - * - polyfixveck *b: input fixed polynomial vector - **************************************************/ -void polyfixveck_round(polyveck *a, const polyfixveck *b) { - unsigned i; - - for (i = 0; i < K; ++i) - polyfix_round(&a->vec[i], &b->vec[i]); -} - -/**************************************************************/ -/********* Double Vectors of polynomials of length L **********/ -/**************************************************************/ - -/************************************************* - * Name: polyfixvecl_add - * - * Description: Add vector to a vector of double polynomials of length L. - * No modular reduction is performed. - * - * Arguments: - polyvecl *w: pointer to output vector - * - const polyfixvecl *u: pointer to first summand - * - const polyvecl *v: pointer to second summand - **************************************************/ -void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - polyfix_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyfixfixvecl_sub - * - * Description: subtract vector to a vector of fixed polynomials of length l. - * No modular reduction is performed. - * - * Arguments: - polyvecl *w: pointer to output vector - * - const polyfixvecl *u: pointer to first summand - * - const polyfixvecl *v: pointer to second summand - **************************************************/ -void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, - const polyfixvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - polyfixfix_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} -/************************************************* - * Name: polyfixvecl_double - * - * Description: Double vector of polynomials of length L. - * - * Arguments: - polyveck *b: pointer to output vector - * - polyveck *a: pointer to input vector - **************************************************/ -void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a) { - unsigned int i, j; - - for (i = 0; i < L; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] = 2 * a->vec[i].coeffs[j]; -} - -/************************************************* - * Name: polyfixvecl_round - * - * Description: rounds a fixed polynomial vector of length L - * - * Arguments: - polyvecl *a: output integer polynomial vector - * - polyfixvecl *b: input fixed polynomial vector - **************************************************/ -void polyfixvecl_round(polyvecl *a, const polyfixvecl *b) { - unsigned i; - - for (i = 0; i < L; ++i) - polyfix_round(&a->vec[i], &b->vec[i]); -} - -/************************************************* - * Name: polyfixveclk_norm2 - * - * Description: Calculates L2 norm of a fixed point polynomial vector with - *length L + K The result is L2 norm * LN similar to the way polynomial is - *usually stored - * - * Arguments: - polyfixvecl *a: polynomial vector with length L to calculate - * norm - * - polyfixveck *a: polynomial vector with length K to calculate - * norm - **************************************************/ -uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < L; ++i) { - for (j = 0; j < N; ++j) - ret += (int64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; - } - - for (i = 0; i < K; ++i) { - for (j = 0; j < N; ++j) - ret += (int64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; - } - - return ret; -} - -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, - const uint8_t seed[CRHBYTES], - const uint16_t nonce) { - uint16_t ni = nonce; - uint64_t samples[N * (L + K)]; - fp96_76 sqsum, invsqrt; - unsigned int i, j; - uint8_t signs[N * (L + K) / 8]; - - do { - sqsum.limb48[0] = 0; - sqsum.limb48[1] = 0; - - sample_gauss_N(&samples[0], &signs[0], &sqsum, seed, ni++, N + 1); - sample_gauss_N(&samples[N], &signs[N / 8], &sqsum, seed, ni++, N + 1); - - for (i = 2; i < L + K; i++) - sample_gauss_N(&samples[N * i], &signs[N / 8 * i], &sqsum, seed, - ni++, N); - - // divide sqsum by 2 and approximate inverse square root - sqsum.limb48[0] += 1; // rounding - sqsum.limb48[0] >>= 1; - sqsum.limb48[0] += (sqsum.limb48[1] & 1) << 47; - sqsum.limb48[1] >>= 1; - sqsum.limb48[1] += sqsum.limb48[0] >> 48; - sqsum.limb48[0] &= (1ULL << 48) - 1; - fixpoint_newton_invsqrt(&invsqrt, &sqsum); - fixpoint_mul_high(&sqsum, &invsqrt, - (uint64_t)(B0 * LN + SQNM / 2) << (28 - 13)); - - for (i = 0; i < L; i++) { - for (j = 0; j < N; j++) - y1->vec[i].coeffs[j] = fixpoint_mul_rnd13( - samples[(i * N + j)], &sqsum, - (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); - } - for (i = L; i < K + L; i++) { - for (j = 0; j < N; j++) - y2->vec[i - L].coeffs[j] = fixpoint_mul_rnd13( - samples[(i * N + j)], &sqsum, - (signs[(i * N + j) / 8] >> ((i * N + j) % 8)) & 1); - } - } while (polyfixveclk_sqnorm2(y1, y2) > B0SQ * LN * LN); - - { - uint8_t tmp[CRHBYTES + 2]; - for (i = 0; i < CRHBYTES; i++) - { - tmp[i] = seed[i]; - } - tmp[CRHBYTES + 0] = ni >> 0; - tmp[CRHBYTES + 1] = ni >> 8; - shake256(b, 1, tmp, CRHBYTES+2); - } - - return ni; -} diff --git a/crypto_sign/haetae2/ref/polyfix.h b/crypto_sign/haetae2/ref/polyfix.h deleted file mode 100644 index 6177319c..00000000 --- a/crypto_sign/haetae2/ref/polyfix.h +++ /dev/null @@ -1,61 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLYFIX_H -#define HAETAE_POLYFIX_H - -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include "reduce.h" -#include - -typedef struct { - int32_t coeffs[N]; -} polyfix; - -#define polyfix_norm2 HAETAE_NAMESPACE(polyfix_norm2) -double polyfix_norm2(const polyfix *a); - -#define polyfix_round HAETAE_NAMESPACE(polyfix_round) -void polyfix_round(poly *a, const polyfix *b); - -#define polyfix_add HAETAE_NAMESPACE(polyfix_add) -void polyfix_add(polyfix *c, const polyfix *a, const poly *b); - -typedef struct { - polyfix vec[K]; -} polyfixveck; - -#define polyfixveck_add HAETAE_NAMESPACE(polyfixveck_add) -void polyfixveck_add(polyfixveck *w, const polyfixveck *u, const polyveck *v); -#define polyfixfixveck_sub HAETAE_NAMESPACE(polyfixfixveck_sub) -void polyfixfixveck_sub(polyfixveck *w, const polyfixveck *u, - const polyfixveck *v); -#define polyfixveck_double HAETAE_NAMESPACE(polyfixveck_double) -void polyfixveck_double(polyfixveck *b, const polyfixveck *a); - -#define polyfixveck_round HAETAE_NAMESPACE(polyfixveck_round) -void polyfixveck_round(polyveck *a, const polyfixveck *b); - -typedef struct { - polyfix vec[L]; -} polyfixvecl; - -#define polyfixvecl_add HAETAE_NAMESPACE(polyfixvecl_add) -void polyfixvecl_add(polyfixvecl *w, const polyfixvecl *u, const polyvecl *v); -#define polyfixfixvecl_sub HAETAE_NAMESPACE(polyfixfixvecl_sub) -void polyfixfixvecl_sub(polyfixvecl *w, const polyfixvecl *u, - const polyfixvecl *v); -#define polyfixvecl_double HAETAE_NAMESPACE(polyfixvecl_double) -void polyfixvecl_double(polyfixvecl *b, const polyfixvecl *a); - -#define polyfixvecl_round HAETAE_NAMESPACE(polyfixvecl_round) -void polyfixvecl_round(polyvecl *a, const polyfixvecl *b); - -#define polyfixveclk_sqnorm2 HAETAE_NAMESPACE(polyfixveclk_sqnorm2) -uint64_t polyfixveclk_sqnorm2(const polyfixvecl *a, const polyfixveck *b); - -#define polyfixveclk_sample_hyperball HAETAE_NAMESPACE(polyfixveclk_sample_hyperball) -uint16_t polyfixveclk_sample_hyperball(polyfixvecl *y1, polyfixveck *y2, uint8_t *b, const uint8_t seed[CRHBYTES], const uint16_t nonce); - -#endif -// clang-format on diff --git a/crypto_sign/haetae2/ref/polymat.c b/crypto_sign/haetae2/ref/polymat.c deleted file mode 100644 index 9802e98a..00000000 --- a/crypto_sign/haetae2/ref/polymat.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "polymat.h" -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include - -/************************************************* - * Name: polymat_expand - * - * Description: Implementation of ExpandA. Generates matrix A with uniformly - * random coefficients a_{i,j} by performing rejection - * sampling on the output stream of SHAKE128(rho|j|i) - * or AES256CTR(rho,j|i). - * - * Arguments: - polyvecm mat[K]: output matrix k \times m - * - const uint8_t rho[]: byte array containing seed rho - **************************************************/ -void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < M; ++j) - poly_uniform(&mat[i].vec[j + 1], rho, (i << 8) + j); -} - -/************************************************* - * Name: polymat_expand - * - * Description: Implementation of ExpandA. Generates matrix A with uniformly - * random coefficients a_{i,j} by performing rejection - * sampling on the output stream of SHAKE128(rho|j|i) - * or AES256CTR(rho,j|i). - * - * Arguments: - polyvecm mat[K]: output matrix k \times m - * - const uint8_t rho[]: byte array containing seed rho - **************************************************/ -void polymatkl_expand_frozen(polyvecl_frozen mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < M; ++j) - poly_uniform_frozen(&mat[i].vec[j + 1], rho, (i << 8) + j); -} - -/************************************************* - * Name: polymat_expand - * - * Description: Implementation of ExpandA. Generates matrix A with uniformly - * random coefficients a_{i,j} by performing rejection - * sampling on the output stream of SHAKE128(rho|j|i) - * or AES256CTR(rho,j|i). - * - * Arguments: - polyvecm mat[K]: output matrix k \times m - * - const uint8_t rho[]: byte array containing seed rho - **************************************************/ -void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < M; ++j) - poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); -} - -// doubles k * m sub-matrix of k * l mat -void polymatkl_double(polyvecl mat[K]) { - unsigned int i, j, k; - for (i = 0; i < K; ++i) { - for (j = 1; j < L; ++j) { - for (k = 0; k < N; ++k) { - mat[i].vec[j].coeffs[k] *= 2; - } - } - } -} - -// doubles k * m sub-matrix of k * l mat -void polymatkl_double_frozen(polyvecl_frozen mat[K]) { - unsigned int i, j, k; - for (i = 0; i < K; ++i) { - for (j = 1; j < L; ++j) { - for (k = 0; k < N; ++k) { - mat[i].vec[j].coeffs[k] = (uint16_t) freeze(2 * ((int32_t) mat[i].vec[j].coeffs[k])); - } - } - } -} - -void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], - const polyvecl *v) { - unsigned int i; - - for (i = 0; i < K; ++i) { - polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); - } -} - -void polymatkl_pointwise_montgomery_frozen(polyveck *t, const polyvecl_frozen mat[K], - const polyvecl *v) { - unsigned int i; - - for (i = 0; i < K; ++i) { - polyvecl_pointwise_acc_montgomery_frozen(&t->vec[i], &mat[i], v); - } -} - -void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], - const polyvecm *v) { - unsigned int i; - - for (i = 0; i < K; ++i) { - polyvecm_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); - } -} diff --git a/crypto_sign/haetae2/ref/polymat.h b/crypto_sign/haetae2/ref/polymat.h deleted file mode 100644 index 9aaa1e08..00000000 --- a/crypto_sign/haetae2/ref/polymat.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef HAETAE_POLYMAT_H -#define HAETAE_POLYMAT_H - -#include "params.h" -#include "poly.h" -#include "polyvec.h" -#include - -#define polymatkl_expand HAETAE_NAMESPACE(polymatkl_expand) -void polymatkl_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); - -#define polymatkl_expand_frozen HAETAE_NAMESPACE(polymatkl_expand_frozen) -void polymatkl_expand_frozen(polyvecl_frozen mat[K], const uint8_t rho[SEEDBYTES]); - -#define polymatkm_expand HAETAE_NAMESPACE(polymatkm_expand) -void polymatkm_expand(polyvecm mat[K], const uint8_t rho[SEEDBYTES]); - -#define polymatkm_pointwise_montgomery \ - HAETAE_NAMESPACE(polymatkm_pointwise_montgomery) -void polymatkm_pointwise_montgomery(polyveck *t, const polyvecm mat[K], - const polyvecm *v); - -#define polymatkl_pointwise_montgomery \ - HAETAE_NAMESPACE(polymatkl_pointwise_montgomery) -void polymatkl_pointwise_montgomery(polyveck *t, const polyvecl mat[K], - const polyvecl *v); - -#define polymatkl_pointwise_montgomery_frozen \ - HAETAE_NAMESPACE(polymatkl_pointwise_montgomery_frozen) -void polymatkl_pointwise_montgomery_frozen(polyveck *t, const polyvecl_frozen mat[K], - const polyvecl *v); - -#define polymatkl_double HAETAE_NAMESPACE(polymatkl_double) -void polymatkl_double(polyvecl mat[K]); - -#define polymatkl_double_frozen HAETAE_NAMESPACE(polymatkl_double_frozen) -void polymatkl_double_frozen(polyvecl_frozen mat[K]); - -#endif diff --git a/crypto_sign/haetae2/ref/polyvec.c b/crypto_sign/haetae2/ref/polyvec.c deleted file mode 100644 index cec77b3f..00000000 --- a/crypto_sign/haetae2/ref/polyvec.c +++ /dev/null @@ -1,566 +0,0 @@ -#include - -#include "decompose.h" -#include "fft.h" -#include "math.h" -#include "params.h" -#include "poly.h" -#include "polyvec.h" - -/**************************************************************/ -/************ Vectors of polynomials of length K **************/ -/**************************************************************/ - -/************************************************* - * Name: polyveck_add - * - * Description: Add vectors of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first summand - * - const polyveck *v: pointer to second summand - **************************************************/ -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyveck_sub - * - * Description: Subtract vectors of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - * - const polyveck *u: pointer to first input vector - * - const polyveck *v: pointer to second input vector to be - * subtracted from first input vector - **************************************************/ -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyveck_double - * - * Description: Double vector of polynomials of length K. - * No modular reduction is performed. - * - * Arguments: - polyveck *w: pointer to output vector - **************************************************/ -void polyveck_double(polyveck *b) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - b->vec[i].coeffs[j] *= 2; -} - -/************************************************* - * Name: polyveck_reduce2q - * - * Description: Reduce coefficients to 2q - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_reduce2q(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_reduce2q(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_freeze - * - * Description: For all coefficients of polynomials in vector of length K - * compute standard representative r = a mod^+ Q. - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_freeze(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_freeze(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_freeze2q - * - * Description: For all coefficients of polynomials in vector of length K - * compute standard representative r = a mod^+ 2Q. - * - * Arguments: - polyveck *v: pointer to input/output vector - **************************************************/ -void polyveck_freeze2q(polyveck *v) { - unsigned int i; - - for (i = 0; i < K; ++i) - poly_freeze2q(&v->vec[i]); -} - -/************************************************* - * Name: polyveck_expand - * - * Description: Sample a vector of polynomials with uniformly random - * coefficients in Zq by rejection sampling on the - * output stream from SHAKE128(seed|nonce) - * - * Arguments: - polyveck *v: pointer to output a vector of polynomials of - * length K - * - const uint8_t seed[]: byte array with seed of length SEEDBYTES - **************************************************/ -void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]) { - unsigned int i, nonce = (K << 8) + M; - for (i = 0; i < K; ++i) - poly_uniform(&v->vec[i], seed, nonce++); -} - -/************************************************* - * Name: polyvecmk_uniform_eta - * - * Description: Sample a vector of polynomials with uniformly random - * coefficients in [-ETA,ETA] by rejection sampling on the - * output stream from SHAKE256(seed|nonce) - * - * Arguments: - polyveck *v: pointer to output a vector of polynomials of - * length K - * - const uint8_t seed[]: byte array with seed of length CRHBYTES - * - uint16_t nonce: 2-byte nonce - **************************************************/ -void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, - const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i, n = nonce; - for (i = 0; i < M; i++) - poly_uniform_eta(&u->vec[i], seed, n++); - for (i = 0; i < K; ++i) - poly_uniform_eta(&v->vec[i], seed, n++); -} - -/************************************************* - * Name: polyveck_double_negate - * - * Description: multiply each coefficient with -2 - * - * Arguments: - polyveck *v: pointer to output vector of polynomials of - * length K - **************************************************/ -void polyveck_double_negate(polyveck *v) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; j++) - v->vec[i].coeffs[j] = - montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONT * -2); -} - -/************************************************* - * Name: polyveck_frommont - * - * Description: multiply each coefficient with MONT - * - * Arguments: - polyveck *v: pointer to output vector of polynomials of - * length K - **************************************************/ -void polyveck_frommont(polyveck *v) { - unsigned int i, j; - - for (i = 0; i < K; ++i) - for (j = 0; j < N; j++) - v->vec[i].coeffs[j] = - montgomery_reduce((int64_t)v->vec[i].coeffs[j] * MONTSQ); -} - -void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, - const poly *v) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_pointwise_montgomery(&w->vec[i], &u->vec[i], v); - } -} - -/************************************************* - * Name: polyveck_poly_fromcrt - * - * Description: recover polynomials from CRT domain, where all "mod q" - * polynomials are known and only the uppermost "mod 2" polynomial - * is non-zero - * - * Arguments: - polyveck *w: pointer to output vector of polynomials of - * length K - * - const polyveck *u: pointer to the input vector of polynomials - * of length K - * - const poly *v: pointer to the input polynomial ("mod 2") - **************************************************/ -void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v) { - unsigned int i; - - poly_fromcrt(&w->vec[0], &u->vec[0], v); - - for (i = 1; i < K; i++) { - poly_fromcrt0(&w->vec[i], &u->vec[i]); - } -} - -void polyveck_highbits_hint(polyveck *w, const polyveck *v) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - decompose_hint(&w->vec[i].coeffs[j], v->vec[i].coeffs[j]); - } - } -} - -void polyveck_pack_highbits(uint8_t *buf, const polyveck *v) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_pack_highbits(buf + i * POLY_HIGHBITS_PACKEDBYTES, &v->vec[i]); - } -} - -void polyveck_cneg(polyveck *v, const uint8_t b) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] *= 1 - 2 * b; - } - } -} - -void polyveck_caddDQ2ALPHA(polyveck *h) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - h->vec[i].coeffs[j] += - (h->vec[i].coeffs[j] >> 31) & ((DQ - 2) / ALPHA_HINT); - } - } -} - -void polyveck_csubDQ2ALPHA(polyveck *v) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] -= - ~((v->vec[i].coeffs[j] - (DQ - 2) / ALPHA_HINT) >> 31) & - ((DQ - 2) / ALPHA_HINT); - } - } -} - -void polyveck_mul_alpha(polyveck *v, const polyveck *u) { - unsigned int i, j; - for (i = 0; i < K; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] = u->vec[i].coeffs[j] * ALPHA_HINT; - } - } -} - -void polyveck_div2(polyveck *v) { - unsigned i, j; - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - v->vec[i].coeffs[j] >>= 1; -} - -void polyveck_caddq(polyveck *v) { - unsigned i, j; - for (i = 0; i < K; ++i) - for (j = 0; j < N; ++j) - v->vec[i].coeffs[j] = caddq(v->vec[i].coeffs[j]); -} - -void polyveck_decompose_vk(polyveck *v0, polyveck *v) { - for (int i = 0; i < K; i++) { - for (int j = 0; j < N; j++) { - v->vec[i].coeffs[j] = - decompose_vk(&v0->vec[i].coeffs[j], v->vec[i].coeffs[j]); - } - } -} - -void polyveck_ntt(polyveck *x) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_ntt(&x->vec[i]); - } -} - -void polyveck_invntt_tomont(polyveck *x) { - unsigned int i; - for (i = 0; i < K; i++) { - poly_invntt_tomont(&x->vec[i]); - } -} - -/************************************************* - * Name: polyveck_sqnorm2 - * - * Description: Calculates L2 norm of a polynomial vector with length k - * - * Arguments: - polyveck *b: polynomial vector with length k to calculate - *norm - **************************************************/ -uint64_t polyveck_sqnorm2(const polyveck *b) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < K; ++i) { - for (j = 0; j < N; ++j) { - ret += (uint64_t)b->vec[i].coeffs[j] * b->vec[i].coeffs[j]; - } - } - return ret; -} - -/**************************************************************/ -/************ Vectors of polynomials of length L **************/ -/**************************************************************/ - -/************************************************* - * Name: polyvecl_highbits - * - * Description: Compute HighBits of a vector of polynomials - * - * Arguments: - polyvecl *v2: pointer to output vector of polynomials of - * length L - * - const polyvecl *v: pointer to input vector of polynomials of - * length L - **************************************************/ -void polyvecl_highbits(polyvecl *v2, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - poly_highbits(&v2->vec[i], &v->vec[i]); -} - -/************************************************* - * Name: polyvecl_lowbits - * - * Description: Compute LowBits of a vector of polynomials - * - * Arguments: - polyvecl *v1: pointer to output vector of polynomials of - * length L - * - const polyvecl *v: pointer to input vector of polynomials of - * length L - **************************************************/ -void polyvecl_lowbits(polyvecl *v1, const polyvecl *v) { - unsigned int i; - - for (i = 0; i < L; ++i) - poly_lowbits(&v1->vec[i], &v->vec[i]); -} - -void polyvecl_cneg(polyvecl *v, const uint8_t b) { - unsigned int i, j; - for (i = 0; i < L; i++) { - for (j = 0; j < N; j++) { - v->vec[i].coeffs[j] *= 1 - 2 * b; - } - } -} - -/************************************************* - * Name: polyvecl_sqnorm2 - * - * Description: Calculates L2 norm of a polynomial vector with length l - * - * Arguments: - polyvecl *a: polynomial vector with length l to calculate - *norm - **************************************************/ -uint64_t polyvecl_sqnorm2(const polyvecl *a) { - unsigned int i, j; - uint64_t ret = 0; - - for (i = 0; i < L; ++i) { - for (j = 0; j < N; ++j) { - ret += (uint64_t)a->vec[i].coeffs[j] * a->vec[i].coeffs[j]; - } - } - - return ret; -} - -/************************************************* - * Name: polyvecl_pointwise_acc_montgomery - * - * Description: Pointwise multiply vectors of polynomials of length L, multiply - * resulting vector by 2^{-32} and add (accumulate) polynomials - * in it. Input/output vectors are in NTT domain representation. - * - * Arguments: - poly *w: output polynomial - * - const polyvecl *u: pointer to first input vector - * - const polyvecl *v: pointer to second input vector - **************************************************/ -void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, - const polyvecl *v) { - unsigned int i; - poly t; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -/************************************************* - * Name: polyvecl_pointwise_acc_montgomery_frozen - * - * Description: Pointwise multiply vectors of polynomials of length L, multiply - * resulting vector by 2^{-32} and add (accumulate) polynomials - * in it. Input/output vectors are in NTT domain representation. - * - * Arguments: - poly *w: output polynomial - * - const polyvecl *u: pointer to first input vector - * - const polyvecl *v: pointer to second input vector - **************************************************/ -void polyvecl_pointwise_acc_montgomery_frozen(poly *w, const polyvecl_frozen *u, - const polyvecl *v) { - unsigned int i; - poly t; - - poly_pointwise_montgomery_frozen(w, &u->vec[0], &v->vec[0]); - for (i = 1; i < L; ++i) { - poly_pointwise_montgomery_frozen(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -void polyvecl_ntt(polyvecl *x) { - unsigned int i; - for (i = 0; i < L; i++) { - poly_ntt(&x->vec[i]); - } -} - -/**************************************************************/ -/************ Vectors of polynomials of length M **************/ -/**************************************************************/ - -/************************************************* - * Name: polyvecm_pointwise_acc_montgomery - * - * Description: Pointwise multiply vectors of polynomials of length L, multiply - * resulting vector by 2^{-32} and add (accumulate) polynomials - * in it. Input/output vectors are in NTT domain representation. - * - * Arguments: - poly *w: output polynomial - * - const polyvecm *u: pointer to first input vector - * - const polyvecm *v: pointer to second input vector - **************************************************/ -void polyvecm_pointwise_acc_montgomery(poly *w, const polyvecm *u, - const polyvecm *v) { - unsigned int i; - poly t; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for (i = 1; i < M; ++i) { - poly_pointwise_montgomery(&t, &u->vec[i], &v->vec[i]); - poly_add(w, w, &t); - } -} - -void polyvecm_ntt(polyvecm *x) { - unsigned int i; - for (i = 0; i < M; i++) { - poly_ntt(&x->vec[i]); - } -} - -static inline void minmax(int32_t *x, int32_t *y) // taken from djbsort -{ - int32_t a = *x; - int32_t b = *y; - int32_t ab = b ^ a; - int32_t c = b - a; - c ^= ab & (c ^ b); - c >>= 31; - c &= ab; - *x = a ^ c; - *y = b ^ c; -} -static inline void minmaxmask(int32_t *x, int32_t *y, - int32_t *mask) // adapted from djbsort -{ - // If mask is -1, we perform the operation, else we do basically nothing. - // mask truth table: - // mask = 0 -> mask = 0, no swap is performed - // mask = -1, swap performed -> mask = 0 - // mask = -1, swap not performed -> mask = -1 - int32_t a = *x; - int32_t b = *y; - int32_t ab = (b ^ a) & *mask; - int32_t c = b - a; - c ^= ab & (c ^ b); - c >>= 31; - *mask &= ~c; - c &= ab; - *x = a ^ c; - *y = b ^ c; -} - -int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2) { - int32_t res = 0; - complex_fp32_16 input[FFT_N] = {0}; - int32_t sum[N] = {0}, bestm[N / TAU + 1] = {0}, min = 0; - - for (size_t i = 0; i < M; ++i) { - fft_bitrev(input, &s1->vec[i]); - fft(input); - - // cumulative sum - for (size_t j = 0; j < N; j++) { - sum[j] += complex_fp_sqabs(input[2 * j + 1]); - } - } - - for (size_t i = 0; i < K; ++i) { - fft_bitrev(input, &s2->vec[i]); - fft(input); - - // cumulative sum - for (size_t j = 0; j < N; j++) { - sum[j] += complex_fp_sqabs(input[2 * j + 1]); - } - } - - // compute max m - for (size_t i = 0; i < N / TAU + 1; ++i) { - bestm[i] = sum[i]; - } - for (size_t i = N / TAU + 1; i < N; i++) { - int32_t mask = -1; - for (size_t j = 0; j < N / TAU + 1; j++) { - minmaxmask(&sum[i], &bestm[j], &mask); - } - } - // find minimum in bestm - min = bestm[0]; - for (size_t i = 1; i < N / TAU + 1; i++) { - int32_t tmp = bestm[i]; - minmax(&min, &tmp); - } - // multiply all but the minimum by N mod TAU - for (size_t i = 0; i < N / TAU + 1; i++) { - int32_t fac = ((min - bestm[i]) >> 31); // all-ones if bestm[i] != min (TODO: impl specific behaviour) - fac = - (fac & (TAU)) ^ - ((~fac) & (N % TAU)); // fac = TAU for all != min and N%TAU for min - bestm[i] += - 0x10200; // add 1 for the "1 poly" in S, and prepare rounding - bestm[i] >>= 10; // round off 10 bits - bestm[i] *= fac; - res += bestm[i]; - } - - return (res + (1 << 5)) >> 6; // return rounded, squared value -} diff --git a/crypto_sign/haetae2/ref/polyvec.h b/crypto_sign/haetae2/ref/polyvec.h deleted file mode 100644 index 38659f0f..00000000 --- a/crypto_sign/haetae2/ref/polyvec.h +++ /dev/null @@ -1,138 +0,0 @@ -// clang-format off -#ifndef HAETAE_POLYVEC_H -#define HAETAE_POLYVEC_H - -#include "params.h" -#include "poly.h" -#include - -/* Vectors of polynomials of length K */ -typedef struct { - poly vec[K]; -} polyveck; - -#define polyveck_add HAETAE_NAMESPACE(polyveck_add) -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_sub HAETAE_NAMESPACE(polyveck_sub) -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_double HAETAE_NAMESPACE(polyveck_double) -void polyveck_double(polyveck *b); - -#define polyveck_reduce2q HAETAE_NAMESPACE(polyveck_reduce2q) -void polyveck_reduce2q(polyveck *v); -#define polyveck_freeze2q HAETAE_NAMESPACE(polyveck_freeze2q) -void polyveck_freeze2q(polyveck *v); -#define polyveck_freeze HAETAE_NAMESPACE(polyveck_freeze) -void polyveck_freeze(polyveck *v); - -#define polyveck_uniform_eta HAETAE_NAMESPACE(polyveck_uniform_eta) -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); -#define polyveck_expand HAETAE_NAMESPACE(polyveck_expand) -void polyveck_expand(polyveck *v, const uint8_t seed[SEEDBYTES]); - -#define polyveck_ntt HAETAE_NAMESPACE(polyveck_ntt) -void polyveck_ntt(polyveck *x); - -#define polyveck_invntt_tomont HAETAE_NAMESPACE(polyveck_invntt_tomont) -void polyveck_invntt_tomont(polyveck *x); - -#define polyveck_double_negate HAETAE_NAMESPACE(polyveck_double_negate) -void polyveck_double_negate(polyveck *x); - -#define polyveck_frommont HAETAE_NAMESPACE(polyveck_frommont) -void polyveck_frommont(polyveck *x); - -#define polyveck_poly_pointwise_montgomery HAETAE_NAMESPACE(polyveck_poly_pointwise_montgomery) -void polyveck_poly_pointwise_montgomery(polyveck *w, const polyveck *u, const poly *v); - -#define polyveck_poly_fromcrt HAETAE_NAMESPACE(polyveck_poly_fromcrt) -void polyveck_poly_fromcrt(polyveck *w, const polyveck *u, const poly *v); - -#define polyveck_highbits_hint HAETAE_NAMESPACE(polyveck_highbits_hint) -void polyveck_highbits_hint(polyveck *w, const polyveck *v); - -#define polyveck_pack_highbits HAETAE_NAMESPACE(polyveck_pack_highbits) -void polyveck_pack_highbits(uint8_t *buf, const polyveck *v); - -#define polyveck_cneg HAETAE_NAMESPACE(polyveck_cneg) -void polyveck_cneg(polyveck *v, const uint8_t b); - -#define polyveck_caddDQ2ALPHA HAETAE_NAMESPACE(polyveck_caddDQ2ALPHA) -void polyveck_caddDQ2ALPHA(polyveck *h); - -#define polyveck_csubDQ2ALPHA HAETAE_NAMESPACE(polyveck_csubDQ2ALPHA) -void polyveck_csubDQ2ALPHA(polyveck *v); - -#define polyveck_mul_alpha HAETAE_NAMESPACE(polyveck_mul_alpha) -void polyveck_mul_alpha(polyveck *v, const polyveck *u); - -#define polyveck_div2 HAETAE_NAMESPACE(polyveck_div2) -void polyveck_div2(polyveck *v); - -#define polyveck_caddq HAETAE_NAMESPACE(polyveck_caddq) -void polyveck_caddq(polyveck *v); - -#define polyveck_decompose_vk HAETAE_NAMESPACE(polyveck_decompose_vk) -void polyveck_decompose_vk(polyveck *v0, polyveck *v); - -#define polyveck_sqnorm2 HAETAE_NAMESPACE(polyveck_sqnorm2) -uint64_t polyveck_sqnorm2(const polyveck *b); - -/* Vectors of polynomials of length L */ -typedef struct { - poly vec[L]; -} polyvecl; - -/* Vectors of frozen polynomials of length L */ -typedef struct { - poly_frozen vec[L]; -} polyvecl_frozen; - -#define polyvecl_cneg HAETAE_NAMESPACE(polyvecl_cneg) -void polyvecl_cneg(polyvecl *v, const uint8_t b); - -#define polyvecl_sqnorm2 HAETAE_NAMESPACE(polyvecl_sqnorm2) -uint64_t polyvecl_sqnorm2(const polyvecl *a); - -#define polyvecl_ntt HAETAE_NAMESPACE(polyvecl_ntt) -void polyvecl_ntt(polyvecl *x); - -#define polyvecl_highbits HAETAE_NAMESPACE(polyvecl_highbits) -void polyvecl_highbits(polyvecl *v2, const polyvecl *v); -#define polyvecl_lowbits HAETAE_NAMESPACE(polyvecl_lowbits) -void polyvecl_lowbits(polyvecl *v2, const polyvecl *v); - -#define polyvecl_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery) -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v); - -#define polyvecl_pointwise_acc_montgomery_frozen HAETAE_NAMESPACE(polyvecl_pointwise_acc_montgomery_frozen) -void polyvecl_pointwise_acc_montgomery_frozen(poly *w, - const polyvecl_frozen *u, - const polyvecl *v); - -/* Vectors of polynomials of length M */ -typedef struct { - poly vec[M]; -} polyvecm; - -#define polyvecm_ntt HAETAE_NAMESPACE(polyvecm_ntt) -void polyvecm_ntt(polyvecm *x); - -#define polyvecmk_uniform_eta HAETAE_NAMESPACE(polyvecmk_uniform_eta) -void polyvecmk_uniform_eta(polyvecm *u, polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecm_pointwise_acc_montgomery HAETAE_NAMESPACE(polyvecm_pointwise_acc_montgomery) -void polyvecm_pointwise_acc_montgomery(poly *w, - const polyvecm *u, - const polyvecm *v); - -#define polyvecmk_sqsing_value HAETAE_NAMESPACE(polyvecmk_sqsing_value) -int64_t polyvecmk_sqsing_value(const polyvecm *s1, const polyveck *s2); - -#define polyvecmk_sing_value HAETAE_NAMESPACE(polyvecmk_sing_value) -int64_t polyvecmk_sing_value(const polyvecm *s1, const polyveck *s2); - -#endif -//clang-format on diff --git a/crypto_sign/haetae2/ref/rans_byte.h b/crypto_sign/haetae2/ref/rans_byte.h deleted file mode 100644 index 403ce20e..00000000 --- a/crypto_sign/haetae2/ref/rans_byte.h +++ /dev/null @@ -1,333 +0,0 @@ -// Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014 -// -// Not intended to be "industrial strength"; just meant to illustrate the general -// idea. - -#ifndef RANS_BYTE_HEADER -#define RANS_BYTE_HEADER - -#include - -#ifdef assert -#define RansAssert assert -#else -#define RansAssert(x) -#endif - -// READ ME FIRST: -// -// This is designed like a typical arithmetic coder API, but there's three -// twists you absolutely should be aware of before you start hacking: -// -// 1. You need to encode data in *reverse* - last symbol first. rANS works -// like a stack: last in, first out. -// 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give -// it a pointer to the *end* of your buffer (exclusive), and it will -// slowly move towards the beginning as more bytes are emitted. -// 3. Unlike basically any other entropy coder implementation you might -// have used, you can interleave data from multiple independent rANS -// encoders into the same bytestream without any extra signaling; -// you can also just write some bytes by yourself in the middle if -// you want to. This is in addition to the usual arithmetic encoder -// property of being able to switch models on the fly. Writing raw -// bytes can be useful when you have some data that you know is -// incompressible, and is cheaper than going through the rANS encode -// function. Using multiple rANS coders on the same byte stream wastes -// a few bytes compared to using just one, but execution of two -// independent encoders can happen in parallel on superscalar and -// Out-of-Order CPUs, so this can be *much* faster in tight decoding -// loops. -// -// This is why all the rANS functions take the write pointer as an -// argument instead of just storing it in some context struct. - -// -------------------------------------------------------------------------- - -// L ('l' in the paper) is the lower bound of our normalization interval. -// Between this and our byte-aligned emission, we use 31 (not 32!) bits. -// This is done intentionally because exact reciprocals for 31-bit uints -// fit in 32-bit uints: this permits some optimizations during encoding. -#define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval - -// State for a rANS encoder. Yep, that's all there is to it. -typedef uint32_t RansState; - -// Initialize a rANS encoder. -static inline void RansEncInit(RansState* r) -{ - *r = RANS_BYTE_L; -} - -// Renormalize the encoder. Internal function. -static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits) -{ - uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift. - if (x >= x_max) { - uint8_t* ptr = *pptr; - do { - *--ptr = (uint8_t) (x & 0xff); - x >>= 8; - } while (x >= x_max); - *pptr = ptr; - } - return x; -} - -// Encodes a single symbol with range start "start" and frequency "freq". -// All frequencies are assumed to sum to "1 << scale_bits", and the -// resulting bytes get written to ptr (which is updated). -// -// NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from -// beginning to end! Likewise, the output bytestream is written *backwards*: -// ptr starts pointing at the end of the output buffer and keeps decrementing. -static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - // renormalize - RansState x = RansEncRenorm(*r, pptr, freq, scale_bits); - - // x = C(s,x) - *r = ((x / freq) << scale_bits) + (x % freq) + start; -} - -// Flushes the rANS encoder. -static inline void RansEncFlush(RansState* r, uint8_t** pptr) -{ - uint32_t x = *r; - uint8_t* ptr = *pptr; - - ptr -= 4; - ptr[0] = (uint8_t) (x >> 0); - ptr[1] = (uint8_t) (x >> 8); - ptr[2] = (uint8_t) (x >> 16); - ptr[3] = (uint8_t) (x >> 24); - - *pptr = ptr; -} - -// Initializes a rANS decoder. -// Unlike the encoder, the decoder works forwards as you'd expect. -static inline int RansDecInit(RansState* r, uint8_t** pptr) -{ - uint32_t x; - uint8_t* ptr = *pptr; - - x = ptr[0] << 0; - x |= ptr[1] << 8; - x |= ptr[2] << 16; - x |= ptr[3] << 24; - if (x < RANS_BYTE_L || (RANS_BYTE_L << 8) <= x ) - return 1; // initial state out of range - - ptr += 4; - *pptr = ptr; - *r = x; - return 0; -} - -// Returns the current cumulative frequency (map it to a symbol yourself!) -static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits) -{ - return *r & ((1u << scale_bits) - 1); -} - -// Advances in the bit stream by "popping" a single symbol with range start -// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits", -// and the resulting bytes get written to ptr (which is updated). -static inline void RansDecAdvance(RansState* r, uint8_t** pptr, const uint8_t* end, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - uint32_t mask = (1u << scale_bits) - 1; - - // s, x = D(x) - uint32_t x = *r; - x = freq * (x >> scale_bits) + (x & mask) - start; - - // renormalize - if (x < RANS_BYTE_L && *pptr < end) { - uint8_t* ptr = *pptr; - do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L && ptr < end); - *pptr = ptr; - } - - *r = x; -} - -// -------------------------------------------------------------------------- - -// That's all you need for a full encoder; below here are some utility -// functions with extra convenience or optimizations. - -// Encoder symbol description -// This (admittedly odd) selection of parameters was chosen to make -// RansEncPutSymbol as cheap as possible. -typedef struct { - uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval - uint32_t rcp_freq; // Fixed-point reciprocal frequency - uint32_t bias; // Bias - uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq - uint16_t rcp_shift; // Reciprocal shift -} RansEncSymbol; - -// Decoder symbols are straightforward. -typedef struct { - uint16_t start; // Start of range. - uint16_t freq; // Symbol frequency. -} RansDecSymbol; - -// Initializes an encoder symbol to start "start" and frequency "freq" -static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - RansAssert(scale_bits <= 16); - RansAssert(start <= (1u << scale_bits)); - RansAssert(freq <= (1u << scale_bits) - start); - - // Say M := 1 << scale_bits. - // - // The original encoder does: - // x_new = (x/freq)*M + start + (x%freq) - // - // The fast encoder does (schematically): - // q = mul_hi(x, rcp_freq) >> rcp_shift (division) - // r = x - q*freq (remainder) - // x_new = q*M + bias + r (new x) - // plugging in r into x_new yields: - // x_new = bias + x + q*(M - freq) - // =: bias + x + q*cmpl_freq (*) - // - // and we can just precompute cmpl_freq. Now we just need to - // set up our parameters such that the original encoder and - // the fast encoder agree. - - s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; - s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq); - if (freq < 2) { - // freq=0 symbols are never valid to encode, so it doesn't matter what - // we set our values to. - // - // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately, - // our fixed-point reciprocal approximation can only multiply by values - // smaller than 1. - // - // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0. - // This gives: - // q = mul_hi(x, rcp_freq) >> rcp_shift - // = mul_hi(x, (1<<32) - 1)) >> 0 - // = floor(x - x/(2^32)) - // = x - 1 if 1 <= x < 2^32 - // and we know that x>0 (x=0 is never in a valid normalization interval). - // - // So we now need to choose the other parameters such that - // x_new = x*M + start - // plug it in: - // x*M + start (desired result) - // = bias + x + q*cmpl_freq (*) - // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq) - // = bias + 1 + (x - 1)*M - // = x*M + (bias + 1 - M) - // - // so we have start = bias + 1 - M, or equivalently - // bias = start + M - 1. - s->rcp_freq = ~0u; - s->rcp_shift = 0; - s->bias = start + (1 << scale_bits) - 1; - } else { - // Alverson, "Integer Division using reciprocals" - // shift=ceil(log2(freq)) - uint32_t shift = 0; - while (freq > (1u << shift)) - shift++; - - s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq); - s->rcp_shift = shift - 1; - - // With these values, 'q' is the correct quotient, so we - // have bias=start. - s->bias = start; - } -} - -// Initialize a decoder symbol to start "start" and frequency "freq" -static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq) -{ - RansAssert(start <= (1 << 16)); - RansAssert(freq <= (1 << 16) - start); - s->start = (uint16_t) start; - s->freq = (uint16_t) freq; -} - -// Encodes a given symbol. This is faster than straight RansEnc since we can do -// multiplications instead of a divide. -// -// See RansEncSymbolInit for a description of how this works. -static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym) -{ - RansAssert(sym->x_max != 0); // can't encode symbol with freq=0 - - // renormalize - uint32_t x = *r; - uint32_t x_max = sym->x_max; - if (x >= x_max) { - uint8_t* ptr = *pptr; - do { - *--ptr = (uint8_t) (x & 0xff); - x >>= 8; - } while (x >= x_max); - *pptr = ptr; - } - - // x = C(s,x) - // NOTE: written this way so we get a 32-bit "multiply high" when - // available. If you're on a 64-bit platform with cheap multiplies - // (e.g. x64), just bake the +32 into rcp_shift. - uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift; - *r = x + sym->bias + q * sym->cmpl_freq; -} - -// Equivalent to RansDecAdvance that takes a symbol. -static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, const uint8_t* end, RansDecSymbol const* sym, uint32_t scale_bits) -{ - RansDecAdvance(r, pptr, end, sym->start, sym->freq, scale_bits); -} - -// Advances in the bit stream by "popping" a single symbol with range start -// "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits". -// No renormalization or output happens. -static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits) -{ - uint32_t mask = (1u << scale_bits) - 1; - - // s, x = D(x) - uint32_t x = *r; - *r = freq * (x >> scale_bits) + (x & mask) - start; -} - -// Equivalent to RansDecAdvanceStep that takes a symbol. -static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits) -{ - RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits); -} - -// Renormalize. -static inline void RansDecRenorm(RansState* r, uint8_t** pptr) -{ - // renormalize - uint32_t x = *r; - if (x < RANS_BYTE_L) { - uint8_t* ptr = *pptr; - do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L); - *pptr = ptr; - } - - *r = x; -} - -// Verify final state -static inline int RansDecVerify(const RansState* const r) -{ - if (*r != RANS_BYTE_L) - { - return 1; // the final state is inconsistent with the initial state - } - return 0; -} - -#endif // RANS_BYTE_HEADER \ No newline at end of file diff --git a/crypto_sign/haetae2/ref/reduce.c b/crypto_sign/haetae2/ref/reduce.c deleted file mode 100644 index 55623734..00000000 --- a/crypto_sign/haetae2/ref/reduce.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "reduce.h" -#include "params.h" -#include - -/************************************************* - * Name: montgomery_reduce - * - * Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, - * compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. - * - * Arguments: - int64_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t montgomery_reduce(int64_t a) { - int32_t t; - - t = (int64_t)(int32_t)a * QINV; - t = (a - (int64_t)t * Q) >> 32; - return t; -} - -/************************************************* - * Name: caddq - * - * Description: Add Q if input coefficient is negative. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t caddq(int32_t a) { - a += (a >> 31) & Q; - return a; -} - -/************************************************* - * Name: freeze - * - * Description: For finite field element a, compute standard - * representative r = a mod^+ Q. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t freeze(int32_t a) { - int64_t t = (int64_t)a * QREC; - t = t >> 32; - t = a - t * Q; // -2Q < t < 2Q - t += (t >> 31) & DQ; // 0 <= t < 2Q - t -= ~((t - Q) >> 31) & Q; // 0 <= t < Q - return t; -} - -/************************************************* - * Name: reduce32_2q - * - * Description: compute reduction with 2Q - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t reduce32_2q(int32_t a) { - int64_t t = (int64_t)a * DQREC; - t >>= 32; - t = a - t * DQ; // -4Q < t < 4Q - t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q - t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q - t -= ~((t - Q) >> 31) & DQ; // centered representation - return (int32_t)t; -} - -/************************************************* - * Name: freeze2q - * - * Description: For finite field element a, compute standard - * representative r = a mod^+ 2Q. - * - * Arguments: - int32_t: finite field element a - * - * Returns r. - **************************************************/ -int32_t freeze2q(int32_t a) { - int64_t t = (int64_t)a * DQREC; - t >>= 32; - t = a - t * DQ; // -4Q < t < 4Q - t += (t >> 31) & (DQ * 2); // 0 <= t < 4Q - t -= ~((t - DQ) >> 31) & DQ; // 0 <= t < Q - return (int32_t)t; -} diff --git a/crypto_sign/haetae2/ref/reduce.h b/crypto_sign/haetae2/ref/reduce.h deleted file mode 100644 index 6f4a3a76..00000000 --- a/crypto_sign/haetae2/ref/reduce.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef HAETAE_REDUCE_H -#define HAETAE_REDUCE_H - -#include "params.h" -#include - -#define MONT 14321 // 2^32 % Q -#define MONTSQ 4214 // 2^64 % Q -#define QINV 940508161 // q^(-1) mod 2^32 -#define QREC 66575 // 2^32 / Q for Barrett -#define DQREC 33287 // 2^32 / DQ for Barrett - -#define montgomery_reduce HAETAE_NAMESPACE(montgomery_reduce) -int32_t montgomery_reduce(int64_t a); - -#define caddq HAETAE_NAMESPACE(caddq) -int32_t caddq(int32_t a); - -#define freeze HAETAE_NAMESPACE(freeze) -int32_t freeze(int32_t a); - -#define reduce32_2q HAETAE_NAMESPACE(reduce32_2q) -int32_t reduce32_2q(int32_t a); - -#define freeze2q HAETAE_NAMESPACE(freeze2q) -int32_t freeze2q(int32_t a); - -#endif diff --git a/crypto_sign/haetae2/ref/sampler.c b/crypto_sign/haetae2/ref/sampler.c deleted file mode 100644 index 35a3691f..00000000 --- a/crypto_sign/haetae2/ref/sampler.c +++ /dev/null @@ -1,302 +0,0 @@ -#include "sampler.h" -#include "fixpoint.h" -#include "symmetric.h" -#include - -/************************************************* - * Name: rej_uniform - * - * Description: Sample uniformly random coefficients in [0, Q-1] by - * performing rejection sampling on array of random bytes. - * - * Arguments: - int32_t *a: pointer to output array (allocated) - * - unsigned int len: number of coefficients to be sampled - * - const uint8_t *buf: array of random bytes - * - unsigned int buflen: length of array of random bytes - * - * Returns number of sampled coefficients. Can be smaller than len if not enough - * random bytes were given. - **************************************************/ -unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen) { - unsigned int ctr, pos; - uint32_t t; - - ctr = pos = 0; - while (ctr < len && pos + 2 <= buflen) { - t = buf[pos++]; - t |= (uint32_t)buf[pos++] << 8; - - if (t < Q) - a[ctr++] = t; - } - return ctr; -} - -/************************************************* - * Name: rej_uniform_frozen - * - * Description: Sample uniformly random coefficients in [0, Q-1] by - * performing rejection sampling on array of random bytes. - * - * Arguments: - int32_t *a: pointer to output array (allocated) - * - unsigned int len: number of coefficients to be sampled - * - const uint8_t *buf: array of random bytes - * - unsigned int buflen: length of array of random bytes - * - * Returns number of sampled coefficients. Can be smaller than len if not enough - * random bytes were given. - **************************************************/ -unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen) { - unsigned int ctr, pos; - uint16_t t; - - ctr = pos = 0; - while (ctr < len && pos + 2 <= buflen) { - t = buf[pos++]; - t |= (uint16_t)buf[pos++] << 8; - - if (t < Q) - a[ctr++] = t; - } - return ctr; -} - -/************************************************* - * Name: rej_eta - * - * Description: Sample uniformly random coefficients in [-ETA, ETA] by - * performing rejection sampling on array of random bytes. - * - * Arguments: - int32_t *a: pointer to output array (allocated) - * - unsigned int len: number of coefficients to be sampled - * - const uint8_t *buf: array of random bytes - * - unsigned int buflen: length of array of random bytes - * - * Returns number of sampled coefficients. Can be smaller than len if not enough - * random bytes were given. - **************************************************/ -static int32_t mod3(uint8_t t) { - int32_t r; - r = (t >> 4) + (t & 0xf); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -static int32_t mod3_leq26(uint8_t t) { - int32_t r; - r = (t >> 4) + (t & 0xf); - r = (r >> 2) + (r & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -static int32_t mod3_leq8(uint8_t t) { - int32_t r; - r = (t >> 2) + (t & 3); - r = (r >> 2) + (r & 3); - return r - (3 * (r >> 1)); -} -unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen) { - unsigned int ctr, pos; - - ctr = pos = 0; - while (ctr < len && pos < buflen) { -#if ETA == 1 - uint32_t t = buf[pos++]; - if (t < 243) { - // reduce mod 3 - a[ctr++] = mod3(t); - - if (ctr >= len) - break; - - t *= 171; // 171*3 = 1 mod 256 - t >>= 9; - a[ctr++] = mod3(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = mod3_leq26(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = mod3_leq8(t); - - if (ctr >= len) - break; - - t *= 171; - t >>= 9; - a[ctr++] = (int32_t)t - (int32_t)3 * (t >> 1); - } -#elif ETA == 2 - uint32_t t0, t1; - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - if (t0 < 15) { - t0 = t0 - (205 * t0 >> 10) * 5; - a[ctr++] = 2 - t0; - } - if (t1 < 15 && ctr < len) { - t1 = t1 - (205 * t1 >> 10) * 5; - a[ctr++] = 2 - t1; - } -#endif - } - return ctr; -} - -static uint64_t approx_exp(const uint64_t x) { - int64_t result; - result = -0x0000B6C6340925AELL; - result = ((smulh48(result, x) + (1LL << 2)) >> 3) + 0x0000B4BD4DF85227LL; - result = ((smulh48(result, x) + (1LL << 2)) >> 3) - 0x0000887F727491E2LL; - result = ((smulh48(result, x) + (1LL << 1)) >> 2) + 0x0000AAAA643C7E8DLL; - result = ((smulh48(result, x) + (1LL << 1)) >> 2) - 0x0000AAAAA98179E6LL; - result = ((smulh48(result, x) + 1LL) >> 1) + 0x0000FFFFFFFB2E7ALL; - result = ((smulh48(result, x) + 1LL) >> 1) - 0x0000FFFFFFFFF85FLL; - result = ((smulh48(result, x))) + 0x0000FFFFFFFFFFFCLL; - return result; -} - -#define CDTLEN 64 -static const uint32_t CDT[CDTLEN] = { - 3266, 6520, 9748, 12938, 16079, 19159, 22168, 25096, -27934, 30674, 33309, 35833, 38241, 40531, 42698, 44742, -46663, 48460, 50135, 51690, 53128, 54454, 55670, 56781, -57794, 58712, 59541, 60287, 60956, 61554, 62085, 62556, -62972, 63337, 63657, 63936, 64178, 64388, 64569, 64724, -64857, 64970, 65066, 65148, 65216, 65273, 65321, 65361, -65394, 65422, 65444, 65463, 65478, 65490, 65500, 65508, -65514, 65519, 65523, 65527, 65529, 65531, 65533, 65534 -}; - - -static uint64_t sample_gauss16(const uint64_t rand16) { - unsigned int i; - uint64_t r = 0; - for (i = 0; i < CDTLEN; i++) { - r += (((uint64_t)CDT[i] - rand16) >> 63) & 1; - } - return r; -} - -#define GAUSS_RAND (72 + 16 + 48) -#define GAUSS_RAND_BYTES ((GAUSS_RAND + 7) / 8) -static int sample_gauss_sigma76(uint64_t *r, fp96_76 *sqr, - const uint8_t rand[GAUSS_RAND_BYTES]) { - const uint64_t *rand_gauss16_ptr = (uint64_t *)rand, - *rand_rej_ptr = (uint64_t *)(&rand[2]); - const uint64_t rand_gauss16 = (*rand_gauss16_ptr) & ((1ULL << 16) - 1); - const uint64_t rand_rej = (*rand_rej_ptr) & ((1ULL << 48) - 1); - uint64_t x, exp_in; - fp96_76 y; - - // sample x - x = sample_gauss16(rand_gauss16); - - // y := append x to y - // leave 16 bit for carries - y.limb48[0] = rand[8] | ((uint64_t)rand[9] << 8) | - ((uint64_t)rand[10] << 16) | ((uint64_t)rand[11] << 24) | - ((uint64_t)rand[12] << 32) | ((uint64_t)rand[13] << 40); - y.limb48[1] = - rand[14] | ((uint64_t)rand[15] << 8) | ((uint64_t)rand[16] << 16) | - (x << 24); - - // r := round y - *r = (y.limb48[0] >> 15) ^ (y.limb48[1] << 33); - *r += 1; // rounding - *r >>= 1; - - // sqr := y*y - fixpoint_square(sqr, &y); - - // sqr[1] = y^2 >> (76+48) // 34 bit - // sqr[0] = (y^2 >> 76) & ((1UL<<48)-1) // 48 bit - // exp_in := sqr - ((x*x) << 68) - exp_in = sqr->limb48[1] - ((x*x) << (68 - 48)); - exp_in <<= 20; - exp_in |= sqr->limb48[0] >> 28; - exp_in += 1; // rounding - exp_in >>= 1; - - return ((((int64_t)(rand_rej ^ - (rand_rej & 1)) // set lowest bit to zero in order to - // use it for rejection if sample==0 - - (int64_t)approx_exp(exp_in)) >> - 63) // reject with prob 1-approx_exp(exp_in) - & (((*r | -*r) >> 63) | rand_rej)) & - 1; // if the sample is zero, clear the return value with prob 1/2 -} - -int sample_gauss(uint64_t *r, fp96_76 *sqsum, const uint8_t *buf, const size_t buflen, const size_t len, const int dont_write_last) -{ - const uint8_t *pos = buf; - fp96_76 sqr; - size_t bytecnt = buflen, coefcnt = 0, cnt = 0; - int accepted; - uint64_t dummy; - - while (coefcnt < len) { - if (bytecnt < GAUSS_RAND_BYTES) { - renormalize(sqsum); - return coefcnt; - } - - if (dont_write_last && coefcnt == len-1) - { - accepted = sample_gauss_sigma76(&dummy, &sqr, pos); - } else { - accepted = sample_gauss_sigma76(&r[coefcnt], &sqr, pos); - } - cnt += 1; - coefcnt += accepted; - pos += GAUSS_RAND_BYTES; - bytecnt -= GAUSS_RAND_BYTES; - - sqsum->limb48[0] += sqr.limb48[0] & -(int64_t)accepted; - sqsum->limb48[1] += sqr.limb48[1] & -(int64_t)accepted; - } - - renormalize(sqsum); - return len; -} - -#define POLY_HYPERBALL_BUFLEN (GAUSS_RAND_BYTES * N) -#define POLY_HYPERBALL_NBLOCKS ((POLY_HYPERBALL_BUFLEN + STREAM256_BLOCKBYTES - 1) / STREAM256_BLOCKBYTES) -void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, - const uint8_t seed[CRHBYTES], const uint16_t nonce, - const size_t len) { - uint8_t buf[POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES]; - size_t bytecnt, coefcnt, firstflag = 1; - stream256_state state; - stream256_init(&state, seed, nonce); - - stream256_squeezeblocks(buf, POLY_HYPERBALL_NBLOCKS, &state); - for (size_t i = 0; i < len / 8; i++) { - signs[i] = buf[i]; - } - bytecnt = POLY_HYPERBALL_NBLOCKS * STREAM256_BLOCKBYTES - len / 8; - coefcnt = sample_gauss(r, sqsum, buf + len / 8, bytecnt, len, len%N); - while (coefcnt < len) { - size_t off = bytecnt % GAUSS_RAND_BYTES; - for (size_t i = 0; i < off; i++) { - buf[i] = buf[bytecnt + len/8*firstflag - off + i]; - } - stream256_squeezeblocks(buf + off, 1, &state); - bytecnt = STREAM256_BLOCKBYTES + off; - - coefcnt += sample_gauss(r + coefcnt, sqsum, buf, bytecnt, len - coefcnt, len%N); - firstflag = 0; - } -} diff --git a/crypto_sign/haetae2/ref/sampler.h b/crypto_sign/haetae2/ref/sampler.h deleted file mode 100644 index 4f636775..00000000 --- a/crypto_sign/haetae2/ref/sampler.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef HAETAE_SAMPLER_H -#define HAETAE_SAMPLER_H - -#include "fixpoint.h" -#include "params.h" -#include "reduce.h" -#include - -#define rej_uniform HAETAE_NAMESPACE(rej_uniform) -unsigned int rej_uniform(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen); -#define rej_uniform_frozen HAETAE_NAMESPACE(rej_uniform_frozen) -unsigned int rej_uniform_frozen(uint16_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen); -#define rej_eta HAETAE_NAMESPACE(rej_eta) -unsigned int rej_eta(int32_t *a, unsigned int len, const uint8_t *buf, - unsigned int buflen); - -#define sample_gauss_N HAETAE_NAMESPACE(sample_gauss_N) -void sample_gauss_N(uint64_t *r, uint8_t *signs, fp96_76 *sqsum, - const uint8_t seed[CRHBYTES], const uint16_t nonce, - const size_t len); - -#endif diff --git a/crypto_sign/haetae2/ref/sign.c b/crypto_sign/haetae2/ref/sign.c deleted file mode 100644 index 438ae415..00000000 --- a/crypto_sign/haetae2/ref/sign.c +++ /dev/null @@ -1,456 +0,0 @@ -#include "sign.h" -#include "packing.h" -#include "params.h" -#include "poly.h" -#include "polyfix.h" -#include "polymat.h" -#include "polyvec.h" -#include "randombytes.h" -#include "symmetric.h" -#include -#include -#include -#include - -/************************************************* - * Name: crypto_sign_keypair - * - * Description: Generates public and private key. - * - * Arguments: - uint8_t *pk: pointer to output public key (allocated - * array of CRYPTO_PUBLICKEYBYTES bytes) - * - uint8_t *sk: pointer to output private key (allocated - * array of CRYPTO_SECRETKEYBYTES bytes) - * - * Returns 0 (success) - **************************************************/ - -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES] = {0}; - uint16_t nonce = 0; - const uint8_t *rhoprime, *sigma, *key; - polyvecm A[K], s1, s1hat; - polyveck b, s2; -#if D > 0 - polyveck a, b0; -#else - polyveck s2hat; -#endif - xof256_state state; - - // Get entropy \rho - randombytes(seedbuf, SEEDBYTES); - - // Sample seeds with entropy \rho - xof256_absorbe_once(&state, seedbuf, SEEDBYTES); - xof256_squeeze(seedbuf, 2 * SEEDBYTES + CRHBYTES, &state); - - rhoprime = seedbuf; - sigma = rhoprime + SEEDBYTES; - key = sigma + CRHBYTES; - - // Expand Matrix A0 and vector a - polymatkm_expand(A, rhoprime); - -#if D > 0 - /********************************************** - * If there is rounding (D > 0), we need another polyveck a. - * Then, b = a + A0 * s1 + s2 and the lower D bits are - * rounded from b. The lower D bits are subsequently - * subtracted from s2. - **********************************************/ - polyveck_expand(&a, rhoprime); - -reject: - // Sample secret vectors s1 and s2 - polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); - nonce += M + K; - - // b = a + A0 * s1 + s2 mod q - s1hat = s1; - polyvecm_ntt(&s1hat); - polymatkm_pointwise_montgomery(&b, A, &s1hat); - polyveck_invntt_tomont(&b); - polyveck_add(&b, &b, &s2); - polyveck_add(&b, &b, &a); - polyveck_freeze(&b); - - // round off D bits - polyveck_decompose_vk(&b0, &b); - polyveck_sub(&s2, &s2, &b0); - - int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); - if (squared_singular_value > GAMMA * GAMMA * N) { - goto reject; - } -#else - /********************************************** - * If there is no rounding (D == 0), we store - * -2b directly in NTT domain into the public key. - **********************************************/ -reject: - // Sample secret vectors s1 and s2 - polyvecmk_uniform_eta(&s1, &s2, sigma, nonce); - nonce += M + K; - int64_t squared_singular_value = polyvecmk_sqsing_value(&s1, &s2); - if (squared_singular_value > GAMMA * GAMMA * N) { - goto reject; - } - - // b = A0 * s1 + s2 mod q - s1hat = s1; - s2hat = s2; - polyvecm_ntt(&s1hat); - polyveck_ntt(&s2hat); - polymatkm_pointwise_montgomery(&b, A, &s1hat); - polyveck_frommont(&b); - polyveck_add(&b, &b, &s2hat); - polyveck_double_negate(&b); - polyveck_caddq(&b); // directly compute and store NTT(-2b) -#endif - - pack_pk(pk, &b, rhoprime); - pack_sk(sk, pk, &s1, &s2, key); - - return 0; -} - -/************************************************* - * Name: crypto_sign_signature - * - * Description: Computes signature. - * - * Arguments: - uint8_t *sig: pointer to output signature (of length - * CRYPTO_BYTES) - * - size_t *siglen: pointer to output length of signature - * - uint8_t *m: pointer to message to be signed - * - size_t mlen: length of message - * - uint8_t *sk: pointer to bit-packed secret key - * - * Returns 0 (success) - **************************************************/ -int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, - size_t mlen, const uint8_t *sk) { - - uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t seedbuf[CRHBYTES] = {0}, key[SEEDBYTES] = {0}; - uint8_t mu[SEEDBYTES] = {0}; - uint8_t b = 0; // one bit - uint16_t counter = 0; - uint64_t reject1, reject2; - - polyvecm s1; - polyvecl_frozen A1[K]; - polyveck s2, highbits, Ay; - poly c, chat, z1rnd0, lsb; - - vecl1 vl1; // cs1, z1rnd, z1tmp - vecl2 vl2; // y1, lb_z1 - veck1 vk1; // cs2, z2rnd, z2tmp - veck2 vk2; // y2, htmp - vecl3 vl3; // z1, hb_z1 - veck3 vk3; // z2, h - - - xof256_state state; - - unsigned int i; - - // Unpack secret key - unpack_sk(A1, &s1, &s2, key, sk); - - xof256_absorbe_twice(&state, sk, CRYPTO_PUBLICKEYBYTES, m, mlen); - xof256_squeeze(mu, SEEDBYTES, &state); - xof256_absorbe_twice(&state, key, SEEDBYTES, mu, SEEDBYTES); - xof256_squeeze(seedbuf, CRHBYTES, &state); - - polyvecm_ntt(&s1); - polyveck_ntt(&s2); - -reject: - - /*------------------ 1. Sample y1 and y2 from hyperball ------------------*/ - counter = polyfixveclk_sample_hyperball(&vl2.y1, &vk2.y2, &b, seedbuf, counter); - - /*------------------- 2. Compute a chanllenge c --------------------------*/ - // Round y1 and y2 - polyfixvecl_round(&vl1.z1rnd, &vl2.y1); - polyfixveck_round(&vk1.z2rnd, &vk2.y2); - - // A * round(y) mod q = A1 * round(y1) + 2 * round(y2) mod q - z1rnd0 = vl1.z1rnd.vec[0]; - polyvecl_ntt(&vl1.z1rnd); - polymatkl_pointwise_montgomery_frozen(&Ay, A1, &vl1.z1rnd); - polyveck_invntt_tomont(&Ay); - polyveck_double(&vk1.z2rnd); - polyveck_add(&Ay, &Ay, &vk1.z2rnd); - - // recover A * round(y) mod 2q - polyveck_poly_fromcrt(&Ay, &Ay, &z1rnd0); - polyveck_freeze2q(&Ay); - - // HighBits of (A * round(y) mod 2q) - polyveck_highbits_hint(&highbits, &Ay); - - // LSB(round(y_0) * j) - poly_lsb(&lsb, &z1rnd0); - - // Pack HighBits of A * round(y) mod 2q and LSB of round(y0) - polyveck_pack_highbits(buf, &highbits); - poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &lsb); - - // c = challenge(highbits, lsb, mu) - poly_challenge(&c, buf, mu); - - /*------------------- 3. Compute z = y + (-1)^b c * s --------------------*/ - // cs = c * s = c * (si1 || s2) - vl1.cs1.vec[0] = c; - chat = c; - poly_ntt(&chat); - - for (i = 1; i < L; ++i) { - poly_pointwise_montgomery(&vl1.cs1.vec[i], &chat, &s1.vec[i - 1]); - poly_invntt_tomont(&vl1.cs1.vec[i]); - } - polyveck_poly_pointwise_montgomery(&vk1.cs2, &s2, &chat); - polyveck_invntt_tomont(&vk1.cs2); - - // z = y + (-1)^b cs = z1 + z2 - polyvecl_cneg(&vl1.cs1, b & 1); - polyveck_cneg(&vk1.cs2, b & 1); - polyfixvecl_add(&vl3.z1, &vl2.y1, &vl1.cs1); - polyfixveck_add(&vk3.z2, &vk2.y2, &vk1.cs2); - - // reject if norm(z) >= B' - reject1 = ((uint64_t)B1SQ * LN * LN - polyfixveclk_sqnorm2(&vl3.z1, &vk3.z2)) >> 63; - reject1 &= 1; - - polyfixvecl_double(&vl1.z1tmp, &vl3.z1); - polyfixveck_double(&vk1.z2tmp, &vk3.z2); - - polyfixfixvecl_sub(&vl1.z1tmp, &vl1.z1tmp, &vl2.y1); - polyfixfixveck_sub(&vk1.z2tmp, &vk1.z2tmp, &vk2.y2); - - // reject if norm(2z-y) < B and b' = 0 - reject2 = - (polyfixveclk_sqnorm2(&vl1.z1tmp, &vk1.z2tmp) - (uint64_t)B0SQ * LN * LN) >> 63; - reject2 &= 1; - reject2 &= (b & 0x2) >> 1; - - if (reject1 | reject2) { - goto reject; - } - - /*------------------- 4. Make a hint -------------------------------------*/ - // Round z1 and z2 - polyfixvecl_round(&vl1.z1rnd, &vl3.z1); - polyfixveck_round(&vk1.z2rnd, &vk3.z2); - - // recover A1 * round(z1) - qcj mod 2q - polyveck_double(&vk1.z2rnd); - polyveck_sub(&vk2.htmp, &Ay, &vk1.z2rnd); - polyveck_freeze2q(&vk2.htmp); - - // HighBits of (A * round(z) - qcj mod 2q) and (A1 * round(z1) - qcj mod 2q) - polyveck_highbits_hint(&vk2.htmp, &vk2.htmp); - polyveck_sub(&vk3.h, &highbits, &vk2.htmp); - polyveck_caddDQ2ALPHA(&vk3.h); - - /*------------------ Decompose(z1) and Pack signature -------------------*/ - polyvecl_lowbits(&vl2.lb_z1, &vl1.z1rnd); // TODO do this in one function together! - polyvecl_highbits(&vl3.hb_z1, &vl1.z1rnd); - - if (pack_sig(sig, &c, &vl2.lb_z1, &vl3.hb_z1, - &vk3.h)) { // reject if signature is too big - goto reject; - } - *siglen = CRYPTO_BYTES; - - return 0; -} - -/************************************************* - * Name: crypto_sign - * - * Description: Compute signed message. - * - * Arguments: - uint8_t *sm: pointer to output signed message (allocated - * array with CRYPTO_BYTES + mlen bytes), - * can be equal to m - * - size_t *smlen: pointer to output length of signed - * message - * - const uint8_t *m: pointer to message to be signed - * - size_t mlen: length of message - * - const uint8_t *sk: pointer to bit-packed secret key - * - * Returns 0 (success) - **************************************************/ -int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, - const uint8_t *sk) { - size_t i; - - for (i = 0; i < mlen; ++i) - sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); - *smlen += mlen; - return 0; -} - -/************************************************* - * Name: crypto_sign_verify - * - * Description: Verifies signature. - * - * Arguments: - uint8_t *m: pointer to input signature - * - size_t siglen: length of signature - * - const uint8_t *m: pointer to message - * - size_t mlen: length of message - * - const uint8_t *pk: pointer to bit-packed public key - * - * Returns 0 if signature could be verified correctly and -1 otherwise - **************************************************/ -int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, - size_t mlen, const uint8_t *pk) { - unsigned int i; - uint8_t buf[POLYVECK_HIGHBITS_PACKEDBYTES + POLYC_PACKEDBYTES] = {0}; - uint8_t rhoprime[SEEDBYTES] = {0}, mu[SEEDBYTES]; - uint64_t sqnorm2; - polyvecl A1[K], z1; - polyveck b, highbits, h, z2, w; -#if D > 0 - polyveck a; -#endif - poly c, cprime, wprime; - - xof256_state state; - - // Check signature length - if (siglen != CRYPTO_BYTES) { - return -1; - } - - // Unpack public key - unpack_pk(&b, rhoprime, pk); - - // Unpack signature and Check conditions -- A1 is used only as intermediate - // buffer for the low bits - if (unpack_sig(&c, A1, &z1, &h, sig)) { - return -1; - } - - // Compose z1 out of HighBits(z1) and LowBits(z1) - for (i = 0; i < L; ++i) { - poly_compose(&z1.vec[i], &z1.vec[i], &A1[0].vec[i]); - } - - /*------------------- 1. Recover A1 --------------------------------------*/ - // A1 = (-2b + qj || 2 * A0) - polymatkl_expand(A1, rhoprime); - polymatkl_double(A1); -#if D == 1 - polyveck_expand(&a, rhoprime); - polyveck_double(&b); - polyveck_sub(&b, &a, &b); - polyveck_double(&b); - polyveck_ntt(&b); -#elif D == 0 - // no action required as b already contains -2b in NTT domain -#else -#error "Not yet implemented." -#endif - - for (i = 0; i < K; ++i) { - A1[i].vec[0] = b.vec[i]; - } - - /*------------------- 2. Compute \tilde{z}_2 -----------------------------*/ - // compute squared norm of z1 and w' before NTT - sqnorm2 = polyvecl_sqnorm2(&z1); - poly_sub(&wprime, &z1.vec[0], &c); - poly_lsb(&wprime, &wprime); - - // A1 * round(z1) - qcj mod q - polyvecl_ntt(&z1); - polymatkl_pointwise_montgomery(&highbits, A1, &z1); - polyveck_invntt_tomont(&highbits); - - // recover A1 * round(z1) - qcj mod 2q - polyveck_poly_fromcrt(&highbits, &highbits, &wprime); - polyveck_freeze2q(&highbits); - - // recover w1 - polyveck_highbits_hint(&w, &highbits); - polyveck_add(&w, &w, &h); - polyveck_csubDQ2ALPHA(&w); - - // recover \tilde{z}_2 mod q - polyveck_mul_alpha(&z2, &w); - polyveck_sub(&z2, &z2, &highbits); - poly_add(&z2.vec[0], &z2.vec[0], &wprime); - polyveck_reduce2q(&z2); - polyveck_div2(&z2); - - // check final norm of \tilde{z} - if (sqnorm2 + polyveck_sqnorm2(&z2) > B2SQ) { - return -1; - } - - /*------------------- 3. Compute c_seed' and Compare ---------------------*/ - - // Pack highBits(A * round(z) - qcj mod 2q) and h' - polyveck_pack_highbits(buf, &w); - poly_pack_lsb(buf + POLYVECK_HIGHBITS_PACKEDBYTES, &wprime); - - xof256_absorbe_twice(&state, pk, CRYPTO_PUBLICKEYBYTES, m, mlen); - xof256_squeeze(mu, SEEDBYTES, &state); - - // c_seed = H(HighBits(A * y mod 2q), LSB(round(y0) * j), M) - poly_challenge(&cprime, buf, mu); - - for (i = 0; i < N; ++i) { - if (c.coeffs[i] != cprime.coeffs[i]) { - return -1; - } - } - return 0; -} - -/************************************************* - * Name: crypto_sign_open - * - * Description: Verify signed message. - * - * Arguments: - uint8_t *m: pointer to output message (allocated - * array with smlen bytes), can be equal to sm - * - size_t *mlen: pointer to output length of message - * - const uint8_t *sm: pointer to signed message - * - size_t smlen: length of signed message - * - const uint8_t *pk: pointer to bit-packed public key - * - * Returns 0 if signed message could be verified correctly and -1 otherwise - **************************************************/ -int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, - const uint8_t *pk) { - size_t i; - - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - if (crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) - goto badsig; - else { - /* All good, copy msg, return 0 */ - for (i = 0; i < *mlen; ++i) - m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - for (i = 0; i < smlen; ++i) - m[i] = 0; - - return -1; -} diff --git a/crypto_sign/haetae2/ref/sign.h b/crypto_sign/haetae2/ref/sign.h deleted file mode 100644 index 27e6a0b0..00000000 --- a/crypto_sign/haetae2/ref/sign.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef HAETAE_SIGN_H -#define HAETAE_SIGN_H - -#include "params.h" -#include "poly.h" -#include "polymat.h" -#include "polyvec.h" -#include "polyfix.h" -#include -#include - -typedef union { - polyvecl cs1; - polyvecl z1rnd; - polyfixvecl z1tmp; -} vecl1; - -typedef union { - polyveck cs2; - polyveck z2rnd; - polyfixveck z2tmp; -} veck1; - -typedef union { - polyfixvecl y1; - polyvecl lb_z1; -} vecl2; - -typedef union { - polyfixveck y2; - polyveck htmp; -} veck2; - -typedef union { - polyfixvecl z1; - polyvecl hb_z1; -} vecl3; - -typedef union { - polyfixveck z2; - polyveck h; -} veck3; - -#define crypto_sign_keypair HAETAE_NAMESPACE(keypair) -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -#define crypto_sign_signature HAETAE_NAMESPACE(signature) -int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, - size_t mlen, const uint8_t *sk); - -#define crypto_sign HAETAE_NAMESPACE(sign) -int crypto_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, - const uint8_t *sk); - -#define crypto_sign_verify HAETAE_NAMESPACE(verify) -int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, - size_t mlen, const uint8_t *pk); - -#define crypto_sign_open HAETAE_NAMESPACE(open) -int crypto_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif // HAETAE_SIGN_H diff --git a/crypto_sign/haetae2/ref/symmetric-shake.c b/crypto_sign/haetae2/ref/symmetric-shake.c deleted file mode 100644 index c9aeadd3..00000000 --- a/crypto_sign/haetae2/ref/symmetric-shake.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "fips202.h" -#include "params.h" -#include "symmetric.h" -#include - -void haetae_shake128_stream_init(keccak_state *state, - const uint8_t seed[SEEDBYTES], - uint16_t nonce) { - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake128_init(state); - shake128_absorb(state, seed, SEEDBYTES); - shake128_absorb(state, t, 2); - shake128_finalize(state); -} - -void haetae_shake256_stream_init(keccak_state *state, - const uint8_t seed[CRHBYTES], uint16_t nonce) { - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake256_init(state); - shake256_absorb(state, seed, CRHBYTES); - shake256_absorb(state, t, 2); - shake256_finalize(state); -} - -void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, - size_t in1len, const uint8_t *in2, - size_t in2len) { - shake256_init(state); - shake256_absorb(state, in1, in1len); - shake256_absorb(state, in2, in2len); - shake256_finalize(state); -} diff --git a/crypto_sign/haetae2/ref/symmetric.h b/crypto_sign/haetae2/ref/symmetric.h deleted file mode 100644 index b3b9c37d..00000000 --- a/crypto_sign/haetae2/ref/symmetric.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include "params.h" -#include -#include "fips202.h" - -// Cryptographic XOF function: shake256 -typedef keccak_state xof256_state; - -#define haetae_shake256_absorb_twice \ - HAETAE_NAMESPACE(haetae_shake256_absorb_twice) -void haetae_shake256_absorb_twice(keccak_state *state, const uint8_t *in1, - size_t in1len, const uint8_t *in2, size_t in2len); - -#define XOF256_BLOCKBYTES SHAKE256_RATE - -#define xof256_absorbe_once(STATE, IN, IN_LEN) \ - shake256_absorb_once(STATE, IN, IN_LEN) -#define xof256_absorbe_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) \ - haetae_shake256_absorb_twice(STATE, IN, IN_LEN, IN2, IN2_LEN) -#define xof256_squeeze(OUT, OUT_LEN, STATE) \ - shake256_squeeze(OUT, OUT_LEN, STATE) -#define xof256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - - -// Stream function: aes256 or shake128|256 -#ifdef HAETAE_USE_AES // stream: aes256 - -#include "aes256ctr.h" - -typedef aes256ctr_ctx stream128_state; -typedef aes256ctr_ctx stream256_state; - -#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES -#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES - -#define stream128_init(STATE, SEED, NONCE) \ - aes256ctr_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - aes256ctr_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#else // stream: shake128 and shake256 - -typedef keccak_state stream128_state; -typedef keccak_state stream256_state; - -#define haetae_shake128_stream_init \ - HAETAE_NAMESPACE(haetae_shake128_stream_init) -void haetae_shake128_stream_init(keccak_state *state, - const uint8_t seed[SEEDBYTES], uint16_t nonce); - -#define haetae_shake256_stream_init \ - HAETAE_NAMESPACE(haetae_shake256_stream_init) -void haetae_shake256_stream_init(keccak_state *state, - const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define STREAM128_BLOCKBYTES SHAKE128_RATE -#define STREAM256_BLOCKBYTES SHAKE256_RATE - -#define stream128_init(STATE, SEED, NONCE) \ - haetae_shake128_stream_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - haetae_shake256_stream_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#endif // stream - -#endif //SYMMETRIC_H - diff --git a/crypto_sign/haetae3/ref/api.h b/crypto_sign/haetae3/ref/api.h deleted file mode 120000 index 4cc87a52..00000000 --- a/crypto_sign/haetae3/ref/api.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/api.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/config.h b/crypto_sign/haetae3/ref/config.h deleted file mode 100644 index 0748c077..00000000 --- a/crypto_sign/haetae3/ref/config.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define HAETAE_MODE 3 - -#if HAETAE_MODE == 2 -#define CRYPTO_ALGNAME "HAETAE2" -#define HAETAE_NAMESPACETOP haetae2 -#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s -#elif HAETAE_MODE == 3 -#define CRYPTO_ALGNAME "HAETAE3" -#define HAETAE_NAMESPACETOP haetae3 -#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s -#elif HAETAE_MODE == 5 -#define CRYPTO_ALGNAME "HAETAE5" -#define HAETAE_NAMESPACETOP haetae5 -#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s -#endif /* if HAETAE_MODE */ - -#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae3/ref/decompose.c b/crypto_sign/haetae3/ref/decompose.c deleted file mode 120000 index ae51ead9..00000000 --- a/crypto_sign/haetae3/ref/decompose.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/decompose.h b/crypto_sign/haetae3/ref/decompose.h deleted file mode 120000 index a0b57cf4..00000000 --- a/crypto_sign/haetae3/ref/decompose.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/encoding.c b/crypto_sign/haetae3/ref/encoding.c deleted file mode 120000 index 21c33670..00000000 --- a/crypto_sign/haetae3/ref/encoding.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/encoding.h b/crypto_sign/haetae3/ref/encoding.h deleted file mode 120000 index 228432d5..00000000 --- a/crypto_sign/haetae3/ref/encoding.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fft.c b/crypto_sign/haetae3/ref/fft.c deleted file mode 120000 index 1e693203..00000000 --- a/crypto_sign/haetae3/ref/fft.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fft.h b/crypto_sign/haetae3/ref/fft.h deleted file mode 120000 index 8c5f7907..00000000 --- a/crypto_sign/haetae3/ref/fft.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fips202.c b/crypto_sign/haetae3/ref/fips202.c deleted file mode 120000 index 40cab797..00000000 --- a/crypto_sign/haetae3/ref/fips202.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fips202.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fips202.h b/crypto_sign/haetae3/ref/fips202.h deleted file mode 120000 index 3845b909..00000000 --- a/crypto_sign/haetae3/ref/fips202.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fixpoint.c b/crypto_sign/haetae3/ref/fixpoint.c deleted file mode 120000 index 600c0752..00000000 --- a/crypto_sign/haetae3/ref/fixpoint.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/fixpoint.h b/crypto_sign/haetae3/ref/fixpoint.h deleted file mode 120000 index 03e6dbb7..00000000 --- a/crypto_sign/haetae3/ref/fixpoint.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/ntt.c b/crypto_sign/haetae3/ref/ntt.c deleted file mode 120000 index 1ac478b5..00000000 --- a/crypto_sign/haetae3/ref/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/ntt.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/ntt.h b/crypto_sign/haetae3/ref/ntt.h deleted file mode 120000 index 7d8e40b8..00000000 --- a/crypto_sign/haetae3/ref/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/ntt.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/packing.c b/crypto_sign/haetae3/ref/packing.c deleted file mode 120000 index ed6a9940..00000000 --- a/crypto_sign/haetae3/ref/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/packing.h b/crypto_sign/haetae3/ref/packing.h deleted file mode 120000 index bfc421a3..00000000 --- a/crypto_sign/haetae3/ref/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/params.h b/crypto_sign/haetae3/ref/params.h deleted file mode 120000 index b60911fc..00000000 --- a/crypto_sign/haetae3/ref/params.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/params.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/poly.c b/crypto_sign/haetae3/ref/poly.c deleted file mode 120000 index 39ccd75a..00000000 --- a/crypto_sign/haetae3/ref/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/poly.h b/crypto_sign/haetae3/ref/poly.h deleted file mode 120000 index a0ae8937..00000000 --- a/crypto_sign/haetae3/ref/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyfix.c b/crypto_sign/haetae3/ref/polyfix.c deleted file mode 120000 index f5de52c9..00000000 --- a/crypto_sign/haetae3/ref/polyfix.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyfix.h b/crypto_sign/haetae3/ref/polyfix.h deleted file mode 120000 index 7fd30789..00000000 --- a/crypto_sign/haetae3/ref/polyfix.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polymat.c b/crypto_sign/haetae3/ref/polymat.c deleted file mode 120000 index 6437bb1a..00000000 --- a/crypto_sign/haetae3/ref/polymat.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polymat.h b/crypto_sign/haetae3/ref/polymat.h deleted file mode 120000 index 65909b3d..00000000 --- a/crypto_sign/haetae3/ref/polymat.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyvec.c b/crypto_sign/haetae3/ref/polyvec.c deleted file mode 120000 index a030bd9f..00000000 --- a/crypto_sign/haetae3/ref/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/polyvec.h b/crypto_sign/haetae3/ref/polyvec.h deleted file mode 120000 index 8737f657..00000000 --- a/crypto_sign/haetae3/ref/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/rans_byte.h b/crypto_sign/haetae3/ref/rans_byte.h deleted file mode 120000 index 56556a86..00000000 --- a/crypto_sign/haetae3/ref/rans_byte.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/reduce.c b/crypto_sign/haetae3/ref/reduce.c deleted file mode 120000 index 2c77824c..00000000 --- a/crypto_sign/haetae3/ref/reduce.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/reduce.h b/crypto_sign/haetae3/ref/reduce.h deleted file mode 120000 index beaf84e3..00000000 --- a/crypto_sign/haetae3/ref/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sampler.c b/crypto_sign/haetae3/ref/sampler.c deleted file mode 120000 index db1ffe9c..00000000 --- a/crypto_sign/haetae3/ref/sampler.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sampler.h b/crypto_sign/haetae3/ref/sampler.h deleted file mode 120000 index cca2cc46..00000000 --- a/crypto_sign/haetae3/ref/sampler.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sign.c b/crypto_sign/haetae3/ref/sign.c deleted file mode 120000 index f7d3d524..00000000 --- a/crypto_sign/haetae3/ref/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/sign.h b/crypto_sign/haetae3/ref/sign.h deleted file mode 120000 index 7c12c2e9..00000000 --- a/crypto_sign/haetae3/ref/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/symmetric-shake.c b/crypto_sign/haetae3/ref/symmetric-shake.c deleted file mode 120000 index 0cf4a8a9..00000000 --- a/crypto_sign/haetae3/ref/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae3/ref/symmetric.h b/crypto_sign/haetae3/ref/symmetric.h deleted file mode 120000 index 341745bf..00000000 --- a/crypto_sign/haetae3/ref/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/symmetric.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/api.h b/crypto_sign/haetae5/ref/api.h deleted file mode 120000 index 4cc87a52..00000000 --- a/crypto_sign/haetae5/ref/api.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/api.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/config.h b/crypto_sign/haetae5/ref/config.h deleted file mode 100644 index 4ea01f5c..00000000 --- a/crypto_sign/haetae5/ref/config.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define HAETAE_MODE 5 - -#if HAETAE_MODE == 2 -#define CRYPTO_ALGNAME "HAETAE2" -#define HAETAE_NAMESPACETOP haetae2 -#define HAETAE_NAMESPACE(s) cryptolab_haetae2_##s -#elif HAETAE_MODE == 3 -#define CRYPTO_ALGNAME "HAETAE3" -#define HAETAE_NAMESPACETOP haetae3 -#define HAETAE_NAMESPACE(s) cryptolab_haetae3_##s -#elif HAETAE_MODE == 5 -#define CRYPTO_ALGNAME "HAETAE5" -#define HAETAE_NAMESPACETOP haetae5 -#define HAETAE_NAMESPACE(s) cryptolab_haetae5_##s -#endif /* if HAETAE_MODE */ - -#endif /* CONFIG_H */ diff --git a/crypto_sign/haetae5/ref/decompose.c b/crypto_sign/haetae5/ref/decompose.c deleted file mode 120000 index ae51ead9..00000000 --- a/crypto_sign/haetae5/ref/decompose.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/decompose.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/decompose.h b/crypto_sign/haetae5/ref/decompose.h deleted file mode 120000 index a0b57cf4..00000000 --- a/crypto_sign/haetae5/ref/decompose.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/decompose.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/encoding.c b/crypto_sign/haetae5/ref/encoding.c deleted file mode 120000 index 21c33670..00000000 --- a/crypto_sign/haetae5/ref/encoding.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/encoding.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/encoding.h b/crypto_sign/haetae5/ref/encoding.h deleted file mode 120000 index 228432d5..00000000 --- a/crypto_sign/haetae5/ref/encoding.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/encoding.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fft.c b/crypto_sign/haetae5/ref/fft.c deleted file mode 120000 index 1e693203..00000000 --- a/crypto_sign/haetae5/ref/fft.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fft.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fft.h b/crypto_sign/haetae5/ref/fft.h deleted file mode 120000 index 8c5f7907..00000000 --- a/crypto_sign/haetae5/ref/fft.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fft.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fips202.c b/crypto_sign/haetae5/ref/fips202.c deleted file mode 120000 index 40cab797..00000000 --- a/crypto_sign/haetae5/ref/fips202.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fips202.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fips202.h b/crypto_sign/haetae5/ref/fips202.h deleted file mode 120000 index 3845b909..00000000 --- a/crypto_sign/haetae5/ref/fips202.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fips202.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fixpoint.c b/crypto_sign/haetae5/ref/fixpoint.c deleted file mode 120000 index 600c0752..00000000 --- a/crypto_sign/haetae5/ref/fixpoint.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fixpoint.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/fixpoint.h b/crypto_sign/haetae5/ref/fixpoint.h deleted file mode 120000 index 03e6dbb7..00000000 --- a/crypto_sign/haetae5/ref/fixpoint.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/fixpoint.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/ntt.c b/crypto_sign/haetae5/ref/ntt.c deleted file mode 120000 index 1ac478b5..00000000 --- a/crypto_sign/haetae5/ref/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/ntt.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/ntt.h b/crypto_sign/haetae5/ref/ntt.h deleted file mode 120000 index 7d8e40b8..00000000 --- a/crypto_sign/haetae5/ref/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/ntt.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/packing.c b/crypto_sign/haetae5/ref/packing.c deleted file mode 120000 index ed6a9940..00000000 --- a/crypto_sign/haetae5/ref/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/packing.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/packing.h b/crypto_sign/haetae5/ref/packing.h deleted file mode 120000 index bfc421a3..00000000 --- a/crypto_sign/haetae5/ref/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/packing.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/params.h b/crypto_sign/haetae5/ref/params.h deleted file mode 120000 index b60911fc..00000000 --- a/crypto_sign/haetae5/ref/params.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/params.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/poly.c b/crypto_sign/haetae5/ref/poly.c deleted file mode 120000 index 39ccd75a..00000000 --- a/crypto_sign/haetae5/ref/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/poly.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/poly.h b/crypto_sign/haetae5/ref/poly.h deleted file mode 120000 index a0ae8937..00000000 --- a/crypto_sign/haetae5/ref/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/poly.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyfix.c b/crypto_sign/haetae5/ref/polyfix.c deleted file mode 120000 index f5de52c9..00000000 --- a/crypto_sign/haetae5/ref/polyfix.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyfix.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyfix.h b/crypto_sign/haetae5/ref/polyfix.h deleted file mode 120000 index 7fd30789..00000000 --- a/crypto_sign/haetae5/ref/polyfix.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyfix.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polymat.c b/crypto_sign/haetae5/ref/polymat.c deleted file mode 120000 index 6437bb1a..00000000 --- a/crypto_sign/haetae5/ref/polymat.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polymat.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polymat.h b/crypto_sign/haetae5/ref/polymat.h deleted file mode 120000 index 65909b3d..00000000 --- a/crypto_sign/haetae5/ref/polymat.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polymat.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyvec.c b/crypto_sign/haetae5/ref/polyvec.c deleted file mode 120000 index a030bd9f..00000000 --- a/crypto_sign/haetae5/ref/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyvec.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/polyvec.h b/crypto_sign/haetae5/ref/polyvec.h deleted file mode 120000 index 8737f657..00000000 --- a/crypto_sign/haetae5/ref/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/polyvec.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/rans_byte.h b/crypto_sign/haetae5/ref/rans_byte.h deleted file mode 120000 index 56556a86..00000000 --- a/crypto_sign/haetae5/ref/rans_byte.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/rans_byte.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/reduce.c b/crypto_sign/haetae5/ref/reduce.c deleted file mode 120000 index 2c77824c..00000000 --- a/crypto_sign/haetae5/ref/reduce.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/reduce.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/reduce.h b/crypto_sign/haetae5/ref/reduce.h deleted file mode 120000 index beaf84e3..00000000 --- a/crypto_sign/haetae5/ref/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/reduce.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sampler.c b/crypto_sign/haetae5/ref/sampler.c deleted file mode 120000 index db1ffe9c..00000000 --- a/crypto_sign/haetae5/ref/sampler.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sampler.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sampler.h b/crypto_sign/haetae5/ref/sampler.h deleted file mode 120000 index cca2cc46..00000000 --- a/crypto_sign/haetae5/ref/sampler.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sampler.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sign.c b/crypto_sign/haetae5/ref/sign.c deleted file mode 120000 index f7d3d524..00000000 --- a/crypto_sign/haetae5/ref/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sign.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/sign.h b/crypto_sign/haetae5/ref/sign.h deleted file mode 120000 index 7c12c2e9..00000000 --- a/crypto_sign/haetae5/ref/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/sign.h \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/symmetric-shake.c b/crypto_sign/haetae5/ref/symmetric-shake.c deleted file mode 120000 index 0cf4a8a9..00000000 --- a/crypto_sign/haetae5/ref/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/haetae5/ref/symmetric.h b/crypto_sign/haetae5/ref/symmetric.h deleted file mode 120000 index 341745bf..00000000 --- a/crypto_sign/haetae5/ref/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../haetae2/ref/symmetric.h \ No newline at end of file From 8dc5cf5c7a63d2919af90b3527d6d1f929677fa7 Mon Sep 17 00:00:00 2001 From: Marco Palumbi Date: Thu, 7 Dec 2023 12:59:00 +0000 Subject: [PATCH 047/107] add PERK for all NIST levels Implementation compliant with version v1.1 of 2023/10/16 https://pqc-perk.org/ --- crypto_sign/perk-128-fast-3/m4/README | 43 ++ crypto_sign/perk-128-fast-3/m4/api.h | 26 + crypto_sign/perk-128-fast-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-128-fast-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-128-fast-3/m4/common.c | 102 ++++ crypto_sign/perk-128-fast-3/m4/common.h | 109 ++++ crypto_sign/perk-128-fast-3/m4/common_s.c | 42 ++ .../perk-128-fast-3/m4/crypto_memset.c | 7 + .../perk-128-fast-3/m4/crypto_memset.h | 18 + .../perk-128-fast-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-128-fast-3/m4/djbsort.c | 12 + crypto_sign/perk-128-fast-3/m4/djbsort.h | 16 + crypto_sign/perk-128-fast-3/m4/keygen.c | 51 ++ crypto_sign/perk-128-fast-3/m4/keygen.h | 21 + crypto_sign/perk-128-fast-3/m4/parameters.h | 43 ++ crypto_sign/perk-128-fast-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-128-fast-3/m4/parsing.h | 75 +++ .../perk-128-fast-3/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-128-fast-3/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-128-fast-3/m4/permutation.c | 91 ++++ crypto_sign/perk-128-fast-3/m4/permutation.h | 111 ++++ crypto_sign/perk-128-fast-3/m4/sign.c | 119 +++++ crypto_sign/perk-128-fast-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-128-fast-3/m4/signature.h | 64 +++ crypto_sign/perk-128-fast-3/m4/sort.c | 128 +++++ crypto_sign/perk-128-fast-3/m4/symmetric.c | 51 ++ crypto_sign/perk-128-fast-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-128-fast-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-128-fast-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-128-fast-3/m4/verbose.c | 131 +++++ crypto_sign/perk-128-fast-3/m4/verbose.h | 129 +++++ crypto_sign/perk-128-fast-3/m4/verify.c | 160 ++++++ crypto_sign/perk-128-fast-3/m4/verify.h | 26 + crypto_sign/perk-128-fast-5/m4/README | 43 ++ crypto_sign/perk-128-fast-5/m4/api.h | 26 + crypto_sign/perk-128-fast-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-128-fast-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-128-fast-5/m4/common.c | 102 ++++ crypto_sign/perk-128-fast-5/m4/common.h | 109 ++++ crypto_sign/perk-128-fast-5/m4/common_s.c | 42 ++ .../perk-128-fast-5/m4/crypto_memset.c | 7 + .../perk-128-fast-5/m4/crypto_memset.h | 18 + .../perk-128-fast-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-128-fast-5/m4/djbsort.c | 12 + crypto_sign/perk-128-fast-5/m4/djbsort.h | 16 + crypto_sign/perk-128-fast-5/m4/keygen.c | 51 ++ crypto_sign/perk-128-fast-5/m4/keygen.h | 21 + crypto_sign/perk-128-fast-5/m4/parameters.h | 43 ++ crypto_sign/perk-128-fast-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-128-fast-5/m4/parsing.h | 75 +++ .../perk-128-fast-5/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-128-fast-5/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-128-fast-5/m4/permutation.c | 91 ++++ crypto_sign/perk-128-fast-5/m4/permutation.h | 111 ++++ crypto_sign/perk-128-fast-5/m4/sign.c | 119 +++++ crypto_sign/perk-128-fast-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-128-fast-5/m4/signature.h | 64 +++ crypto_sign/perk-128-fast-5/m4/sort.c | 128 +++++ crypto_sign/perk-128-fast-5/m4/symmetric.c | 51 ++ crypto_sign/perk-128-fast-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-128-fast-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-128-fast-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-128-fast-5/m4/verbose.c | 131 +++++ crypto_sign/perk-128-fast-5/m4/verbose.h | 129 +++++ crypto_sign/perk-128-fast-5/m4/verify.c | 160 ++++++ crypto_sign/perk-128-fast-5/m4/verify.h | 26 + crypto_sign/perk-128-short-3/m4/README | 43 ++ crypto_sign/perk-128-short-3/m4/api.h | 26 + crypto_sign/perk-128-short-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-128-short-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-128-short-3/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-128-short-3/m4/bn.h | 117 +++++ crypto_sign/perk-128-short-3/m4/common.c | 102 ++++ crypto_sign/perk-128-short-3/m4/common.h | 109 ++++ crypto_sign/perk-128-short-3/m4/common_s.c | 42 ++ .../perk-128-short-3/m4/crypto_memset.c | 7 + .../perk-128-short-3/m4/crypto_memset.h | 18 + .../perk-128-short-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-128-short-3/m4/djbsort.c | 12 + crypto_sign/perk-128-short-3/m4/djbsort.h | 16 + crypto_sign/perk-128-short-3/m4/keygen.c | 51 ++ crypto_sign/perk-128-short-3/m4/keygen.h | 21 + crypto_sign/perk-128-short-3/m4/parameters.h | 46 ++ crypto_sign/perk-128-short-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-128-short-3/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-128-short-3/m4/permutation.c | 91 ++++ crypto_sign/perk-128-short-3/m4/permutation.h | 111 ++++ .../perk-128-short-3/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-128-short-3/m4/sign.c | 119 +++++ crypto_sign/perk-128-short-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-128-short-3/m4/signature.h | 64 +++ crypto_sign/perk-128-short-3/m4/sort.c | 128 +++++ crypto_sign/perk-128-short-3/m4/symmetric.c | 51 ++ crypto_sign/perk-128-short-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-128-short-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-128-short-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-128-short-3/m4/verbose.c | 131 +++++ crypto_sign/perk-128-short-3/m4/verbose.h | 129 +++++ crypto_sign/perk-128-short-3/m4/verify.c | 160 ++++++ crypto_sign/perk-128-short-3/m4/verify.h | 26 + crypto_sign/perk-128-short-5/m4/README | 43 ++ crypto_sign/perk-128-short-5/m4/api.h | 26 + crypto_sign/perk-128-short-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-128-short-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-128-short-5/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-128-short-5/m4/bn.h | 117 +++++ crypto_sign/perk-128-short-5/m4/common.c | 102 ++++ crypto_sign/perk-128-short-5/m4/common.h | 109 ++++ crypto_sign/perk-128-short-5/m4/common_s.c | 42 ++ .../perk-128-short-5/m4/crypto_memset.c | 7 + .../perk-128-short-5/m4/crypto_memset.h | 18 + .../perk-128-short-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-128-short-5/m4/djbsort.c | 12 + crypto_sign/perk-128-short-5/m4/djbsort.h | 16 + crypto_sign/perk-128-short-5/m4/keygen.c | 51 ++ crypto_sign/perk-128-short-5/m4/keygen.h | 21 + crypto_sign/perk-128-short-5/m4/parameters.h | 46 ++ crypto_sign/perk-128-short-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-128-short-5/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-128-short-5/m4/permutation.c | 91 ++++ crypto_sign/perk-128-short-5/m4/permutation.h | 111 ++++ .../perk-128-short-5/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-128-short-5/m4/sign.c | 119 +++++ crypto_sign/perk-128-short-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-128-short-5/m4/signature.h | 64 +++ crypto_sign/perk-128-short-5/m4/sort.c | 128 +++++ crypto_sign/perk-128-short-5/m4/symmetric.c | 51 ++ crypto_sign/perk-128-short-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-128-short-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-128-short-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-128-short-5/m4/verbose.c | 131 +++++ crypto_sign/perk-128-short-5/m4/verbose.h | 129 +++++ crypto_sign/perk-128-short-5/m4/verify.c | 160 ++++++ crypto_sign/perk-128-short-5/m4/verify.h | 26 + crypto_sign/perk-192-fast-3/m4/README | 43 ++ crypto_sign/perk-192-fast-3/m4/api.h | 26 + crypto_sign/perk-192-fast-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-192-fast-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-192-fast-3/m4/common.c | 102 ++++ crypto_sign/perk-192-fast-3/m4/common.h | 109 ++++ crypto_sign/perk-192-fast-3/m4/common_s.c | 42 ++ .../perk-192-fast-3/m4/crypto_memset.c | 7 + .../perk-192-fast-3/m4/crypto_memset.h | 18 + .../perk-192-fast-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-192-fast-3/m4/djbsort.c | 12 + crypto_sign/perk-192-fast-3/m4/djbsort.h | 16 + crypto_sign/perk-192-fast-3/m4/keygen.c | 51 ++ crypto_sign/perk-192-fast-3/m4/keygen.h | 21 + crypto_sign/perk-192-fast-3/m4/parameters.h | 43 ++ crypto_sign/perk-192-fast-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-192-fast-3/m4/parsing.h | 75 +++ .../perk-192-fast-3/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-192-fast-3/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-192-fast-3/m4/permutation.c | 91 ++++ crypto_sign/perk-192-fast-3/m4/permutation.h | 111 ++++ crypto_sign/perk-192-fast-3/m4/sign.c | 119 +++++ crypto_sign/perk-192-fast-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-192-fast-3/m4/signature.h | 64 +++ crypto_sign/perk-192-fast-3/m4/sort.c | 128 +++++ crypto_sign/perk-192-fast-3/m4/symmetric.c | 51 ++ crypto_sign/perk-192-fast-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-192-fast-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-192-fast-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-192-fast-3/m4/verbose.c | 131 +++++ crypto_sign/perk-192-fast-3/m4/verbose.h | 129 +++++ crypto_sign/perk-192-fast-3/m4/verify.c | 160 ++++++ crypto_sign/perk-192-fast-3/m4/verify.h | 26 + crypto_sign/perk-192-fast-5/m4/README | 43 ++ crypto_sign/perk-192-fast-5/m4/api.h | 26 + crypto_sign/perk-192-fast-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-192-fast-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-192-fast-5/m4/common.c | 102 ++++ crypto_sign/perk-192-fast-5/m4/common.h | 109 ++++ crypto_sign/perk-192-fast-5/m4/common_s.c | 42 ++ .../perk-192-fast-5/m4/crypto_memset.c | 7 + .../perk-192-fast-5/m4/crypto_memset.h | 18 + .../perk-192-fast-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-192-fast-5/m4/djbsort.c | 12 + crypto_sign/perk-192-fast-5/m4/djbsort.h | 16 + crypto_sign/perk-192-fast-5/m4/keygen.c | 51 ++ crypto_sign/perk-192-fast-5/m4/keygen.h | 21 + crypto_sign/perk-192-fast-5/m4/parameters.h | 43 ++ crypto_sign/perk-192-fast-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-192-fast-5/m4/parsing.h | 75 +++ .../perk-192-fast-5/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-192-fast-5/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-192-fast-5/m4/permutation.c | 91 ++++ crypto_sign/perk-192-fast-5/m4/permutation.h | 111 ++++ crypto_sign/perk-192-fast-5/m4/sign.c | 119 +++++ crypto_sign/perk-192-fast-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-192-fast-5/m4/signature.h | 64 +++ crypto_sign/perk-192-fast-5/m4/sort.c | 128 +++++ crypto_sign/perk-192-fast-5/m4/symmetric.c | 51 ++ crypto_sign/perk-192-fast-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-192-fast-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-192-fast-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-192-fast-5/m4/verbose.c | 131 +++++ crypto_sign/perk-192-fast-5/m4/verbose.h | 129 +++++ crypto_sign/perk-192-fast-5/m4/verify.c | 160 ++++++ crypto_sign/perk-192-fast-5/m4/verify.h | 26 + crypto_sign/perk-192-short-3/m4/README | 43 ++ crypto_sign/perk-192-short-3/m4/api.h | 26 + crypto_sign/perk-192-short-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-192-short-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-192-short-3/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-192-short-3/m4/bn.h | 117 +++++ crypto_sign/perk-192-short-3/m4/common.c | 102 ++++ crypto_sign/perk-192-short-3/m4/common.h | 109 ++++ crypto_sign/perk-192-short-3/m4/common_s.c | 42 ++ .../perk-192-short-3/m4/crypto_memset.c | 7 + .../perk-192-short-3/m4/crypto_memset.h | 18 + .../perk-192-short-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-192-short-3/m4/djbsort.c | 12 + crypto_sign/perk-192-short-3/m4/djbsort.h | 16 + crypto_sign/perk-192-short-3/m4/keygen.c | 51 ++ crypto_sign/perk-192-short-3/m4/keygen.h | 21 + crypto_sign/perk-192-short-3/m4/parameters.h | 46 ++ crypto_sign/perk-192-short-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-192-short-3/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-192-short-3/m4/permutation.c | 91 ++++ crypto_sign/perk-192-short-3/m4/permutation.h | 111 ++++ .../perk-192-short-3/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-192-short-3/m4/sign.c | 119 +++++ crypto_sign/perk-192-short-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-192-short-3/m4/signature.h | 64 +++ crypto_sign/perk-192-short-3/m4/sort.c | 128 +++++ crypto_sign/perk-192-short-3/m4/symmetric.c | 51 ++ crypto_sign/perk-192-short-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-192-short-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-192-short-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-192-short-3/m4/verbose.c | 131 +++++ crypto_sign/perk-192-short-3/m4/verbose.h | 129 +++++ crypto_sign/perk-192-short-3/m4/verify.c | 160 ++++++ crypto_sign/perk-192-short-3/m4/verify.h | 26 + crypto_sign/perk-192-short-5/m4/README | 43 ++ crypto_sign/perk-192-short-5/m4/api.h | 26 + crypto_sign/perk-192-short-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-192-short-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-192-short-5/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-192-short-5/m4/bn.h | 117 +++++ crypto_sign/perk-192-short-5/m4/common.c | 102 ++++ crypto_sign/perk-192-short-5/m4/common.h | 109 ++++ crypto_sign/perk-192-short-5/m4/common_s.c | 42 ++ .../perk-192-short-5/m4/crypto_memset.c | 7 + .../perk-192-short-5/m4/crypto_memset.h | 18 + .../perk-192-short-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-192-short-5/m4/djbsort.c | 12 + crypto_sign/perk-192-short-5/m4/djbsort.h | 16 + crypto_sign/perk-192-short-5/m4/keygen.c | 51 ++ crypto_sign/perk-192-short-5/m4/keygen.h | 21 + crypto_sign/perk-192-short-5/m4/parameters.h | 46 ++ crypto_sign/perk-192-short-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-192-short-5/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-192-short-5/m4/permutation.c | 91 ++++ crypto_sign/perk-192-short-5/m4/permutation.h | 111 ++++ .../perk-192-short-5/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-192-short-5/m4/sign.c | 119 +++++ crypto_sign/perk-192-short-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-192-short-5/m4/signature.h | 64 +++ crypto_sign/perk-192-short-5/m4/sort.c | 128 +++++ crypto_sign/perk-192-short-5/m4/symmetric.c | 51 ++ crypto_sign/perk-192-short-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-192-short-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-192-short-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-192-short-5/m4/verbose.c | 131 +++++ crypto_sign/perk-192-short-5/m4/verbose.h | 129 +++++ crypto_sign/perk-192-short-5/m4/verify.c | 160 ++++++ crypto_sign/perk-192-short-5/m4/verify.h | 26 + crypto_sign/perk-256-fast-3/m4/README | 43 ++ crypto_sign/perk-256-fast-3/m4/api.h | 26 + crypto_sign/perk-256-fast-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-256-fast-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-256-fast-3/m4/common.c | 102 ++++ crypto_sign/perk-256-fast-3/m4/common.h | 109 ++++ crypto_sign/perk-256-fast-3/m4/common_s.c | 42 ++ .../perk-256-fast-3/m4/crypto_memset.c | 7 + .../perk-256-fast-3/m4/crypto_memset.h | 18 + .../perk-256-fast-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-256-fast-3/m4/djbsort.c | 12 + crypto_sign/perk-256-fast-3/m4/djbsort.h | 16 + crypto_sign/perk-256-fast-3/m4/keygen.c | 51 ++ crypto_sign/perk-256-fast-3/m4/keygen.h | 21 + crypto_sign/perk-256-fast-3/m4/parameters.h | 43 ++ crypto_sign/perk-256-fast-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-256-fast-3/m4/parsing.h | 75 +++ .../perk-256-fast-3/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-256-fast-3/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-256-fast-3/m4/permutation.c | 91 ++++ crypto_sign/perk-256-fast-3/m4/permutation.h | 111 ++++ crypto_sign/perk-256-fast-3/m4/sign.c | 119 +++++ crypto_sign/perk-256-fast-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-256-fast-3/m4/signature.h | 64 +++ crypto_sign/perk-256-fast-3/m4/sort.c | 128 +++++ crypto_sign/perk-256-fast-3/m4/symmetric.c | 51 ++ crypto_sign/perk-256-fast-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-256-fast-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-256-fast-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-256-fast-3/m4/verbose.c | 131 +++++ crypto_sign/perk-256-fast-3/m4/verbose.h | 129 +++++ crypto_sign/perk-256-fast-3/m4/verify.c | 160 ++++++ crypto_sign/perk-256-fast-3/m4/verify.h | 26 + crypto_sign/perk-256-fast-5/m4/README | 43 ++ crypto_sign/perk-256-fast-5/m4/api.h | 26 + crypto_sign/perk-256-fast-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-256-fast-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-256-fast-5/m4/common.c | 102 ++++ crypto_sign/perk-256-fast-5/m4/common.h | 109 ++++ crypto_sign/perk-256-fast-5/m4/common_s.c | 42 ++ .../perk-256-fast-5/m4/crypto_memset.c | 7 + .../perk-256-fast-5/m4/crypto_memset.h | 18 + .../perk-256-fast-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-256-fast-5/m4/djbsort.c | 12 + crypto_sign/perk-256-fast-5/m4/djbsort.h | 16 + crypto_sign/perk-256-fast-5/m4/keygen.c | 51 ++ crypto_sign/perk-256-fast-5/m4/keygen.h | 21 + crypto_sign/perk-256-fast-5/m4/parameters.h | 43 ++ crypto_sign/perk-256-fast-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-256-fast-5/m4/parsing.h | 75 +++ .../perk-256-fast-5/m4/parsing_permutations.c | 425 ++++++++++++++++ .../perk-256-fast-5/m4/parsing_permutations.h | 53 ++ crypto_sign/perk-256-fast-5/m4/permutation.c | 91 ++++ crypto_sign/perk-256-fast-5/m4/permutation.h | 111 ++++ crypto_sign/perk-256-fast-5/m4/sign.c | 119 +++++ crypto_sign/perk-256-fast-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-256-fast-5/m4/signature.h | 64 +++ crypto_sign/perk-256-fast-5/m4/sort.c | 128 +++++ crypto_sign/perk-256-fast-5/m4/symmetric.c | 51 ++ crypto_sign/perk-256-fast-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-256-fast-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-256-fast-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-256-fast-5/m4/verbose.c | 131 +++++ crypto_sign/perk-256-fast-5/m4/verbose.h | 129 +++++ crypto_sign/perk-256-fast-5/m4/verify.c | 160 ++++++ crypto_sign/perk-256-fast-5/m4/verify.h | 26 + crypto_sign/perk-256-short-3/m4/README | 43 ++ crypto_sign/perk-256-short-3/m4/api.h | 26 + crypto_sign/perk-256-short-3/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-256-short-3/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-256-short-3/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-256-short-3/m4/bn.h | 117 +++++ crypto_sign/perk-256-short-3/m4/common.c | 102 ++++ crypto_sign/perk-256-short-3/m4/common.h | 109 ++++ crypto_sign/perk-256-short-3/m4/common_s.c | 42 ++ .../perk-256-short-3/m4/crypto_memset.c | 7 + .../perk-256-short-3/m4/crypto_memset.h | 18 + .../perk-256-short-3/m4/data_structures.h | 131 +++++ crypto_sign/perk-256-short-3/m4/djbsort.c | 12 + crypto_sign/perk-256-short-3/m4/djbsort.h | 16 + crypto_sign/perk-256-short-3/m4/keygen.c | 51 ++ crypto_sign/perk-256-short-3/m4/keygen.h | 21 + crypto_sign/perk-256-short-3/m4/parameters.h | 46 ++ crypto_sign/perk-256-short-3/m4/parsing.c | 217 ++++++++ crypto_sign/perk-256-short-3/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-256-short-3/m4/permutation.c | 91 ++++ crypto_sign/perk-256-short-3/m4/permutation.h | 111 ++++ .../perk-256-short-3/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-256-short-3/m4/sign.c | 119 +++++ crypto_sign/perk-256-short-3/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-256-short-3/m4/signature.h | 64 +++ crypto_sign/perk-256-short-3/m4/sort.c | 128 +++++ crypto_sign/perk-256-short-3/m4/symmetric.c | 51 ++ crypto_sign/perk-256-short-3/m4/symmetric.h | 135 +++++ crypto_sign/perk-256-short-3/m4/theta_tree.c | 55 ++ crypto_sign/perk-256-short-3/m4/theta_tree.h | 65 +++ crypto_sign/perk-256-short-3/m4/verbose.c | 131 +++++ crypto_sign/perk-256-short-3/m4/verbose.h | 129 +++++ crypto_sign/perk-256-short-3/m4/verify.c | 160 ++++++ crypto_sign/perk-256-short-3/m4/verify.h | 26 + crypto_sign/perk-256-short-5/m4/README | 43 ++ crypto_sign/perk-256-short-5/m4/api.h | 26 + crypto_sign/perk-256-short-5/m4/arithmetic.c | 154 ++++++ crypto_sign/perk-256-short-5/m4/arithmetic.h | 156 ++++++ crypto_sign/perk-256-short-5/m4/bn.c | 474 ++++++++++++++++++ crypto_sign/perk-256-short-5/m4/bn.h | 117 +++++ crypto_sign/perk-256-short-5/m4/common.c | 102 ++++ crypto_sign/perk-256-short-5/m4/common.h | 109 ++++ crypto_sign/perk-256-short-5/m4/common_s.c | 42 ++ .../perk-256-short-5/m4/crypto_memset.c | 7 + .../perk-256-short-5/m4/crypto_memset.h | 18 + .../perk-256-short-5/m4/data_structures.h | 131 +++++ crypto_sign/perk-256-short-5/m4/djbsort.c | 12 + crypto_sign/perk-256-short-5/m4/djbsort.h | 16 + crypto_sign/perk-256-short-5/m4/keygen.c | 51 ++ crypto_sign/perk-256-short-5/m4/keygen.h | 21 + crypto_sign/perk-256-short-5/m4/parameters.h | 46 ++ crypto_sign/perk-256-short-5/m4/parsing.c | 217 ++++++++ crypto_sign/perk-256-short-5/m4/parsing.h | 75 +++ .../m4/parsing_permutations.c | 111 ++++ .../m4/parsing_permutations.h | 65 +++ crypto_sign/perk-256-short-5/m4/permutation.c | 91 ++++ crypto_sign/perk-256-short-5/m4/permutation.h | 111 ++++ .../perk-256-short-5/m4/rank_unrank_table.h | 171 +++++++ crypto_sign/perk-256-short-5/m4/sign.c | 119 +++++ crypto_sign/perk-256-short-5/m4/signature.c | 384 ++++++++++++++ crypto_sign/perk-256-short-5/m4/signature.h | 64 +++ crypto_sign/perk-256-short-5/m4/sort.c | 128 +++++ crypto_sign/perk-256-short-5/m4/symmetric.c | 51 ++ crypto_sign/perk-256-short-5/m4/symmetric.h | 135 +++++ crypto_sign/perk-256-short-5/m4/theta_tree.c | 55 ++ crypto_sign/perk-256-short-5/m4/theta_tree.h | 65 +++ crypto_sign/perk-256-short-5/m4/verbose.c | 131 +++++ crypto_sign/perk-256-short-5/m4/verbose.h | 129 +++++ crypto_sign/perk-256-short-5/m4/verify.c | 160 ++++++ crypto_sign/perk-256-short-5/m4/verify.h | 26 + 414 files changed, 42978 insertions(+) create mode 100644 crypto_sign/perk-128-fast-3/m4/README create mode 100644 crypto_sign/perk-128-fast-3/m4/api.h create mode 100644 crypto_sign/perk-128-fast-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-128-fast-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-128-fast-3/m4/common.c create mode 100644 crypto_sign/perk-128-fast-3/m4/common.h create mode 100644 crypto_sign/perk-128-fast-3/m4/common_s.c create mode 100644 crypto_sign/perk-128-fast-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-128-fast-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-128-fast-3/m4/data_structures.h create mode 100644 crypto_sign/perk-128-fast-3/m4/djbsort.c create mode 100644 crypto_sign/perk-128-fast-3/m4/djbsort.h create mode 100644 crypto_sign/perk-128-fast-3/m4/keygen.c create mode 100644 crypto_sign/perk-128-fast-3/m4/keygen.h create mode 100644 crypto_sign/perk-128-fast-3/m4/parameters.h create mode 100644 crypto_sign/perk-128-fast-3/m4/parsing.c create mode 100644 crypto_sign/perk-128-fast-3/m4/parsing.h create mode 100644 crypto_sign/perk-128-fast-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-128-fast-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-128-fast-3/m4/permutation.c create mode 100644 crypto_sign/perk-128-fast-3/m4/permutation.h create mode 100644 crypto_sign/perk-128-fast-3/m4/sign.c create mode 100644 crypto_sign/perk-128-fast-3/m4/signature.c create mode 100644 crypto_sign/perk-128-fast-3/m4/signature.h create mode 100644 crypto_sign/perk-128-fast-3/m4/sort.c create mode 100644 crypto_sign/perk-128-fast-3/m4/symmetric.c create mode 100644 crypto_sign/perk-128-fast-3/m4/symmetric.h create mode 100644 crypto_sign/perk-128-fast-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-128-fast-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-128-fast-3/m4/verbose.c create mode 100644 crypto_sign/perk-128-fast-3/m4/verbose.h create mode 100644 crypto_sign/perk-128-fast-3/m4/verify.c create mode 100644 crypto_sign/perk-128-fast-3/m4/verify.h create mode 100644 crypto_sign/perk-128-fast-5/m4/README create mode 100644 crypto_sign/perk-128-fast-5/m4/api.h create mode 100644 crypto_sign/perk-128-fast-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-128-fast-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-128-fast-5/m4/common.c create mode 100644 crypto_sign/perk-128-fast-5/m4/common.h create mode 100644 crypto_sign/perk-128-fast-5/m4/common_s.c create mode 100644 crypto_sign/perk-128-fast-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-128-fast-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-128-fast-5/m4/data_structures.h create mode 100644 crypto_sign/perk-128-fast-5/m4/djbsort.c create mode 100644 crypto_sign/perk-128-fast-5/m4/djbsort.h create mode 100644 crypto_sign/perk-128-fast-5/m4/keygen.c create mode 100644 crypto_sign/perk-128-fast-5/m4/keygen.h create mode 100644 crypto_sign/perk-128-fast-5/m4/parameters.h create mode 100644 crypto_sign/perk-128-fast-5/m4/parsing.c create mode 100644 crypto_sign/perk-128-fast-5/m4/parsing.h create mode 100644 crypto_sign/perk-128-fast-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-128-fast-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-128-fast-5/m4/permutation.c create mode 100644 crypto_sign/perk-128-fast-5/m4/permutation.h create mode 100644 crypto_sign/perk-128-fast-5/m4/sign.c create mode 100644 crypto_sign/perk-128-fast-5/m4/signature.c create mode 100644 crypto_sign/perk-128-fast-5/m4/signature.h create mode 100644 crypto_sign/perk-128-fast-5/m4/sort.c create mode 100644 crypto_sign/perk-128-fast-5/m4/symmetric.c create mode 100644 crypto_sign/perk-128-fast-5/m4/symmetric.h create mode 100644 crypto_sign/perk-128-fast-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-128-fast-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-128-fast-5/m4/verbose.c create mode 100644 crypto_sign/perk-128-fast-5/m4/verbose.h create mode 100644 crypto_sign/perk-128-fast-5/m4/verify.c create mode 100644 crypto_sign/perk-128-fast-5/m4/verify.h create mode 100644 crypto_sign/perk-128-short-3/m4/README create mode 100644 crypto_sign/perk-128-short-3/m4/api.h create mode 100644 crypto_sign/perk-128-short-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-128-short-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-128-short-3/m4/bn.c create mode 100644 crypto_sign/perk-128-short-3/m4/bn.h create mode 100644 crypto_sign/perk-128-short-3/m4/common.c create mode 100644 crypto_sign/perk-128-short-3/m4/common.h create mode 100644 crypto_sign/perk-128-short-3/m4/common_s.c create mode 100644 crypto_sign/perk-128-short-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-128-short-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-128-short-3/m4/data_structures.h create mode 100644 crypto_sign/perk-128-short-3/m4/djbsort.c create mode 100644 crypto_sign/perk-128-short-3/m4/djbsort.h create mode 100644 crypto_sign/perk-128-short-3/m4/keygen.c create mode 100644 crypto_sign/perk-128-short-3/m4/keygen.h create mode 100644 crypto_sign/perk-128-short-3/m4/parameters.h create mode 100644 crypto_sign/perk-128-short-3/m4/parsing.c create mode 100644 crypto_sign/perk-128-short-3/m4/parsing.h create mode 100644 crypto_sign/perk-128-short-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-128-short-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-128-short-3/m4/permutation.c create mode 100644 crypto_sign/perk-128-short-3/m4/permutation.h create mode 100644 crypto_sign/perk-128-short-3/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-128-short-3/m4/sign.c create mode 100644 crypto_sign/perk-128-short-3/m4/signature.c create mode 100644 crypto_sign/perk-128-short-3/m4/signature.h create mode 100644 crypto_sign/perk-128-short-3/m4/sort.c create mode 100644 crypto_sign/perk-128-short-3/m4/symmetric.c create mode 100644 crypto_sign/perk-128-short-3/m4/symmetric.h create mode 100644 crypto_sign/perk-128-short-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-128-short-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-128-short-3/m4/verbose.c create mode 100644 crypto_sign/perk-128-short-3/m4/verbose.h create mode 100644 crypto_sign/perk-128-short-3/m4/verify.c create mode 100644 crypto_sign/perk-128-short-3/m4/verify.h create mode 100644 crypto_sign/perk-128-short-5/m4/README create mode 100644 crypto_sign/perk-128-short-5/m4/api.h create mode 100644 crypto_sign/perk-128-short-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-128-short-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-128-short-5/m4/bn.c create mode 100644 crypto_sign/perk-128-short-5/m4/bn.h create mode 100644 crypto_sign/perk-128-short-5/m4/common.c create mode 100644 crypto_sign/perk-128-short-5/m4/common.h create mode 100644 crypto_sign/perk-128-short-5/m4/common_s.c create mode 100644 crypto_sign/perk-128-short-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-128-short-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-128-short-5/m4/data_structures.h create mode 100644 crypto_sign/perk-128-short-5/m4/djbsort.c create mode 100644 crypto_sign/perk-128-short-5/m4/djbsort.h create mode 100644 crypto_sign/perk-128-short-5/m4/keygen.c create mode 100644 crypto_sign/perk-128-short-5/m4/keygen.h create mode 100644 crypto_sign/perk-128-short-5/m4/parameters.h create mode 100644 crypto_sign/perk-128-short-5/m4/parsing.c create mode 100644 crypto_sign/perk-128-short-5/m4/parsing.h create mode 100644 crypto_sign/perk-128-short-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-128-short-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-128-short-5/m4/permutation.c create mode 100644 crypto_sign/perk-128-short-5/m4/permutation.h create mode 100644 crypto_sign/perk-128-short-5/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-128-short-5/m4/sign.c create mode 100644 crypto_sign/perk-128-short-5/m4/signature.c create mode 100644 crypto_sign/perk-128-short-5/m4/signature.h create mode 100644 crypto_sign/perk-128-short-5/m4/sort.c create mode 100644 crypto_sign/perk-128-short-5/m4/symmetric.c create mode 100644 crypto_sign/perk-128-short-5/m4/symmetric.h create mode 100644 crypto_sign/perk-128-short-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-128-short-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-128-short-5/m4/verbose.c create mode 100644 crypto_sign/perk-128-short-5/m4/verbose.h create mode 100644 crypto_sign/perk-128-short-5/m4/verify.c create mode 100644 crypto_sign/perk-128-short-5/m4/verify.h create mode 100644 crypto_sign/perk-192-fast-3/m4/README create mode 100644 crypto_sign/perk-192-fast-3/m4/api.h create mode 100644 crypto_sign/perk-192-fast-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-192-fast-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-192-fast-3/m4/common.c create mode 100644 crypto_sign/perk-192-fast-3/m4/common.h create mode 100644 crypto_sign/perk-192-fast-3/m4/common_s.c create mode 100644 crypto_sign/perk-192-fast-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-192-fast-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-192-fast-3/m4/data_structures.h create mode 100644 crypto_sign/perk-192-fast-3/m4/djbsort.c create mode 100644 crypto_sign/perk-192-fast-3/m4/djbsort.h create mode 100644 crypto_sign/perk-192-fast-3/m4/keygen.c create mode 100644 crypto_sign/perk-192-fast-3/m4/keygen.h create mode 100644 crypto_sign/perk-192-fast-3/m4/parameters.h create mode 100644 crypto_sign/perk-192-fast-3/m4/parsing.c create mode 100644 crypto_sign/perk-192-fast-3/m4/parsing.h create mode 100644 crypto_sign/perk-192-fast-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-192-fast-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-192-fast-3/m4/permutation.c create mode 100644 crypto_sign/perk-192-fast-3/m4/permutation.h create mode 100644 crypto_sign/perk-192-fast-3/m4/sign.c create mode 100644 crypto_sign/perk-192-fast-3/m4/signature.c create mode 100644 crypto_sign/perk-192-fast-3/m4/signature.h create mode 100644 crypto_sign/perk-192-fast-3/m4/sort.c create mode 100644 crypto_sign/perk-192-fast-3/m4/symmetric.c create mode 100644 crypto_sign/perk-192-fast-3/m4/symmetric.h create mode 100644 crypto_sign/perk-192-fast-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-192-fast-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-192-fast-3/m4/verbose.c create mode 100644 crypto_sign/perk-192-fast-3/m4/verbose.h create mode 100644 crypto_sign/perk-192-fast-3/m4/verify.c create mode 100644 crypto_sign/perk-192-fast-3/m4/verify.h create mode 100644 crypto_sign/perk-192-fast-5/m4/README create mode 100644 crypto_sign/perk-192-fast-5/m4/api.h create mode 100644 crypto_sign/perk-192-fast-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-192-fast-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-192-fast-5/m4/common.c create mode 100644 crypto_sign/perk-192-fast-5/m4/common.h create mode 100644 crypto_sign/perk-192-fast-5/m4/common_s.c create mode 100644 crypto_sign/perk-192-fast-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-192-fast-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-192-fast-5/m4/data_structures.h create mode 100644 crypto_sign/perk-192-fast-5/m4/djbsort.c create mode 100644 crypto_sign/perk-192-fast-5/m4/djbsort.h create mode 100644 crypto_sign/perk-192-fast-5/m4/keygen.c create mode 100644 crypto_sign/perk-192-fast-5/m4/keygen.h create mode 100644 crypto_sign/perk-192-fast-5/m4/parameters.h create mode 100644 crypto_sign/perk-192-fast-5/m4/parsing.c create mode 100644 crypto_sign/perk-192-fast-5/m4/parsing.h create mode 100644 crypto_sign/perk-192-fast-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-192-fast-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-192-fast-5/m4/permutation.c create mode 100644 crypto_sign/perk-192-fast-5/m4/permutation.h create mode 100644 crypto_sign/perk-192-fast-5/m4/sign.c create mode 100644 crypto_sign/perk-192-fast-5/m4/signature.c create mode 100644 crypto_sign/perk-192-fast-5/m4/signature.h create mode 100644 crypto_sign/perk-192-fast-5/m4/sort.c create mode 100644 crypto_sign/perk-192-fast-5/m4/symmetric.c create mode 100644 crypto_sign/perk-192-fast-5/m4/symmetric.h create mode 100644 crypto_sign/perk-192-fast-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-192-fast-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-192-fast-5/m4/verbose.c create mode 100644 crypto_sign/perk-192-fast-5/m4/verbose.h create mode 100644 crypto_sign/perk-192-fast-5/m4/verify.c create mode 100644 crypto_sign/perk-192-fast-5/m4/verify.h create mode 100644 crypto_sign/perk-192-short-3/m4/README create mode 100644 crypto_sign/perk-192-short-3/m4/api.h create mode 100644 crypto_sign/perk-192-short-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-192-short-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-192-short-3/m4/bn.c create mode 100644 crypto_sign/perk-192-short-3/m4/bn.h create mode 100644 crypto_sign/perk-192-short-3/m4/common.c create mode 100644 crypto_sign/perk-192-short-3/m4/common.h create mode 100644 crypto_sign/perk-192-short-3/m4/common_s.c create mode 100644 crypto_sign/perk-192-short-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-192-short-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-192-short-3/m4/data_structures.h create mode 100644 crypto_sign/perk-192-short-3/m4/djbsort.c create mode 100644 crypto_sign/perk-192-short-3/m4/djbsort.h create mode 100644 crypto_sign/perk-192-short-3/m4/keygen.c create mode 100644 crypto_sign/perk-192-short-3/m4/keygen.h create mode 100644 crypto_sign/perk-192-short-3/m4/parameters.h create mode 100644 crypto_sign/perk-192-short-3/m4/parsing.c create mode 100644 crypto_sign/perk-192-short-3/m4/parsing.h create mode 100644 crypto_sign/perk-192-short-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-192-short-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-192-short-3/m4/permutation.c create mode 100644 crypto_sign/perk-192-short-3/m4/permutation.h create mode 100644 crypto_sign/perk-192-short-3/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-192-short-3/m4/sign.c create mode 100644 crypto_sign/perk-192-short-3/m4/signature.c create mode 100644 crypto_sign/perk-192-short-3/m4/signature.h create mode 100644 crypto_sign/perk-192-short-3/m4/sort.c create mode 100644 crypto_sign/perk-192-short-3/m4/symmetric.c create mode 100644 crypto_sign/perk-192-short-3/m4/symmetric.h create mode 100644 crypto_sign/perk-192-short-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-192-short-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-192-short-3/m4/verbose.c create mode 100644 crypto_sign/perk-192-short-3/m4/verbose.h create mode 100644 crypto_sign/perk-192-short-3/m4/verify.c create mode 100644 crypto_sign/perk-192-short-3/m4/verify.h create mode 100644 crypto_sign/perk-192-short-5/m4/README create mode 100644 crypto_sign/perk-192-short-5/m4/api.h create mode 100644 crypto_sign/perk-192-short-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-192-short-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-192-short-5/m4/bn.c create mode 100644 crypto_sign/perk-192-short-5/m4/bn.h create mode 100644 crypto_sign/perk-192-short-5/m4/common.c create mode 100644 crypto_sign/perk-192-short-5/m4/common.h create mode 100644 crypto_sign/perk-192-short-5/m4/common_s.c create mode 100644 crypto_sign/perk-192-short-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-192-short-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-192-short-5/m4/data_structures.h create mode 100644 crypto_sign/perk-192-short-5/m4/djbsort.c create mode 100644 crypto_sign/perk-192-short-5/m4/djbsort.h create mode 100644 crypto_sign/perk-192-short-5/m4/keygen.c create mode 100644 crypto_sign/perk-192-short-5/m4/keygen.h create mode 100644 crypto_sign/perk-192-short-5/m4/parameters.h create mode 100644 crypto_sign/perk-192-short-5/m4/parsing.c create mode 100644 crypto_sign/perk-192-short-5/m4/parsing.h create mode 100644 crypto_sign/perk-192-short-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-192-short-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-192-short-5/m4/permutation.c create mode 100644 crypto_sign/perk-192-short-5/m4/permutation.h create mode 100644 crypto_sign/perk-192-short-5/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-192-short-5/m4/sign.c create mode 100644 crypto_sign/perk-192-short-5/m4/signature.c create mode 100644 crypto_sign/perk-192-short-5/m4/signature.h create mode 100644 crypto_sign/perk-192-short-5/m4/sort.c create mode 100644 crypto_sign/perk-192-short-5/m4/symmetric.c create mode 100644 crypto_sign/perk-192-short-5/m4/symmetric.h create mode 100644 crypto_sign/perk-192-short-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-192-short-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-192-short-5/m4/verbose.c create mode 100644 crypto_sign/perk-192-short-5/m4/verbose.h create mode 100644 crypto_sign/perk-192-short-5/m4/verify.c create mode 100644 crypto_sign/perk-192-short-5/m4/verify.h create mode 100644 crypto_sign/perk-256-fast-3/m4/README create mode 100644 crypto_sign/perk-256-fast-3/m4/api.h create mode 100644 crypto_sign/perk-256-fast-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-256-fast-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-256-fast-3/m4/common.c create mode 100644 crypto_sign/perk-256-fast-3/m4/common.h create mode 100644 crypto_sign/perk-256-fast-3/m4/common_s.c create mode 100644 crypto_sign/perk-256-fast-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-256-fast-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-256-fast-3/m4/data_structures.h create mode 100644 crypto_sign/perk-256-fast-3/m4/djbsort.c create mode 100644 crypto_sign/perk-256-fast-3/m4/djbsort.h create mode 100644 crypto_sign/perk-256-fast-3/m4/keygen.c create mode 100644 crypto_sign/perk-256-fast-3/m4/keygen.h create mode 100644 crypto_sign/perk-256-fast-3/m4/parameters.h create mode 100644 crypto_sign/perk-256-fast-3/m4/parsing.c create mode 100644 crypto_sign/perk-256-fast-3/m4/parsing.h create mode 100644 crypto_sign/perk-256-fast-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-256-fast-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-256-fast-3/m4/permutation.c create mode 100644 crypto_sign/perk-256-fast-3/m4/permutation.h create mode 100644 crypto_sign/perk-256-fast-3/m4/sign.c create mode 100644 crypto_sign/perk-256-fast-3/m4/signature.c create mode 100644 crypto_sign/perk-256-fast-3/m4/signature.h create mode 100644 crypto_sign/perk-256-fast-3/m4/sort.c create mode 100644 crypto_sign/perk-256-fast-3/m4/symmetric.c create mode 100644 crypto_sign/perk-256-fast-3/m4/symmetric.h create mode 100644 crypto_sign/perk-256-fast-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-256-fast-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-256-fast-3/m4/verbose.c create mode 100644 crypto_sign/perk-256-fast-3/m4/verbose.h create mode 100644 crypto_sign/perk-256-fast-3/m4/verify.c create mode 100644 crypto_sign/perk-256-fast-3/m4/verify.h create mode 100644 crypto_sign/perk-256-fast-5/m4/README create mode 100644 crypto_sign/perk-256-fast-5/m4/api.h create mode 100644 crypto_sign/perk-256-fast-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-256-fast-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-256-fast-5/m4/common.c create mode 100644 crypto_sign/perk-256-fast-5/m4/common.h create mode 100644 crypto_sign/perk-256-fast-5/m4/common_s.c create mode 100644 crypto_sign/perk-256-fast-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-256-fast-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-256-fast-5/m4/data_structures.h create mode 100644 crypto_sign/perk-256-fast-5/m4/djbsort.c create mode 100644 crypto_sign/perk-256-fast-5/m4/djbsort.h create mode 100644 crypto_sign/perk-256-fast-5/m4/keygen.c create mode 100644 crypto_sign/perk-256-fast-5/m4/keygen.h create mode 100644 crypto_sign/perk-256-fast-5/m4/parameters.h create mode 100644 crypto_sign/perk-256-fast-5/m4/parsing.c create mode 100644 crypto_sign/perk-256-fast-5/m4/parsing.h create mode 100644 crypto_sign/perk-256-fast-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-256-fast-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-256-fast-5/m4/permutation.c create mode 100644 crypto_sign/perk-256-fast-5/m4/permutation.h create mode 100644 crypto_sign/perk-256-fast-5/m4/sign.c create mode 100644 crypto_sign/perk-256-fast-5/m4/signature.c create mode 100644 crypto_sign/perk-256-fast-5/m4/signature.h create mode 100644 crypto_sign/perk-256-fast-5/m4/sort.c create mode 100644 crypto_sign/perk-256-fast-5/m4/symmetric.c create mode 100644 crypto_sign/perk-256-fast-5/m4/symmetric.h create mode 100644 crypto_sign/perk-256-fast-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-256-fast-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-256-fast-5/m4/verbose.c create mode 100644 crypto_sign/perk-256-fast-5/m4/verbose.h create mode 100644 crypto_sign/perk-256-fast-5/m4/verify.c create mode 100644 crypto_sign/perk-256-fast-5/m4/verify.h create mode 100644 crypto_sign/perk-256-short-3/m4/README create mode 100644 crypto_sign/perk-256-short-3/m4/api.h create mode 100644 crypto_sign/perk-256-short-3/m4/arithmetic.c create mode 100644 crypto_sign/perk-256-short-3/m4/arithmetic.h create mode 100644 crypto_sign/perk-256-short-3/m4/bn.c create mode 100644 crypto_sign/perk-256-short-3/m4/bn.h create mode 100644 crypto_sign/perk-256-short-3/m4/common.c create mode 100644 crypto_sign/perk-256-short-3/m4/common.h create mode 100644 crypto_sign/perk-256-short-3/m4/common_s.c create mode 100644 crypto_sign/perk-256-short-3/m4/crypto_memset.c create mode 100644 crypto_sign/perk-256-short-3/m4/crypto_memset.h create mode 100644 crypto_sign/perk-256-short-3/m4/data_structures.h create mode 100644 crypto_sign/perk-256-short-3/m4/djbsort.c create mode 100644 crypto_sign/perk-256-short-3/m4/djbsort.h create mode 100644 crypto_sign/perk-256-short-3/m4/keygen.c create mode 100644 crypto_sign/perk-256-short-3/m4/keygen.h create mode 100644 crypto_sign/perk-256-short-3/m4/parameters.h create mode 100644 crypto_sign/perk-256-short-3/m4/parsing.c create mode 100644 crypto_sign/perk-256-short-3/m4/parsing.h create mode 100644 crypto_sign/perk-256-short-3/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-256-short-3/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-256-short-3/m4/permutation.c create mode 100644 crypto_sign/perk-256-short-3/m4/permutation.h create mode 100644 crypto_sign/perk-256-short-3/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-256-short-3/m4/sign.c create mode 100644 crypto_sign/perk-256-short-3/m4/signature.c create mode 100644 crypto_sign/perk-256-short-3/m4/signature.h create mode 100644 crypto_sign/perk-256-short-3/m4/sort.c create mode 100644 crypto_sign/perk-256-short-3/m4/symmetric.c create mode 100644 crypto_sign/perk-256-short-3/m4/symmetric.h create mode 100644 crypto_sign/perk-256-short-3/m4/theta_tree.c create mode 100644 crypto_sign/perk-256-short-3/m4/theta_tree.h create mode 100644 crypto_sign/perk-256-short-3/m4/verbose.c create mode 100644 crypto_sign/perk-256-short-3/m4/verbose.h create mode 100644 crypto_sign/perk-256-short-3/m4/verify.c create mode 100644 crypto_sign/perk-256-short-3/m4/verify.h create mode 100644 crypto_sign/perk-256-short-5/m4/README create mode 100644 crypto_sign/perk-256-short-5/m4/api.h create mode 100644 crypto_sign/perk-256-short-5/m4/arithmetic.c create mode 100644 crypto_sign/perk-256-short-5/m4/arithmetic.h create mode 100644 crypto_sign/perk-256-short-5/m4/bn.c create mode 100644 crypto_sign/perk-256-short-5/m4/bn.h create mode 100644 crypto_sign/perk-256-short-5/m4/common.c create mode 100644 crypto_sign/perk-256-short-5/m4/common.h create mode 100644 crypto_sign/perk-256-short-5/m4/common_s.c create mode 100644 crypto_sign/perk-256-short-5/m4/crypto_memset.c create mode 100644 crypto_sign/perk-256-short-5/m4/crypto_memset.h create mode 100644 crypto_sign/perk-256-short-5/m4/data_structures.h create mode 100644 crypto_sign/perk-256-short-5/m4/djbsort.c create mode 100644 crypto_sign/perk-256-short-5/m4/djbsort.h create mode 100644 crypto_sign/perk-256-short-5/m4/keygen.c create mode 100644 crypto_sign/perk-256-short-5/m4/keygen.h create mode 100644 crypto_sign/perk-256-short-5/m4/parameters.h create mode 100644 crypto_sign/perk-256-short-5/m4/parsing.c create mode 100644 crypto_sign/perk-256-short-5/m4/parsing.h create mode 100644 crypto_sign/perk-256-short-5/m4/parsing_permutations.c create mode 100644 crypto_sign/perk-256-short-5/m4/parsing_permutations.h create mode 100644 crypto_sign/perk-256-short-5/m4/permutation.c create mode 100644 crypto_sign/perk-256-short-5/m4/permutation.h create mode 100644 crypto_sign/perk-256-short-5/m4/rank_unrank_table.h create mode 100644 crypto_sign/perk-256-short-5/m4/sign.c create mode 100644 crypto_sign/perk-256-short-5/m4/signature.c create mode 100644 crypto_sign/perk-256-short-5/m4/signature.h create mode 100644 crypto_sign/perk-256-short-5/m4/sort.c create mode 100644 crypto_sign/perk-256-short-5/m4/symmetric.c create mode 100644 crypto_sign/perk-256-short-5/m4/symmetric.h create mode 100644 crypto_sign/perk-256-short-5/m4/theta_tree.c create mode 100644 crypto_sign/perk-256-short-5/m4/theta_tree.h create mode 100644 crypto_sign/perk-256-short-5/m4/verbose.c create mode 100644 crypto_sign/perk-256-short-5/m4/verbose.h create mode 100644 crypto_sign/perk-256-short-5/m4/verify.c create mode 100644 crypto_sign/perk-256-short-5/m4/verify.h diff --git a/crypto_sign/perk-128-fast-3/m4/README b/crypto_sign/perk-128-fast-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-128-fast-3/m4/api.h b/crypto_sign/perk-128-fast-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-128-fast-3/m4/arithmetic.c b/crypto_sign/perk-128-fast-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/arithmetic.h b/crypto_sign/perk-128-fast-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/common.c b/crypto_sign/perk-128-fast-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/common.h b/crypto_sign/perk-128-fast-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/common_s.c b/crypto_sign/perk-128-fast-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-128-fast-3/m4/crypto_memset.c b/crypto_sign/perk-128-fast-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-fast-3/m4/crypto_memset.h b/crypto_sign/perk-128-fast-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-fast-3/m4/data_structures.h b/crypto_sign/perk-128-fast-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/djbsort.c b/crypto_sign/perk-128-fast-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-128-fast-3/m4/djbsort.h b/crypto_sign/perk-128-fast-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-128-fast-3/m4/keygen.c b/crypto_sign/perk-128-fast-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/keygen.h b/crypto_sign/perk-128-fast-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/parameters.h b/crypto_sign/perk-128-fast-3/m4/parameters.h new file mode 100644 index 00000000..6d0a49f8 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 16 /**< Number of bytes for the expected security level */ +#define PARAM_N1 79 /**< Parameter n of the scheme */ +#define PARAM_M 35 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 30 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 13 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-128-fast-3/m4/parsing.c b/crypto_sign/perk-128-fast-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/parsing.h b/crypto_sign/perk-128-fast-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-128-fast-3/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-128-fast-3/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/permutation.c b/crypto_sign/perk-128-fast-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/permutation.h b/crypto_sign/perk-128-fast-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/sign.c b/crypto_sign/perk-128-fast-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/signature.c b/crypto_sign/perk-128-fast-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/signature.h b/crypto_sign/perk-128-fast-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/sort.c b/crypto_sign/perk-128-fast-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-128-fast-3/m4/symmetric.c b/crypto_sign/perk-128-fast-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-128-fast-3/m4/symmetric.h b/crypto_sign/perk-128-fast-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/theta_tree.c b/crypto_sign/perk-128-fast-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-128-fast-3/m4/theta_tree.h b/crypto_sign/perk-128-fast-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/verbose.c b/crypto_sign/perk-128-fast-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/verbose.h b/crypto_sign/perk-128-fast-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/verify.c b/crypto_sign/perk-128-fast-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-3/m4/verify.h b/crypto_sign/perk-128-fast-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-128-fast-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/README b/crypto_sign/perk-128-fast-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-128-fast-5/m4/api.h b/crypto_sign/perk-128-fast-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.c b/crypto_sign/perk-128-fast-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.h b/crypto_sign/perk-128-fast-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.c b/crypto_sign/perk-128-fast-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.h b/crypto_sign/perk-128-fast-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common_s.c b/crypto_sign/perk-128-fast-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.c b/crypto_sign/perk-128-fast-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.h b/crypto_sign/perk-128-fast-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-fast-5/m4/data_structures.h b/crypto_sign/perk-128-fast-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.c b/crypto_sign/perk-128-fast-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.h b/crypto_sign/perk-128-fast-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.c b/crypto_sign/perk-128-fast-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.h b/crypto_sign/perk-128-fast-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parameters.h b/crypto_sign/perk-128-fast-5/m4/parameters.h new file mode 100644 index 00000000..e79c34e5 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 16 /**< Number of bytes for the expected security level */ +#define PARAM_N1 83 /**< Parameter n of the scheme */ +#define PARAM_M 36 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 28 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 13 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.c b/crypto_sign/perk-128-fast-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.h b/crypto_sign/perk-128-fast-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.c b/crypto_sign/perk-128-fast-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.h b/crypto_sign/perk-128-fast-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/sign.c b/crypto_sign/perk-128-fast-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.c b/crypto_sign/perk-128-fast-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.h b/crypto_sign/perk-128-fast-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/sort.c b/crypto_sign/perk-128-fast-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.c b/crypto_sign/perk-128-fast-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.h b/crypto_sign/perk-128-fast-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.c b/crypto_sign/perk-128-fast-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.h b/crypto_sign/perk-128-fast-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.c b/crypto_sign/perk-128-fast-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.h b/crypto_sign/perk-128-fast-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.c b/crypto_sign/perk-128-fast-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.h b/crypto_sign/perk-128-fast-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/README b/crypto_sign/perk-128-short-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-128-short-3/m4/api.h b/crypto_sign/perk-128-short-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.c b/crypto_sign/perk-128-short-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.h b/crypto_sign/perk-128-short-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/bn.c b/crypto_sign/perk-128-short-3/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/bn.h b/crypto_sign/perk-128-short-3/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-128-short-3/m4/common.c b/crypto_sign/perk-128-short-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common.h b/crypto_sign/perk-128-short-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common_s.c b/crypto_sign/perk-128-short-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.c b/crypto_sign/perk-128-short-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.h b/crypto_sign/perk-128-short-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-short-3/m4/data_structures.h b/crypto_sign/perk-128-short-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.c b/crypto_sign/perk-128-short-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.h b/crypto_sign/perk-128-short-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-128-short-3/m4/keygen.c b/crypto_sign/perk-128-short-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/keygen.h b/crypto_sign/perk-128-short-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parameters.h b/crypto_sign/perk-128-short-3/m4/parameters.h new file mode 100644 index 00000000..02e797a7 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 16 /**< Number of bytes for the expected security level */ +#define PARAM_N1 79 /**< Parameter n of the scheme */ +#define PARAM_M 35 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 20 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 7 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 389 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-128-short-3/m4/parsing.c b/crypto_sign/perk-128-short-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing.h b/crypto_sign/perk-128-short-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing_permutations.c b/crypto_sign/perk-128-short-3/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing_permutations.h b/crypto_sign/perk-128-short-3/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.c b/crypto_sign/perk-128-short-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.h b/crypto_sign/perk-128-short-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-128-short-3/m4/sign.c b/crypto_sign/perk-128-short-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.c b/crypto_sign/perk-128-short-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.h b/crypto_sign/perk-128-short-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/sort.c b/crypto_sign/perk-128-short-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.c b/crypto_sign/perk-128-short-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.h b/crypto_sign/perk-128-short-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.c b/crypto_sign/perk-128-short-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.h b/crypto_sign/perk-128-short-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.c b/crypto_sign/perk-128-short-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.h b/crypto_sign/perk-128-short-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.c b/crypto_sign/perk-128-short-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.h b/crypto_sign/perk-128-short-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/README b/crypto_sign/perk-128-short-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-128-short-5/m4/api.h b/crypto_sign/perk-128-short-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.c b/crypto_sign/perk-128-short-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.h b/crypto_sign/perk-128-short-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/bn.c b/crypto_sign/perk-128-short-5/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/bn.h b/crypto_sign/perk-128-short-5/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-128-short-5/m4/common.c b/crypto_sign/perk-128-short-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common.h b/crypto_sign/perk-128-short-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common_s.c b/crypto_sign/perk-128-short-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.c b/crypto_sign/perk-128-short-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.h b/crypto_sign/perk-128-short-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-short-5/m4/data_structures.h b/crypto_sign/perk-128-short-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.c b/crypto_sign/perk-128-short-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.h b/crypto_sign/perk-128-short-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-128-short-5/m4/keygen.c b/crypto_sign/perk-128-short-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/keygen.h b/crypto_sign/perk-128-short-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parameters.h b/crypto_sign/perk-128-short-5/m4/parameters.h new file mode 100644 index 00000000..6755f791 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 16 /**< Number of bytes for the expected security level */ +#define PARAM_N1 83 /**< Parameter n of the scheme */ +#define PARAM_M 36 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 18 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 7 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 414 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-128-short-5/m4/parsing.c b/crypto_sign/perk-128-short-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing.h b/crypto_sign/perk-128-short-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.c b/crypto_sign/perk-128-short-5/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.h b/crypto_sign/perk-128-short-5/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.c b/crypto_sign/perk-128-short-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.h b/crypto_sign/perk-128-short-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-128-short-5/m4/sign.c b/crypto_sign/perk-128-short-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.c b/crypto_sign/perk-128-short-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.h b/crypto_sign/perk-128-short-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/sort.c b/crypto_sign/perk-128-short-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.c b/crypto_sign/perk-128-short-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.h b/crypto_sign/perk-128-short-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.c b/crypto_sign/perk-128-short-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.h b/crypto_sign/perk-128-short-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.c b/crypto_sign/perk-128-short-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.h b/crypto_sign/perk-128-short-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.c b/crypto_sign/perk-128-short-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.h b/crypto_sign/perk-128-short-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/README b/crypto_sign/perk-192-fast-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-192-fast-3/m4/api.h b/crypto_sign/perk-192-fast-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.c b/crypto_sign/perk-192-fast-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.h b/crypto_sign/perk-192-fast-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.c b/crypto_sign/perk-192-fast-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.h b/crypto_sign/perk-192-fast-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common_s.c b/crypto_sign/perk-192-fast-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.c b/crypto_sign/perk-192-fast-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.h b/crypto_sign/perk-192-fast-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-fast-3/m4/data_structures.h b/crypto_sign/perk-192-fast-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.c b/crypto_sign/perk-192-fast-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.h b/crypto_sign/perk-192-fast-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.c b/crypto_sign/perk-192-fast-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.h b/crypto_sign/perk-192-fast-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parameters.h b/crypto_sign/perk-192-fast-3/m4/parameters.h new file mode 100644 index 00000000..91cec4ff --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 24 /**< Number of bytes for the expected security level */ +#define PARAM_N1 112 /**< Parameter n of the scheme */ +#define PARAM_M 54 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 46 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 14 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.c b/crypto_sign/perk-192-fast-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.h b/crypto_sign/perk-192-fast-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.c b/crypto_sign/perk-192-fast-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.h b/crypto_sign/perk-192-fast-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/sign.c b/crypto_sign/perk-192-fast-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.c b/crypto_sign/perk-192-fast-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.h b/crypto_sign/perk-192-fast-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/sort.c b/crypto_sign/perk-192-fast-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.c b/crypto_sign/perk-192-fast-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.h b/crypto_sign/perk-192-fast-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.c b/crypto_sign/perk-192-fast-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.h b/crypto_sign/perk-192-fast-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.c b/crypto_sign/perk-192-fast-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.h b/crypto_sign/perk-192-fast-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.c b/crypto_sign/perk-192-fast-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.h b/crypto_sign/perk-192-fast-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/README b/crypto_sign/perk-192-fast-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-192-fast-5/m4/api.h b/crypto_sign/perk-192-fast-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.c b/crypto_sign/perk-192-fast-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.h b/crypto_sign/perk-192-fast-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.c b/crypto_sign/perk-192-fast-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.h b/crypto_sign/perk-192-fast-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common_s.c b/crypto_sign/perk-192-fast-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.c b/crypto_sign/perk-192-fast-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.h b/crypto_sign/perk-192-fast-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-fast-5/m4/data_structures.h b/crypto_sign/perk-192-fast-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.c b/crypto_sign/perk-192-fast-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.h b/crypto_sign/perk-192-fast-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.c b/crypto_sign/perk-192-fast-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.h b/crypto_sign/perk-192-fast-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parameters.h b/crypto_sign/perk-192-fast-5/m4/parameters.h new file mode 100644 index 00000000..90e5ba8d --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 24 /**< Number of bytes for the expected security level */ +#define PARAM_N1 116 /**< Parameter n of the scheme */ +#define PARAM_M 55 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 43 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 14 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.c b/crypto_sign/perk-192-fast-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.h b/crypto_sign/perk-192-fast-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.c b/crypto_sign/perk-192-fast-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.h b/crypto_sign/perk-192-fast-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/sign.c b/crypto_sign/perk-192-fast-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.c b/crypto_sign/perk-192-fast-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.h b/crypto_sign/perk-192-fast-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/sort.c b/crypto_sign/perk-192-fast-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.c b/crypto_sign/perk-192-fast-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.h b/crypto_sign/perk-192-fast-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.c b/crypto_sign/perk-192-fast-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.h b/crypto_sign/perk-192-fast-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.c b/crypto_sign/perk-192-fast-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.h b/crypto_sign/perk-192-fast-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.c b/crypto_sign/perk-192-fast-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.h b/crypto_sign/perk-192-fast-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/README b/crypto_sign/perk-192-short-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-192-short-3/m4/api.h b/crypto_sign/perk-192-short-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.c b/crypto_sign/perk-192-short-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.h b/crypto_sign/perk-192-short-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/bn.c b/crypto_sign/perk-192-short-3/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/bn.h b/crypto_sign/perk-192-short-3/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-192-short-3/m4/common.c b/crypto_sign/perk-192-short-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common.h b/crypto_sign/perk-192-short-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common_s.c b/crypto_sign/perk-192-short-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.c b/crypto_sign/perk-192-short-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.h b/crypto_sign/perk-192-short-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-short-3/m4/data_structures.h b/crypto_sign/perk-192-short-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.c b/crypto_sign/perk-192-short-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.h b/crypto_sign/perk-192-short-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-192-short-3/m4/keygen.c b/crypto_sign/perk-192-short-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/keygen.h b/crypto_sign/perk-192-short-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parameters.h b/crypto_sign/perk-192-short-3/m4/parameters.h new file mode 100644 index 00000000..3ffcebeb --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 24 /**< Number of bytes for the expected security level */ +#define PARAM_N1 112 /**< Parameter n of the scheme */ +#define PARAM_M 54 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 31 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 7 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 606 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-192-short-3/m4/parsing.c b/crypto_sign/perk-192-short-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing.h b/crypto_sign/perk-192-short-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.c b/crypto_sign/perk-192-short-3/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.h b/crypto_sign/perk-192-short-3/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.c b/crypto_sign/perk-192-short-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.h b/crypto_sign/perk-192-short-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-192-short-3/m4/sign.c b/crypto_sign/perk-192-short-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.c b/crypto_sign/perk-192-short-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.h b/crypto_sign/perk-192-short-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/sort.c b/crypto_sign/perk-192-short-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.c b/crypto_sign/perk-192-short-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.h b/crypto_sign/perk-192-short-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.c b/crypto_sign/perk-192-short-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.h b/crypto_sign/perk-192-short-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.c b/crypto_sign/perk-192-short-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.h b/crypto_sign/perk-192-short-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.c b/crypto_sign/perk-192-short-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.h b/crypto_sign/perk-192-short-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/README b/crypto_sign/perk-192-short-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-192-short-5/m4/api.h b/crypto_sign/perk-192-short-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.c b/crypto_sign/perk-192-short-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.h b/crypto_sign/perk-192-short-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/bn.c b/crypto_sign/perk-192-short-5/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/bn.h b/crypto_sign/perk-192-short-5/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-192-short-5/m4/common.c b/crypto_sign/perk-192-short-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common.h b/crypto_sign/perk-192-short-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common_s.c b/crypto_sign/perk-192-short-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.c b/crypto_sign/perk-192-short-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.h b/crypto_sign/perk-192-short-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-short-5/m4/data_structures.h b/crypto_sign/perk-192-short-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.c b/crypto_sign/perk-192-short-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.h b/crypto_sign/perk-192-short-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-192-short-5/m4/keygen.c b/crypto_sign/perk-192-short-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/keygen.h b/crypto_sign/perk-192-short-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parameters.h b/crypto_sign/perk-192-short-5/m4/parameters.h new file mode 100644 index 00000000..6d69bbfa --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 24 /**< Number of bytes for the expected security level */ +#define PARAM_N1 116 /**< Parameter n of the scheme */ +#define PARAM_M 55 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 28 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 7 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 633 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-192-short-5/m4/parsing.c b/crypto_sign/perk-192-short-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing.h b/crypto_sign/perk-192-short-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.c b/crypto_sign/perk-192-short-5/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.h b/crypto_sign/perk-192-short-5/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.c b/crypto_sign/perk-192-short-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.h b/crypto_sign/perk-192-short-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-192-short-5/m4/sign.c b/crypto_sign/perk-192-short-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.c b/crypto_sign/perk-192-short-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.h b/crypto_sign/perk-192-short-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/sort.c b/crypto_sign/perk-192-short-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.c b/crypto_sign/perk-192-short-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.h b/crypto_sign/perk-192-short-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.c b/crypto_sign/perk-192-short-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.h b/crypto_sign/perk-192-short-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.c b/crypto_sign/perk-192-short-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.h b/crypto_sign/perk-192-short-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.c b/crypto_sign/perk-192-short-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.h b/crypto_sign/perk-192-short-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/README b/crypto_sign/perk-256-fast-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-256-fast-3/m4/api.h b/crypto_sign/perk-256-fast-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.c b/crypto_sign/perk-256-fast-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.h b/crypto_sign/perk-256-fast-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.c b/crypto_sign/perk-256-fast-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.h b/crypto_sign/perk-256-fast-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common_s.c b/crypto_sign/perk-256-fast-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.c b/crypto_sign/perk-256-fast-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.h b/crypto_sign/perk-256-fast-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-fast-3/m4/data_structures.h b/crypto_sign/perk-256-fast-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.c b/crypto_sign/perk-256-fast-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.h b/crypto_sign/perk-256-fast-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.c b/crypto_sign/perk-256-fast-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.h b/crypto_sign/perk-256-fast-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parameters.h b/crypto_sign/perk-256-fast-3/m4/parameters.h new file mode 100644 index 00000000..b575cabb --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 32 /**< Number of bytes for the expected security level */ +#define PARAM_N1 146 /**< Parameter n of the scheme */ +#define PARAM_M 75 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 61 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 15 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.c b/crypto_sign/perk-256-fast-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.h b/crypto_sign/perk-256-fast-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.c b/crypto_sign/perk-256-fast-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.h b/crypto_sign/perk-256-fast-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/sign.c b/crypto_sign/perk-256-fast-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.c b/crypto_sign/perk-256-fast-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.h b/crypto_sign/perk-256-fast-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/sort.c b/crypto_sign/perk-256-fast-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.c b/crypto_sign/perk-256-fast-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.h b/crypto_sign/perk-256-fast-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.c b/crypto_sign/perk-256-fast-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.h b/crypto_sign/perk-256-fast-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.c b/crypto_sign/perk-256-fast-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.h b/crypto_sign/perk-256-fast-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.c b/crypto_sign/perk-256-fast-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.h b/crypto_sign/perk-256-fast-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/README b/crypto_sign/perk-256-fast-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-256-fast-5/m4/api.h b/crypto_sign/perk-256-fast-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.c b/crypto_sign/perk-256-fast-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.h b/crypto_sign/perk-256-fast-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.c b/crypto_sign/perk-256-fast-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.h b/crypto_sign/perk-256-fast-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common_s.c b/crypto_sign/perk-256-fast-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.c b/crypto_sign/perk-256-fast-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.h b/crypto_sign/perk-256-fast-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-fast-5/m4/data_structures.h b/crypto_sign/perk-256-fast-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.c b/crypto_sign/perk-256-fast-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.h b/crypto_sign/perk-256-fast-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.c b/crypto_sign/perk-256-fast-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.h b/crypto_sign/perk-256-fast-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parameters.h b/crypto_sign/perk-256-fast-5/m4/parameters.h new file mode 100644 index 00000000..443106c3 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parameters.h @@ -0,0 +1,43 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 32 /**< Number of bytes for the expected security level */ +#define PARAM_N1 150 /**< Parameter n of the scheme */ +#define PARAM_M 76 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 57 /**< Parameter tau of the scheme */ + +#define PARAM_N 32 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 5 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_N1_BITSx2 15 /**< Bits needed to store two permutation coefficients */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.c b/crypto_sign/perk-256-fast-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.h b/crypto_sign/perk-256-fast-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c new file mode 100644 index 00000000..39acbcf6 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c @@ -0,0 +1,425 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +// bits needed to store two permutation coefficients +#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) +#define PARAM_N1_BITSx2 13 +#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) +#define PARAM_N1_BITSx2 14 +#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) +#define PARAM_N1_BITSx2 15 +#else +#error PARAM_N1 bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 14) +/** + * @brief store a 7 bit value in a byte array at bit position i*7 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 7 bit value to store + */ +static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7F; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 7: + sb[k + 0] |= val << 1; + break; + } +} + +/** + * @brief load a 7 bit value from a byte array at bit position i*7 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint8_t loaded value + */ +static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { + uint8_t val = 0; + int k = (i * 7) / 8; + switch (i % 8) { + case 0: + val = (sb[k + 0] & 0x7F); + break; + case 1: + val = sb[k + 0] >> 7; + val |= (sb[k + 1] & 0x3F) << 1; + break; + case 2: + val = sb[k + 0] >> 6; + val |= (sb[k + 1] & 0x1F) << 2; + break; + case 3: + val = sb[k + 0] >> 5; + val |= (sb[k + 1] & 0x0F) << 3; + break; + case 4: + val = sb[k + 0] >> 4; + val |= (sb[k + 1] & 0x07) << 4; + break; + case 5: + val = sb[k + 0] >> 3; + val |= (sb[k + 1] & 0x03) << 5; + break; + case 6: + val = sb[k + 0] >> 2; + val |= (sb[k + 1] & 0x01) << 6; + break; + case 7: + val = sb[k + 0] >> 1; + break; + default: + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 13) +/** + * @brief store a 13 bit value in a byte array at bit position i*13 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 13 bit value to store + */ +static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x1FFF; + int k = (i * 13) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 2: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + break; + case 3: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + case 6: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 7: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + break; + } +} + +/** + * @brief load a 13 bit value from a byte array at bit position i*13 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 13) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; + break; + case 1: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x03) << 11; + break; + case 2: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; + break; + case 3: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x01) << 12; + break; + case 5: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; + break; + case 6: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x07) << 10; + break; + case 7: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + break; + } + + return val; +} +#endif + +#if (PARAM_N1_BITSx2 == 15) +/** + * @brief store a 15 bit value in a byte array at bit position i*15 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 15 bit value to store + */ +static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x7FFF; + int k = (i * 15) / 8; + switch (i % 8) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 0] |= val << 7; + sb[k + 1] = val >> 1; + sb[k + 2] = val >> 9; + break; + case 2: + sb[k + 0] |= val << 6; + sb[k + 1] = val >> 2; + sb[k + 2] = val >> 10; + break; + case 3: + sb[k + 0] |= val << 5; + sb[k + 1] = val >> 3; + sb[k + 2] = val >> 11; + break; + case 4: + sb[k + 0] |= val << 4; + sb[k + 1] = val >> 4; + sb[k + 2] = val >> 12; + break; + case 5: + sb[k + 0] |= val << 3; + sb[k + 1] = val >> 5; + sb[k + 2] = val >> 13; + break; + case 6: + sb[k + 0] |= val << 2; + sb[k + 1] = val >> 6; + sb[k + 2] = val >> 14; + break; + case 7: + sb[k + 0] |= val << 1; + sb[k + 1] = val >> 7; + break; + } +} + +/** + * @brief load a 15 bit value from a byte array at bit position i*15 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i * 15) / 8; + uint16_t val = 0; + switch (i % 8) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; + break; + case 1: + val = sb[k + 0] >> 7; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; + val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; + break; + case 2: + val = sb[k + 0] >> 6; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; + val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; + break; + case 3: + val = sb[k + 0] >> 5; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; + val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; + break; + case 4: + val = sb[k + 0] >> 4; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; + val |= ((uint16_t)sb[k + 2] & 0x07) << 12; + break; + case 5: + val = sb[k + 0] >> 3; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; + val |= ((uint16_t)sb[k + 2] & 0x03) << 13; + break; + case 6: + val = sb[k + 0] >> 2; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; + val |= ((uint16_t)sb[k + 2] & 0x01) << 14; + break; + case 7: + val = sb[k + 0] >> 1; + val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; + break; + } + + return val; +} +#endif + +#if (PARAM_Q_BITS != 10) +#error PARAM_Q bit size not supported +#endif + +#if (PARAM_N1_BITSx2 == 13) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_13bit_from_bytearray(sb, i); + *c0 = val % 90; + *c1 = val / 90; +} +#elif (PARAM_N1_BITSx2 == 14) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_7bit_in_bytearray(sb, i * 2 + 0, c0); + store_7bit_in_bytearray(sb, i * 2 + 1, c1); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); + *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); +} +#elif (PARAM_N1_BITSx2 == 15) +static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { + store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); +} + +static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { + uint16_t val = load_15bit_from_bytearray(sb, i); + *c0 = val % 181; + *c1 = val / 181; +} +#else +#error PARAM_N1 bit size not supported +#endif + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; + uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; + store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); + } +} + +/** + * @brief check the permutations to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param responses perk_response_t array of size PARAM_TAU to be checked + * @return int != 0 if a not valid permutation is found + */ +static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { + return 1; + } + } + return 0; +} + +#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) +static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { + uint16_t z2_pi0; + uint16_t z2_pi1; + + load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); + signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; + signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z2_p1_unused_mask) { + // unused bits after the z2_pi != 0 + return EXIT_FAILURE; + } + + if (permutations_not_valid(signature->responses)) { + // loaded permutations are not valid + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h new file mode 100644 index 00000000..b622b736 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h @@ -0,0 +1,53 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +/** + * @brief check the permutation to be valid: + * - coefficients < PARAM_N1 + * - no coefficient duplicates + * + * @param p input permutation to be checked + * @return int + */ +static inline int sig_perk_permutation_not_valid(const perm_t p) { + uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; + + for (unsigned i = 0; i < sizeof(c); i++) { + if (p[i] >= sizeof(c)) + return 1; + if (c[p[i]]) + return 1; + c[p[i]] = 1; + } + return 0; +} + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.c b/crypto_sign/perk-256-fast-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.h b/crypto_sign/perk-256-fast-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/sign.c b/crypto_sign/perk-256-fast-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.c b/crypto_sign/perk-256-fast-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.h b/crypto_sign/perk-256-fast-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/sort.c b/crypto_sign/perk-256-fast-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.c b/crypto_sign/perk-256-fast-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.h b/crypto_sign/perk-256-fast-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.c b/crypto_sign/perk-256-fast-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.h b/crypto_sign/perk-256-fast-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.c b/crypto_sign/perk-256-fast-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.h b/crypto_sign/perk-256-fast-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.c b/crypto_sign/perk-256-fast-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.h b/crypto_sign/perk-256-fast-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/README b/crypto_sign/perk-256-short-3/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-256-short-3/m4/api.h b/crypto_sign/perk-256-short-3/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.c b/crypto_sign/perk-256-short-3/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.h b/crypto_sign/perk-256-short-3/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/bn.c b/crypto_sign/perk-256-short-3/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/bn.h b/crypto_sign/perk-256-short-3/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-256-short-3/m4/common.c b/crypto_sign/perk-256-short-3/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common.h b/crypto_sign/perk-256-short-3/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common_s.c b/crypto_sign/perk-256-short-3/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.c b/crypto_sign/perk-256-short-3/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.h b/crypto_sign/perk-256-short-3/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-short-3/m4/data_structures.h b/crypto_sign/perk-256-short-3/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.c b/crypto_sign/perk-256-short-3/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.h b/crypto_sign/perk-256-short-3/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-256-short-3/m4/keygen.c b/crypto_sign/perk-256-short-3/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/keygen.h b/crypto_sign/perk-256-short-3/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parameters.h b/crypto_sign/perk-256-short-3/m4/parameters.h new file mode 100644 index 00000000..972e38c4 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 32 /**< Number of bytes for the expected security level */ +#define PARAM_N1 146 /**< Parameter n of the scheme */ +#define PARAM_M 75 /**< Parameter m of the scheme */ +#define PARAM_T 3 /**< Parameter t of the scheme */ +#define PARAM_TAU 41 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 8 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 845 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-256-short-3/m4/parsing.c b/crypto_sign/perk-256-short-3/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing.h b/crypto_sign/perk-256-short-3/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.c b/crypto_sign/perk-256-short-3/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.h b/crypto_sign/perk-256-short-3/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.c b/crypto_sign/perk-256-short-3/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.h b/crypto_sign/perk-256-short-3/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-256-short-3/m4/sign.c b/crypto_sign/perk-256-short-3/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.c b/crypto_sign/perk-256-short-3/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.h b/crypto_sign/perk-256-short-3/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/sort.c b/crypto_sign/perk-256-short-3/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.c b/crypto_sign/perk-256-short-3/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.h b/crypto_sign/perk-256-short-3/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.c b/crypto_sign/perk-256-short-3/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.h b/crypto_sign/perk-256-short-3/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.c b/crypto_sign/perk-256-short-3/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.h b/crypto_sign/perk-256-short-3/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.c b/crypto_sign/perk-256-short-3/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.h b/crypto_sign/perk-256-short-3/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/README b/crypto_sign/perk-256-short-5/m4/README new file mode 100644 index 00000000..864ffbb9 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/README @@ -0,0 +1,43 @@ ++=============================================================================+ +| | +| *********************************************** | +| * POST-QUANTUM CRYPTO STANDARDIZATION * | +| *********************************************** | +| | +|=============================================================================| +| | +| Proposal: PERK | +| | +| Submitters (by alphabetical order): | +| - Najwa AARAJ | +| - Slim BETTAIEB | +| [main contact] - Loïc BIDOUX | +| - Alessandro BUDRONI | +| - Victor DYSERYN | +| - Andre ESSER | +| [backup contact] - Philippe GABORIT | +| - Mukul KULKARNI | +| - Victor MATEU | +| - Marco PALUMBI | +| - Lucas PERIN | +| - Jean-Pierre TILLICH | +| | +| Inventors: Same as submitters | +| | +| Developers: Same as submitters | +| | +| Owners: Same as submitters | +| | ++=============================================================================+ + +This archive is a proposal in response to NIST's call for proposal for standar- +dization of quantum-resistant digital signature schemes. + +PERK provides POST-QUANTUM SIGNATURES and targets NIST's +security levels 1, 3, and 5. + +=============================================================================== + +Implementation compliant with version v1.1 of 2023/10/16 +https://pqc-perk.org/ + diff --git a/crypto_sign/perk-256-short-5/m4/api.h b/crypto_sign/perk-256-short-5/m4/api.h new file mode 100644 index 00000000..3478f831 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/api.h @@ -0,0 +1,26 @@ + +/** + * @file api.h + * @brief NIST SIGN API + */ + +#ifndef SIG_PERK_API_H +#define SIG_PERK_API_H + +#include +#include "parameters.h" + +#define CRYPTO_ALGNAME "PERK" + +#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES +#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES +#define CRYPTO_BYTES SIGNATURE_BYTES + +// As a technicality, the public key is appended to the secret key in order to respect the NIST API. +// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES + +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); + +#endif diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.c b/crypto_sign/perk-256-short-5/m4/arithmetic.c new file mode 100644 index 00000000..3b9f86a5 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/arithmetic.c @@ -0,0 +1,154 @@ + +/** + * @file arithmetic.c + * @brief Implementation of arithmetic related functions + */ + +#include "arithmetic.h" +#include +#include +#include "permutation.h" +#include "symmetric.h" + +static inline int16_t caddq(int16_t a) { + a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests + return a; +} + +static uint16_t multiplicativeInverse(uint16_t a) { + // assume a != 0 + // compute a^(q-2) mod q + uint16_t result = 1; + uint16_t exponent = PARAM_Q - 2; + + while (exponent > 0) { + if ((exponent & 0x1) == 1) { + result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); + } + a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); + exponent >>= 1; + } + + return result; +} + +int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { + int rank = 0; + int row, col; + + vect1_t x[PARAM_T]; + memcpy(x, in, sizeof(vect1_t) * PARAM_T); + for (col = 0; col < PARAM_N1; col++) { + int pivot_found = 0; + + // Find a non-zero pivot in the current column + for (int i = rank; i < PARAM_T; i++) { + if (x[i][col] != 0) { + row = i; + pivot_found = 1; + break; + } + } + + if (pivot_found) { + // Swap the current row with the row containing the pivot + for (int i = 0; i < PARAM_N1; i++) { + int temp = x[rank][i]; + x[rank][i] = x[row][i]; + x[row][i] = temp; + } + + // Perform row operations to eliminate entries below the pivot + for (row = rank + 1; row < PARAM_T; row++) { + uint16_t multiplier = + sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); + for (int i = col; i < PARAM_N1; i++) { + x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); + } + } + rank++; + } + if (rank == PARAM_T) + break; + } + return rank; +} + +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { + for (uint16_t i = 0; i < PARAM_N1; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int i = 0, rank; + do { + while (i < PARAM_N1 * PARAM_T) { + int j = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { + output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; + if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample + i++; + } + } + } + // make sure the vectors x are linearly independent + rank = sig_perk_vect1_compute_rank(output); + } while (rank != PARAM_T); +} + +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + // we assume v1 and v2 already reduced + o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); + } +} + +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); + } +} + +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { + for (uint16_t i = 0; i < PARAM_M; ++i) { + output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); + } +} + +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { + uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; + // generate randomness + int j = 0; + while (j < PARAM_M * PARAM_N1) { + int k = 0; + sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; + if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { + uint32_t tmp = 0; + for (int i = 0; i < PARAM_M; ++i) { + for (int j = 0; j < PARAM_N1; ++j) { + tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); + } + output[i] = sig_perk_barrett_reduce32(tmp); + tmp = 0; + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.h b/crypto_sign/perk-256-short-5/m4/arithmetic.h new file mode 100644 index 00000000..06d8d43b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/arithmetic.h @@ -0,0 +1,156 @@ + +/** + * @file arithmetic.h + * @brief Header file for arithmetic.c + */ + +#ifndef SIG_PERK_ARITHMETIC_H +#define SIG_PERK_ARITHMETIC_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define SHBIT16 25 +#define SHBIT32 41 + +/** + * @brief Vector vect1_t + * + * This structure contains a vector of size PARAM_N1 + */ +typedef uint16_t vect1_t[PARAM_N1]; + +/** + * @brief Vector vect2_t + * + * This structure contains a vector of size PARAM_M + */ +typedef uint16_t vect2_t[PARAM_M]; + +/** + * @brief Matrix mat_t + * + * This structure contains a matrix represented as a vector of vectors of type vect1_t + */ +typedef vect1_t mat_t[PARAM_M]; + +/** + * @brief perform barrett reduction on a 16 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) + * + * @param a 16 bit input + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { + uint16_t t; + const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); + + t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief perform barrett reduction on a 32 bit input value + * output range 0 <= out < PARAM_Q + * input range: + * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) + * + * @param a 32 bit input value + * @return uint16_t output + */ +static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { + uint32_t t; + const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); + + t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests + t *= PARAM_Q; + return (uint16_t)(a - t); +} + +/** + * @brief Add in Fq two vect1_t vectors + * + * @details The prototype of this function differs from the others in this file due to + * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); + +/** + * @brief Multiplication in Fq of a vect1_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect1_t + */ +void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); + +/** + * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix + * formed by these. Used to test the linear dependence. + * + * @param [in] x list of vectors to be seen as a matrix + * @returns the rank of the matrix + */ +int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); + +/** + * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq + * + * @param [out] output an array of vectors vect1_t containing the result + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); + +/** + * @brief Add in Fq two vect2_t vectors + * + * @param [out] o a vector containing the result + * @param [in] v1 a vector + * @param [in] v2 a vector + */ +void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Subtract in Fq two vect2_t vectors + * + * @param [out] o vector containing the result + * @param [in] v1 vector + * @param [in] v2 vector + */ +void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); + +/** + * @brief Multiplication in Fq of a vect2_t vector by a scalar + * + * @param [out] output vector containing the result + * @param [in] scalar a scalar in Fq + * @param [in] input a vector of type vect2_t + */ +void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); + +/** + * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq + * + * @param [out] m_output a matrix + * @param [out,in] prg PRG state to squeeze + */ +void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); + +/** + * @brief Compute a matrix vector multiplication in Fq + * + * @param [out] output a vector + * @param [in] m_input a matrix + * @param [in] v_input a vector + */ +void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/bn.c b/crypto_sign/perk-256-short-5/m4/bn.c new file mode 100644 index 00000000..b676feb3 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/bn.c @@ -0,0 +1,474 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include +#include "bn.h" + + + +/* Functions for shifting number in-place. */ +static void _lshift_one_bit(struct bn* a); +static void _rshift_one_bit(struct bn* a); +static void _lshift_word(struct bn* a, int nwords); +static void _rshift_word(struct bn* a, int nwords); + + + +/* Public / Exported functions. */ +void bignum_init(struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + n->array[i] = 0; + } +} + + +void bignum_from_int(struct bn* n, DTYPE_TMP i) +{ + require(n, "n is null"); + + bignum_init(n); + + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE +#if (WORD_SIZE == 1) + n->array[0] = (i & 0x000000ff); + n->array[1] = (i & 0x0000ff00) >> 8; + n->array[2] = (i & 0x00ff0000) >> 16; + n->array[3] = (i & 0xff000000) >> 24; +#elif (WORD_SIZE == 2) + n->array[0] = (i & 0x0000ffff); + n->array[1] = (i & 0xffff0000) >> 16; +#elif (WORD_SIZE == 4) + n->array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n->array[1] = tmp; +#endif +#endif +} + + +int bignum_to_int(struct bn* n) +{ + require(n, "n is null"); + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n->array[0]; + ret += n->array[1] << 8; + ret += n->array[2] << 16; + ret += n->array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n->array[0]; + ret += n->array[1] << 16; +#elif (WORD_SIZE == 4) + ret += (int)n->array[0]; +#endif + + return ret; +} + +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; + carry = (tmp > MAX_VAL); + c->array[i] = (tmp & MAX_VAL); + } +} + + +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b->array[i] + borrow; + res = (tmp1 - tmp2); + c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } +} + + +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + bignum_init(c); + + if (bignum_is_zero(a)) {return;} + if (bignum_is_zero(b)) {return;} + + struct bn tmp; + struct bn max_val; + bignum_from_int(&max_val, MAX_VAL); + + struct bn a1; + DTYPE_TMP a0; + struct bn b1; + DTYPE_TMP b0; + struct bn z0; + struct bn z1; + struct bn z2; + + bignum_rshift(a, &a1, WORD_SIZE*8); + bignum_rshift(b, &b1, WORD_SIZE*8); + a0 = (DTYPE_TMP)(a->array[0]); + b0 = (DTYPE_TMP)(b->array[0]); + DTYPE_TMP z0_small = a0*b0; + + bignum_init(&z0); + z0.array[0] = z0_small & MAX_VAL; + z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); + if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { + bignum_assign(c, &z0); + return; + } + bignum_mul(&a1, &b1, &z2); + struct bn a0_big; + struct bn b0_big; + bignum_from_int(&a0_big, a0); + bignum_from_int(&b0_big, b0); + + struct bn tmpa; + struct bn tmpb; + struct bn tmpz1; + bignum_add(&a1, &a0_big, &tmpa); + bignum_add(&b1, &b0_big, &tmpb); + bignum_mul(&tmpa, &tmpb, &tmpz1); + bignum_sub(&tmpz1, &z2, &tmpa); + bignum_sub(&tmpa, &z0, &z1); + + bignum_lshift(&z2, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z1, c); + bignum_lshift(c, &tmp, WORD_SIZE*8); + bignum_add(&tmp, &z0, c); +} + + +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn current; + struct bn denom; + struct bn tmp; + + bignum_from_int(¤t, 1); // int current = 1; + bignum_assign(&denom, b); // denom = b + bignum_assign(&tmp, a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { + { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) + { + overflow = true; + break; + } + _lshift_one_bit(¤t); // current <<= 1; + _lshift_one_bit(&denom); // denom <<= 1; + } + if (!overflow) + { + _rshift_one_bit(&denom); // denom >>= 1; + _rshift_one_bit(¤t); // current >>= 1; + } + bignum_init(c); // int answer = 0; + + while (!bignum_is_zero(¤t)) // while (current != 0) + { + if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) + { + bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; + bignum_or(c, ¤t, c); // answer |= current; + } + _rshift_one_bit(¤t); // current >>= 1; + _rshift_one_bit(&denom); // denom >>= 1; + } // return answer; +} + + +void bignum_lshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b->array[i] <<= nbits; + } +} + + +void bignum_rshift(const struct bn* a, struct bn* b, int nbits) +{ + require(a, "a is null"); + require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bignum_assign(b, a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) + { + _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) + { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b->array[i] >>= nbits; + } + +} + + +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) +{ + /* + Take divmod and throw away div part + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + bignum_divmod(a,b,&tmp,c); +} + +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) +{ + /* + Puts a%b in d + and a/b in c + + mod(a,b) = a - ((a / b) * b) + + example: + mod(8, 3) = 8 - ((8 / 3) * 3) = 2 + */ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + struct bn tmp; + + /* c = (a / b) */ + bignum_div(a, b, c); + + /* tmp = (c * b) */ + bignum_mul(c, b, &tmp); + + /* c = a - tmp */ + bignum_sub(a, &tmp, d); +} + +void bignum_or(struct bn* a, struct bn* b, struct bn* c) +{ + require(a, "a is null"); + require(b, "b is null"); + require(c, "c is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + c->array[i] = (a->array[i] | b->array[i]); + } +} + +int bignum_cmp(const struct bn *a, const struct bn *b) +{ + require(a, "a is null"); + require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do + { + i -= 1; /* Decrement first, to start with last array element */ + if (a->array[i] > b->array[i]) + { + return LARGER; + } + else if (a->array[i] < b->array[i]) + { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(const struct bn* n) +{ + require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + if (n->array[i]) + { + return 0; + } + } + + return 1; +} + +void bignum_assign(struct bn* dst, const struct bn* src) +{ + require(dst, "dst is null"); + require(src, "src is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + dst->array[i] = src->array[i]; + } +} + + +/* Private / Static functions. */ +static void _rshift_word(struct bn* a, int nwords) +{ + /* Naive method: */ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + if (nwords >= BN_ARRAY_SIZE) + { + for (i = 0; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } + return; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) + { + a->array[i] = a->array[i + nwords]; + } + for (; i < BN_ARRAY_SIZE; ++i) + { + a->array[i] = 0; + } +} + + +static void _lshift_word(struct bn* a, int nwords) +{ + require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) + { + a->array[i] = a->array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) + { + a->array[i] = 0; + } +} + + +static void _lshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) + { + a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a->array[0] <<= 1; +} + + +static void _rshift_one_bit(struct bn* a) +{ + require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) + { + a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a->array[BN_ARRAY_SIZE - 1] >>= 1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/bn.h b/crypto_sign/perk-256-short-5/m4/bn.h new file mode 100644 index 00000000..c0debe59 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/bn.h @@ -0,0 +1,117 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +*/ + +#include +#include + + +/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (64 / WORD_SIZE) +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && msg) + + +/* Data-holding structure: array of DTYPEs */ +struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +}; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + + + +/* Initialization functions: */ +void bignum_init(struct bn* n); +void bignum_from_int(struct bn* n, DTYPE_TMP i); +int bignum_to_int(struct bn* n); + +/* Basic arithmetic operations: */ +void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ +void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ +void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ +void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ +void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ +void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + +/* Bitwise operations: */ +void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ +void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ +void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ + +/* Special operators and comparison */ +int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(const struct bn* n); /* For comparison with zero */ +void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ + + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/crypto_sign/perk-256-short-5/m4/common.c b/crypto_sign/perk-256-short-5/m4/common.c new file mode 100644 index 00000000..0ba860c9 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common.c @@ -0,0 +1,102 @@ + +/** + * @file common.c + * @brief Common functions + */ + +#include "common.h" +#include +#include "crypto_memset.h" +#include "symmetric.h" + +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} + +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta) { + // To make easier the times4 optimized implementation + // we reinitialise the PRNG with a different domain separator, thus we use + // PRG1 to sample the pi_i and PRG2 to sample the v_i + sig_perk_prg_init(state, PRG2, salt, theta); + int j = 0; + while (j < PARAM_N1) { + int k = 0; + sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); + while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { + v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; + if (v_i[j] < PARAM_Q) { // accept the sample + j++; + } + } + } +} + +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, + const perk_theta_seeds_tree_t theta_tree) { + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { + vect1_t tmp_vect; + perm_t tmp_compose_perm; + + sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); + sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); + for (int i = 1; i < PARAM_N - 1; ++i) { + sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); + sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); + sig_perk_vect1_add(o, o, tmp_vect); + } + sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); +} + +// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { + for (int i = 0; i < PARAM_N; ++i) { + sig_perk_hash_state_t state; + uint8_t idx = i; + if (i == 0) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); + } else { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); + } + } +} + +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { + sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); + sig_perk_perm_gen_pi_1(instance->pi_i, pi); + sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); +} + +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v) { + sig_perk_hash_state_t state; + vect2_t tmp; + sig_perk_mat_vect_mul(tmp, H, v); + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); + sig_perk_hash_final(&state, cmt_1, H0); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common.h b/crypto_sign/perk-256-short-5/m4/common.h new file mode 100644 index 00000000..649f2dc8 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common.h @@ -0,0 +1,109 @@ + +/** + * @file common.h + * @brief Header file for common.c + */ + +#ifndef SIG_PERK_COMMON_H +#define SIG_PERK_COMMON_H + +#include "data_structures.h" +#include "permutation.h" +#include "symmetric.h" + +/** + * @brief Generate a set of pi_i and v_i + * + * @param [out] pi_i a pointer to permutations + * @param [out] v_i a pointer to vectors v_i + * @param [in] salt a salt + * @param [in] theta_tree a tree of seeds + */ +void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); + +/** + * @brief Generate one pi_i + * + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate one pi_i and compose with pi_comp + * + * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one + * @param [out] pi_i a pointer to the permutation sampled + * @param [in] salt a salt + * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta); + +/** + * @brief Generate one v_i + * + * @param [out] v_i + * @param [in] salt a salt + * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. + * must be erased by the caller + * @param [out,in] state state for the prg used to sample randomness. + * must be erased by the caller + * @param [in] theta the seed for the prg + */ +void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], + sig_perk_prg_state_t *state, const theta_t theta); + +/** + * @brief Generate the vector v + * + * @param [out] o a variable containing the vector v + * @param [in] pi_i a pointer to permutations pi_i + * @param [in] v_i a pointer to vectors v_i + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); + +/** + * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance pointer to struct instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + */ +void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); + +/** + * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] pi a variable containing the secret permutation pi + */ +void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); + +/** + * @brief Compute commitment cmt_1 for one round of the scheme + * + * @param [out,in] instance a pointer to an instance + * @param [in] salt a salt + * @param [in] tau an integer that is the index in 0,...,tau + * @param [in] H a variable containing the public matrix H + * @param [in] v a variable containing to vectors v_i + */ +void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, + const vect1_t v); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common_s.c b/crypto_sign/perk-256-short-5/m4/common_s.c new file mode 100644 index 00000000..9bbb7b67 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common_s.c @@ -0,0 +1,42 @@ + +/** + * @file common_s.c + * @brief Streamlined common functions + */ + +#include "common.h" +#include "djbsort.h" +#include "permutation.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint8_t)(0xFF & buffer[i]); + pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); + } + return EXIT_SUCCESS; +} + +void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, + uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, + const theta_t theta) { + sig_perk_prg_init(state, PRG1, salt, theta); + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { + sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); + } +} diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.c b/crypto_sign/perk-256-short-5/m4/crypto_memset.c new file mode 100644 index 00000000..531c15a9 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/crypto_memset.c @@ -0,0 +1,7 @@ +/** + * @file memset.c + * @brief Implementation of safe memset + */ +#include + +void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.h b/crypto_sign/perk-256-short-5/m4/crypto_memset.h new file mode 100644 index 00000000..0612f683 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/crypto_memset.h @@ -0,0 +1,18 @@ +/** + * @file memset.h + * @brief Header file for memset.c + */ + +#ifndef PERK_CRYPTO_MEMSET_H +#define PERK_CRYPTO_MEMSET_H + +#include + +/** + * safer call to memset https://github.com/veorq/cryptocoding#problem-4 + */ +extern void *(*volatile memset_volatile)(void *, int, size_t); + +#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) + +#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-short-5/m4/data_structures.h b/crypto_sign/perk-256-short-5/m4/data_structures.h new file mode 100644 index 00000000..b303c778 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/data_structures.h @@ -0,0 +1,131 @@ + +/** + * @file data_structures.h + * @brief common data structures for the scheme + */ + +#ifndef SIG_PERK_DATA_STRUCTURES_H +#define SIG_PERK_DATA_STRUCTURES_H + +#include +#include "arithmetic.h" +#include "parameters.h" +#include "permutation.h" +#include "symmetric.h" +#include "theta_tree.h" + +/** + * @brief Commitment cmt_t + * + * This structure contains a commitment + */ +typedef uint8_t cmt_t[COMMITMENT_BYTES]; + +/** @struct perk_public_key_t + * @brief This structure contains the public key + * @var perk_public_key_t::seed + * Member 'seed' is an array of bytes used to generate the public key + * @var perk_public_key_t::H + * Member 'H' is a matrix + * @var perk_public_key_t::x + * Member 'x' is a vector of vectors + * @var perk_public_key_t::y + * Member 'y' is a vector of vectors + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + mat_t H; + vect1_t x[PARAM_T]; + vect2_t y[PARAM_T]; +} perk_public_key_t; + +/** @struct perk_private_key_t + * @brief This structure contains the private key + * @var perk_private_key_t::seed + * Member 'seed' is an array of bytes used to generate the private key + * @var perk_private_key_t::pi + * Member 'pi' is a permutation + * @var perk_private_key_t::pk_bytes + * Member 'pk_bytes' is an array of bytes that contain the public key + */ +typedef struct { + uint8_t seed[SEED_BYTES]; + perm_t pi; + uint8_t pk_bytes[PUBLIC_KEY_BYTES]; +} perk_private_key_t; + +/** @struct perk_instance_t + * @brief This structure contains an instance of one round of the scheme + * @var perk_instance_t::theta_tree + * Member 'theta_tree' is a seed tree containing theta and the theta_i + * @var perk_instance_t::pi_i + * Member 'pi_i' is a permutation + * @var perk_instance_t::v_i + * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i + * @var perk_instance_t::s_i + * Member 's_i' is an array of vectors + * @var perk_instance_t::cmt_1_i + * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down + * to element 0. + * @var perk_instance_t::cmt_1 + * Member 'cmt_1' is a commitment + */ +typedef struct { + perk_theta_seeds_tree_t theta_tree; + perm_t pi_i[PARAM_N]; + // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; + vect1_t *v_i; + vect1_t s_i[PARAM_N + 1]; + cmt_t cmt_1_i[PARAM_N]; + cmt_t cmt_1; +} perk_instance_t; + +/** + * @brief initialize an array of "perk_instance_t" elements + * + * @param [out,in] instances array of perk_instance_t elements + * @param [in] elements number of elements to be initialized + */ +static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { + for (int i = 0; i < elements; i++) { + instances[i].v_i = &(instances[i].s_i[1]); + } +} + +/** @struct perk_response_t + * @brief This structure contains the response + * @var perk_response_t::z1 + * Member 'z1' is a vector + * @var perk_response_t::z2_pi + * Member 'z2_pi' is a permutation + * @var perk_response_t::z2_theta + * Member 'z2_theta' is an array of theta_t + * @var perk_response_t::cmt_1_alpha + * Member 'cmt_1_alpha' is commitment + */ +typedef struct { + vect1_t z1; + perm_t z2_pi; + theta_t z2_theta[THETA_TREE_LEVELS]; + cmt_t cmt_1_alpha; +} perk_response_t; + +/** @struct perk_signature_t + * @brief This structure contains the signature + * @var perk_signature_t::salt + * Member 'salt' is a salt + * @var perk_signature_t::h1 + * Member 'h1' is a digest + * @var perk_signature_t::h2 + * Member 'h2' is a digest + * @var perk_signature_t::responses + * Member 'responses' is an array of perk_response_t + */ +typedef struct { + salt_t salt; + digest_t h1; + digest_t h2; + perk_response_t responses[PARAM_TAU]; +} perk_signature_t; + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.c b/crypto_sign/perk-256-short-5/m4/djbsort.c new file mode 100644 index 00000000..62e49c57 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/djbsort.c @@ -0,0 +1,12 @@ +#include "djbsort.h" + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +void uint32_sort(uint32_t *x,size_t n) +{ + size_t j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + int32_sort((int32_t *) x,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.h b/crypto_sign/perk-256-short-5/m4/djbsort.h new file mode 100644 index 00000000..92f51643 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/djbsort.h @@ -0,0 +1,16 @@ + +/** + * @file djbsort.h + * @brief Header file for sorting functions + */ + +#ifndef DJB_SORT_H +#define DJB_SORT_H + +#include +#include + +extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); +extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); + +#endif diff --git a/crypto_sign/perk-256-short-5/m4/keygen.c b/crypto_sign/perk-256-short-5/m4/keygen.c new file mode 100644 index 00000000..384e277e --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/keygen.c @@ -0,0 +1,51 @@ + +/** + * @file keygen.c + * @brief Implementation of key generation + */ + +#include "keygen.h" +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "parameters.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "verbose.h" + +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { + vect1_t tmp; + // sample seeds + randombytes(pk->seed, sizeof(pk->seed)); + randombytes(sk->seed, sizeof(sk->seed)); + + // sample private key + sig_perk_perm_set_random(sk->pi, sk->seed); + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + // compute y + for (int i = 0; i < PARAM_T; i++) { + // compute tmp = pi(x) + sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); + sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); + } + + sig_perk_public_key_to_bytes(sk->pk_bytes, pk); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); + SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); + SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/keygen.h b/crypto_sign/perk-256-short-5/m4/keygen.h new file mode 100644 index 00000000..7d84ee2f --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/keygen.h @@ -0,0 +1,21 @@ + +/** + * @file keygen.h + * @brief Header file for keygen.c + */ + +#ifndef SIG_PERK_KEYGEN_H +#define SIG_PERK_KEYGEN_H + +#include "data_structures.h" + +/** + * @brief Generate a key pair + * + * @param [out] pk a pointer to public key structure + * @param [out] sk a pointer to private key structure + * @return int 0 if the key generation is successful + */ +uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parameters.h b/crypto_sign/perk-256-short-5/m4/parameters.h new file mode 100644 index 00000000..03b2fa36 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parameters.h @@ -0,0 +1,46 @@ + +/** + * @file parameters.h + * @brief Parameters of the PERK scheme + */ + +#ifndef SIG_PERK_PARAMETER_H +#define SIG_PERK_PARAMETER_H + +#define SECURITY_BYTES 32 /**< Number of bytes for the expected security level */ +#define PARAM_N1 150 /**< Parameter n of the scheme */ +#define PARAM_M 76 /**< Parameter m of the scheme */ +#define PARAM_T 5 /**< Parameter t of the scheme */ +#define PARAM_TAU 37 /**< Parameter tau of the scheme */ + +#define PARAM_N 256 /**< Parameter N of the scheme */ +#define THETA_TREE_LEVELS 8 /**< The number of levels of the theta tree i.e log2(PARAM_N) */ + +#define PARAM_Q 1021 /**< Parameter q of the scheme */ +#define PARAM_Q_BITS 10 /**< Number of bits needed to represent PARAM_Q */ + +#define PARAM_N_MASK ((1U << THETA_TREE_LEVELS) - 1) /**< Mask for bits representing PARAM_N */ +#define PARAM_Q_MASK ((1U << PARAM_Q_BITS) - 1) /**< Mask for bits representing PARAM_Q */ + +#define PARAM_RANK_UNRANK_K 8 /**< Parameter for rank/unrank compression - log2(PARAM_N1) */ +#define PARAM_PERM_COMPRESSION_BITS 873 /**< Bits needed for Lehemr compression - log2(PARAM_N1!) */ +#define PARAM_PERM_COMPRESSION_BYTES \ + (((PARAM_PERM_COMPRESSION_BITS - 1) / 8) + 1) /**< Bytes needed for Lehemr compression */ + +#define SEED_BYTES SECURITY_BYTES /**< Seed size used in the scheme */ +#define SALT_BYTES (2 * SECURITY_BYTES) /**< Salt size used in the scheme */ +#define HASH_BYTES (2 * SECURITY_BYTES) /**< Hash size used in the scheme */ +#define COMMITMENT_BYTES HASH_BYTES /**< Commitment size used in the scheme */ + +#define PUBLIC_KEY_BYTES (SEED_BYTES + ((PARAM_M * PARAM_Q_BITS * PARAM_T + 7) / 8)) /**< Public key size */ +#define PRIVATE_KEY_BYTES (SEED_BYTES + PUBLIC_KEY_BYTES) /**< Private key size */ + +#define SIGNATURE_BYTES \ + (SALT_BYTES + (2 * COMMITMENT_BYTES) + (COMMITMENT_BYTES + SEED_BYTES * THETA_TREE_LEVELS) * PARAM_TAU + \ + ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) + \ + (PARAM_PERM_COMPRESSION_BYTES * PARAM_TAU)) /**< Signature size */ + +#define EXIT_FAILURE 1 /**< Exit code in case of failure */ +#define EXIT_SUCCESS 0 /**< Exit code in case of success */ + +#endif // SIG_PERK_PARAMETER_H diff --git a/crypto_sign/perk-256-short-5/m4/parsing.c b/crypto_sign/perk-256-short-5/m4/parsing.c new file mode 100644 index 00000000..0d0deda5 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing.c @@ -0,0 +1,217 @@ + +/** + * @file parsing.c + * @brief Implementation of parsing functions + */ + +#include "parsing.h" +#include "parameters.h" +#include "parsing_permutations.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "symmetric.h" + +/** + * @brief store a 10 bit value in a byte array at bit position i*10 + * must be called sequentially with increasing index + * + * @param sb byte array pointer + * @param i position in the byte array + * @param val 10 bit value to store + */ +static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { + val &= 0x3FF; + int k = (i / 4) * 5; + switch (i % 4) { + case 0: + sb[k + 0] = val; + sb[k + 1] = val >> 8; + break; + case 1: + sb[k + 1] |= val << 2; + sb[k + 2] = val >> 6; + break; + case 2: + sb[k + 2] |= val << 4; + sb[k + 3] = val >> 4; + break; + case 3: + sb[k + 3] |= val << 6; + sb[k + 4] = val >> 2; + break; + default: + break; + } +} + +/** + * @brief load a 10 bit value from a byte array at bit position i*10 + * + * @param sb byte array pointer + * @param i position in the byte array + * @return uint16_t loaded value + */ +static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { + int k = (i / 4) * 5; + uint16_t val = 0; + switch (i % 4) { + case 0: + val = sb[k + 0]; + val |= ((uint16_t)sb[k + 1] & 0x3) << 8; + break; + case 1: + val = sb[k + 1] >> 2; + val |= ((uint16_t)sb[k + 2] & 0xF) << 6; + break; + case 2: + val = sb[k + 2] >> 4; + val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; + break; + case 3: + val = sb[k + 3] >> 6; + val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; + break; + default: + break; + } + + return val; +} + +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { + memcpy(sk_bytes, sk->seed, SEED_BYTES); + memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); +} + +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { + memcpy(sk->seed, sk_bytes, SEED_BYTES); + memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); + sig_perk_perm_set_random(sk->pi, sk->seed); +} + +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { + memcpy(pk_bytes, pk->seed, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); + } +} + +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { + memcpy(pk->seed, pk_bytes, SEED_BYTES); + for (int i = 0; i < PARAM_M * PARAM_T; i++) { + uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); + if (y >= PARAM_Q) { + // y out of range + return EXIT_FAILURE; + } + pk->y[i / PARAM_M][i % PARAM_M] = y; + } + + sig_perk_prg_state_t prg; + // initialize prg + sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); + + // Generate H and x + sig_perk_mat_set_random(pk->H, &prg); + sig_perk_vect1_set_random_list(pk->x, &prg); + + return EXIT_SUCCESS; +} + +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { + sig_perk_prg_state_t h1_prg_state; + sig_perk_prg_state_t h2_prg_state; + uint16_t tmp_kappa; + uint16_t tmp_alpha; + + // generate first challenge + sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenges[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } + // generate second challenge + sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenges[i].alpha = tmp_alpha; + } +} + +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { + memcpy(sb, signature->salt, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(sb, signature->h1, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(sb, signature->h2, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; + store_10bit_in_bytearray(sb, i, z1); + } + sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; + + // compress and store permutations + sig_perk_signature_perm_to_bytes(sb, signature); +} + +#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) +static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); + +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { + memcpy(signature->salt, sb, sizeof(salt_t)); + sb += sizeof(salt_t); + memcpy(signature->h1, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + memcpy(signature->h2, sb, sizeof(digest_t)); + sb += sizeof(digest_t); + + for (int i = 0; i < PARAM_TAU; i++) { + memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); + sb += sizeof(cmt_t); + memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); + sb += sizeof(theta_t) * THETA_TREE_LEVELS; + } + + for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { + uint16_t z1 = load_10bit_from_bytearray(sb, i); + if (z1 >= PARAM_Q) { + // z1 out of range + return EXIT_FAILURE; + } + signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; + } + sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; + + // cppcheck-suppress knownConditionTrueFalse + // cppcheck-suppress unmatchedSuppression + if (sb[0] & z1_unused_mask) { + // unused bits after the z1 != 0 + return EXIT_FAILURE; + } + + sb += 1; + + // Load and decompress permutations + return sig_perk_signature_perm_from_bytes(signature, sb); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing.h b/crypto_sign/perk-256-short-5/m4/parsing.h new file mode 100644 index 00000000..35282479 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing.h @@ -0,0 +1,75 @@ + +/** + * @file parsing.h + * @brief Header file for parsing.c + */ + +#ifndef SIG_PERK_PARSING_H +#define SIG_PERK_PARSING_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Parse a private key into a string + * + * As technicality, the public key is appended to the private key in order to respect NIST API. + * + * @param [out] sk_bytes a string containing the private key + * @param [in] sk a pointer to private key structure + */ +void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); + +/** + * @brief Parse a private key from a string + * + * @param [out] sk a pointer to private key structure + * @param [in] sk_bytes a string containing the private key + */ +void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); + +/** + * @brief Parse a public key into a string + * + * @param [out] pk_bytes a string containing the public key + * @param [in] pk a pointer to public key structure + */ +void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); + +/** + * @brief Parse a public key from a string + * + * @param [out] pk a pointer to public key structure + * @param [in] pk_bytes a string containing the public key + */ +int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); + +/** + * @brief Generate challenges based on Fiat-Shamir transform + * + * @param [out] challenges an array containing the challenges for Pall the rounds + * @param [out] h1 a variable containing the digest h1 + * @param [out] h2 a variable containing the digest h2 + */ +void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); + +/** + * @brief Parse a signature into a string + * + * @param [out] sb a string containing the signature + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); + +/** + * @brief Parse a signature from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb a string containing the signature + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.c b/crypto_sign/perk-256-short-5/m4/parsing_permutations.c new file mode 100644 index 00000000..6edb9a7e --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing_permutations.c @@ -0,0 +1,111 @@ + +/** + * @file parsing_permutations.c + * @brief Implementation of parsing functions + */ + +#include "parsing_permutations.h" +#include "parameters.h" + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "rank_unrank_table.h" +#include "symmetric.h" + +#define PARAM_RANK_UNRANK_LEN_T \ + ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ + +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { + struct bn mul, code, tmp; + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + bignum_init(&code); + for (int i = 0; i < PARAM_N1; ++i) { + uint8_t ctr = in_p[i]; + uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + if (node & 0x1) { + ctr -= T[(node >> 1) << 1]; + } + T[node] += 1; + node = node >> 1; + } + T[node] += 1; + bignum_from_int(&tmp, PARAM_N1 - i); + bignum_mul(&code, &tmp, &mul); + bignum_from_int(&tmp, ctr); + bignum_add(&mul, &tmp, &code); + } + + memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); + memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); +} + +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { + struct bn code, tmp, tmp2, tmp3; + bignum_init(&code); + + memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); + + // validate the permutation encoding to be < n! + if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { + return EXIT_FAILURE; + } + + bignum_mod(&code, &factorial[PARAM_N1], &tmp); + bignum_assign(&tmp3, &tmp); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); + out_p[0] = bignum_to_int(&tmp); + + for (int i = 1; i < PARAM_N1 - 1; ++i) { + bignum_assign(&tmp3, &tmp2); + bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); + out_p[i] = bignum_to_int(&tmp); + } + + bignum_div(&tmp2, &factorial[0], &tmp); + out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); + + uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; + for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { + for (int j = 0; j < (1 << i); ++j) { + T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); + } + } + + for (int i = 0; i < PARAM_N1; ++i) { + int digit = out_p[i]; + uint16_t node = 1; + for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { + T[node] -= 1; + node <<= 1; + if (digit >= T[node]) { + digit -= T[node]; + node += 1; + } + } + T[node] = 0; + out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); + } + + return EXIT_SUCCESS; +} + +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { + for (int i = 0; i < (PARAM_TAU); i++) { + sig_perk_perm_encode(signature->responses[i].z2_pi, sb); + sb += PARAM_PERM_COMPRESSION_BYTES; + } +} + +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { + for (int i = 0; i < PARAM_TAU; i++) { + if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + sb += PARAM_PERM_COMPRESSION_BYTES; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.h b/crypto_sign/perk-256-short-5/m4/parsing_permutations.h new file mode 100644 index 00000000..52c64e70 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing_permutations.h @@ -0,0 +1,65 @@ + +/** + * @file parsing_permutations.h + * @brief Header file for parsing_permutations.c + */ + +#ifndef SIG_PERK_PARSING_PERMUTATIONS_H +#define SIG_PERK_PARSING_PERMUTATIONS_H + +#include +#include "data_structures.h" +#include "parameters.h" +#include "signature.h" + +/** + * @brief Permutation rank encoding. Encode a permutation into a bytearray. + * + * @param in_p input permutation + * @param out_buff output buffer byte string + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); + +/** + * @brief Permutation unrank decoding. Decode a bytearray into a permutation. + * + * @param in_buff input buffer byte string + * @param out_p output permutation + * @return EXIT_SUCCESS or EXIT_FAILURE + */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +__attribute__((no_sanitize("memory"))) +#endif +#if __has_feature(address_sanitizer) +__attribute__((no_sanitize("address"))) +#endif +#endif +int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); + +/** + * @brief Parse the permutations into a string + * + * @param [out] sb output string + * @param [in] signature a pointer to signature structure + */ +void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); + +/** + * @brief Parse the permutations from a string + * + * @param [out] signature a pointer to signature structure + * @param [in] sb input string containing the permutations + * @return int 0 if the parsing is successful and 1 otherwise + */ +int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.c b/crypto_sign/perk-256-short-5/m4/permutation.c new file mode 100644 index 00000000..09df4c2e --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/permutation.c @@ -0,0 +1,91 @@ + +/** + * @file permutation.c + * @brief Implementation of permutation related functions. + * + * This implementation uses memory table lookup + * and is constant time only for CPU without RAM cache like Arm M4 CPUs + */ + +#include "permutation.h" +#include +#include "crypto_memset.h" +#include "djbsort.h" +#include "symmetric.h" + +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { + uint32_t buffer[PARAM_N1]; + // Use 16 bits for randomness + for (int i = 0; i < PARAM_N1; i++) { + buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; + } + // sort + uint32_sort(buffer, PARAM_N1); + // check that no double random values were produced + for (int i = 1; i < PARAM_N1; i++) { + if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { + return EXIT_FAILURE; + } + } + // extract permutation from buffer + for (int i = 0; i < PARAM_N1; i++) { + p[i] = (uint16_t)(buffer[i]); + } + return EXIT_SUCCESS; +} + +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { + uint16_t rnd_buff[PARAM_N1]; + sig_perk_prg_state_t prg; + sig_perk_prg_init(&prg, PRG1, NULL, seed); + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + + while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { + sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); + } + memset(rnd_buff, 0, sizeof(rnd_buff)); +} + +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { + vect1_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = input[i]; + } + memcpy(output, buffer, sizeof(vect1_t)); +} + +void sig_perk_perm_inverse(perm_t o, const perm_t p) { + perm_t buffer; + for (int i = 0; i < PARAM_N1; i++) { + buffer[p[i]] = i; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { + perm_t buffer = {0}; + for (size_t i = 0; i < PARAM_N1; i++) { + buffer[i] = p1[p2[i]]; + } + memcpy(o, buffer, sizeof(perm_t)); +} + +// compute p1 compose p2^-1 +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { + uint32_t buffer[PARAM_N1]; + for (int i = 0; i < PARAM_N1; ++i) { + buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; + } + uint32_sort(buffer, PARAM_N1); + for (int i = 0; i < PARAM_N1; ++i) { + o[i] = (uint16_t)(buffer[i]); + } +} + +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { + sig_perk_perm_inverse(pi_i[0], pi_i[1]); + for (int i = 2; i < PARAM_N; i++) { + sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); + } + sig_perk_perm_compose(pi_i[0], pi_i[0], pi); +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.h b/crypto_sign/perk-256-short-5/m4/permutation.h new file mode 100644 index 00000000..0f8e253b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/permutation.h @@ -0,0 +1,111 @@ + +/** + * @file permutation.h + * @brief header file for permutation.c + */ + +#ifndef SIG_PERK_PERMUTATION_H +#define SIG_PERK_PERMUTATION_H + +#include +#include "arithmetic.h" +#include "parameters.h" + +/** + * @brief Permutation perm_t + * + * This structure contains an array of integers that is a permutation + */ +typedef uint8_t perm_t[PARAM_N1]; + +/** + * @brief Set permutation to zero + * + * @param [out,in] input_perm a permutation + */ +void sig_perk_perm_set_zero(perm_t input_perm); + +/** + * @brief Generate a random permutation form a seed + * + * @param [out] p a permutation + * @param [in] seed a string containing a seed + */ +void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); + +/** + * @brief Generate a random permutation form random values + * + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Generate a random permutation form random values and compose + * + * @param [out,in] pi_comp a permutation to be composed + * @param [out] p a permutation + * @param [in] rnd_buff an array containing random values + */ +int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); + +/** + * @brief Apply a permutation on a vector + * + * @param [out] output a permuted vector + * @param [in] p a permutation + * @param [in] input a vector + */ +void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); + +/** + * @brief Compute the composition on two permutations + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the composition p1 compose p2^-1 + * + * o = p1(p2) + * + * @param [out] o a permutation + * @param [in] p1 a permutation + * @param [in] p2 a permutation + */ +void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); + +/** + * @brief Compute the inverse of a permutation + * + * o = p1^(-1) + * + * @param [out] o a permutation + * @param [in] p a permutation + */ +void sig_perk_perm_inverse(perm_t o, const perm_t p); + +/** + * @brief Compute the composition of given permutations + * + * @param [out] o a permutation + * @param [in] pi_i a pointer to permutations + * @param [in] nb_permutations an integer that is the number of permutations to be composed + */ +void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); + +/** + * @brief Compute the permutation pi_1 + * + * @param [out,in] pi_i a pointer to permutations + * @param [in] pi the secret permutation pi in the scheme + */ +void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h new file mode 100644 index 00000000..c530d04f --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h @@ -0,0 +1,171 @@ +/** + * @file rank_unrank_table.h + * @brief Look-up table used in rank/unrank compression. + * For the GMP version, the encoding is in base-62 + * For tiny-bignum, the setting is for 32 bit architectures + * + * Each i-th value is i! encoded in base-62. + * + */ + +#ifndef SIG_PKP_RANK_UNRANK_TABLE_H +#define SIG_PKP_RANK_UNRANK_TABLE_H + +#include "bn.h" + +// clang-format off +static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, + {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, + {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} + +}; + +#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-256-short-5/m4/sign.c b/crypto_sign/perk-256-short-5/m4/sign.c new file mode 100644 index 00000000..d846c73a --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/sign.c @@ -0,0 +1,119 @@ + +/** + * @file sign.c + * @brief Implementation of the NIST api functions + */ + +#include +#include "api.h" +#include "crypto_memset.h" +#include "keygen.h" +#include "parsing.h" +#include "signature.h" +#include "verbose.h" +#include "verify.h" + +/** + * @brief Generate a keypair. + * + * @param [out] pk pointer to public key bytes + * @param [out] sk pointer to public key bytes + * @returns 0 if key generation is successful and -1 otherwise + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); + perk_public_key_t public_key = {0}; + perk_private_key_t private_key = {0}; + + if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + return -1; + } + + sig_perk_public_key_to_bytes(pk, &public_key); + sig_perk_private_key_to_bytes(sk, &private_key); + + memset_zero(&private_key, sizeof(private_key)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); + + return 0; +} + +/** + * @brief Generate a signature of a message. + * + * @param [out] sm pointer to output signed message + * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m + * @param [out] smlen pointer to output length of signed message + * @param [in] m pointer to message to be signed + * @param [in] mlen length of the message + * @param [in] sk pointer to the secret key bytes + * @returns 0 if signing is successful and -1 otherwise + */ +int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN"); + perk_private_key_t private_key = {0}; + perk_signature_t signature = {0}; + sig_perk_private_key_from_bytes(&private_key, sk); + + for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + + if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { + memset_zero(&private_key, sizeof(private_key)); + memset_zero(&signature, sizeof(signature)); + return -1; + } + + sig_perk_signature_to_bytes(sm, &signature); + memset_zero(&private_key, sizeof(private_key)); + + *smlen = mlen + CRYPTO_BYTES; + + SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); + + return 0; +} + +/** + * @brief Verify a signed message + * + * @param [out] m pointer to output message + * (allocated array with smlen bytes), can be equal to sm + * @param [out] mlen pointer to output length of message + * @param [in] sm pointer to signed message + * @param [in] smlen length of signed message + * @param [in] pk pointer to the public key bytes + * @returns 0 if signed message could be verified correctly and -1 otherwise + */ +int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); + if (smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + + perk_signature_t signature; + challenge_t challenges[PARAM_TAU] = {0}; + + if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { + goto badsig; + } + + sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); + + // check the signature + if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { + goto badsig; + } else { + /* All good, copy msg, return 0 */ + for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + return -1; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.c b/crypto_sign/perk-256-short-5/m4/signature.c new file mode 100644 index 00000000..f62c4b98 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/signature.c @@ -0,0 +1,384 @@ + +/** + * @file signature.c + * @brief Implementation of sign function + */ + +#include "signature.h" +#include "parameters.h" + +#include +#include +#include "common.h" +#include "crypto_memset.h" +#include "data_structures.h" +#include "parsing.h" +#include "randombytes.h" +#include "symmetric.h" +#include "theta_tree.h" +#include "verbose.h" + +/** + * @brief Generate the commitments TODO: update + * + * @param [out] signature a pointer to a signature structure + * @param [out,in] instances an array of PARAM_TAU instances + * @param [in] pi a variable that containing the permutation pi + * @param [in] H a variable containing the public matrix H + */ +static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, + sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, + const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, + const mat_t H) { + uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; + sig_perk_prg_state_t prg_state; + vect1_t v = {0}; + perm_t pi_inv; + + sig_perk_perm_inverse(pi_inv, pi); + + randombytes(rand_bytes, sizeof(rand_bytes)); + memcpy(mseed, rand_bytes, SEED_BYTES); + memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); + sig_perk_hash_update(h1_state, m, mlen); + sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); + SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + perm_t pi_1; + perm_t pi_comp; + cmt_t cmt_1_i; + vect1_t v_i; + perk_theta_seeds_tree_t theta_tree; + + memcpy(pi_1, pi_inv, sizeof(perm_t)); + + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_hash_state_t h_state; + sig_perk_prg_state_t p_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} + perm_t pi_i; + uint8_t idx = i; + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, + theta_tree[THETA_SEEDS_OFFSET + i]); + + if (i == (PARAM_N - 1)) { + memcpy(v, v_i, sizeof(vect1_t)); + memcpy(pi_comp, pi_i, sizeof(perm_t)); + } else { + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + sig_perk_perm_compose(pi_comp, pi_comp, pi_i); + } + } + + sig_perk_perm_inverse(pi_1, pi_1); + /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); + + uint8_t idx = 0; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + sig_perk_hash_update(&h_state, pi_1, PARAM_N1); + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); + sig_perk_hash_final(&h_state, cmt_1_i, H0); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(v_i, pi_comp, v_i); + sig_perk_vect1_add(v, v, v_i); + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); + + // reuse cmt_1_i for cmt_1 + sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); + sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); + + SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); + } +} + +static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, + digest_t h1) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_final(h1_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]) { + sig_perk_hash_state_t hash_state; + sig_perk_prg_state_t prg_state; + uint16_t tmp_kappa; + + sig_perk_hash_init(&hash_state, salt, NULL, NULL); + sig_perk_hash_update(&hash_state, m, mlen); + sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); + memcpy(saved_state, &hash_state, sizeof(hash_state)); + for (int i = 0; i < PARAM_TAU; ++i) { + // absorb cmt_1_N to cmt_1_1 + // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); + sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); + } + sig_perk_hash_final(&hash_state, h1, H1); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h1); + for (int i = 0; i < PARAM_TAU; ++i) { + uint16_t nonzero_check = 0; + do { + for (int j = 0; j < PARAM_T; ++j) { + do { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); + tmp_kappa = tmp_kappa & PARAM_Q_MASK; + } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q + challenge[i].kappa[j] = tmp_kappa; + nonzero_check |= tmp_kappa; + } + } while (!nonzero_check); + } +} + +/** + * @brief Generate the first response + * + * @param [out] instances an array of PARAM_TAU instances + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] x an array of PARAM_T public values x_i + */ +static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], + const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], + const vect1_t x[PARAM_T]) { + sig_perk_prg_state_t prg_state; + + sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); + + sig_perk_prg_init(&prg_state, PRG1, salt, mseed); + + sig_perk_prg_state_t state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (int e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + + for (int i = 1; i < PARAM_N; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&state, sizeof(sig_perk_prg_state_t)); +} + +static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], + sig_perk_hash_state_t *h2_state) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_final(h2_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + uint16_t tmp_alpha; + + sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); + } + sig_perk_hash_final(saved_state, h2, H2); + + sig_perk_prg_init(&prg_state, PRG1, NULL, h2); + for (int i = 0; i < PARAM_TAU; ++i) { + sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); + tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N + challenge[i].alpha = tmp_alpha; + } +} + +/** + * @brief Generate second response + * + * @param [out] signature a pointer to a signature structure + * @param [in] challenges an array of PARAM_TAU challenges + * @param [in] instances an array of PARAM_TAU instances + */ +static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, + const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], + const perm_t pi_0[PARAM_TAU]) { + sig_perk_prg_state_t prg_state; + + sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); + + sig_perk_prg_state_t p_state; + sig_perk_hash_state_t h_state; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + + for (uint8_t e = 0; e < PARAM_TAU; ++e) { + vect1_t tmp; + vect1_t v_i; // TODO: tmp and v_i can share memory?? + vect1_t s_0; + vect1_t s_i; + perk_theta_seeds_tree_t theta_tree; + const uint16_t alpha = challenges[e].alpha; + + // compute s_0 + sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); + for (int j = 1; j < PARAM_T; j++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); + sig_perk_vect1_add(s_0, s_0, tmp); + } + + // sample seeds + sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); + sig_perk_expand_theta_tree(signature->salt, theta_tree); + + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); + + sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); + sig_perk_vect1_add(s_i, tmp, v_i); + for (int i = 1; i < alpha; ++i) { + perm_t pi_i; + + // sample p_i and v_i + sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); + + sig_perk_perm_vect_permute(tmp, pi_i, s_i); + sig_perk_vect1_add(s_i, tmp, v_i); + } + memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); + + if (alpha != 1) { + memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); + } else { + for (int j = 0; j < PARAM_N1; j++) { + signature->responses[e].z2_pi[j] = j; + } + } + sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); + + uint8_t idx = alpha - 1; + sig_perk_hash_init(&h_state, signature->salt, &e, &idx); + if (alpha == 1) { + sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); + } + sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); + sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); + } + + memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); + memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); + memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); + memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); +} + +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length) { + perk_public_key_t pk; + perm_t pi_0[PARAM_TAU]; + challenge_t challenges[PARAM_TAU] = {0}; + sig_perk_hash_state_t h1_state; + sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes + seed_t mseed = {0}; + + SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); + + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { + return EXIT_FAILURE; + } + + sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, + sk->pi, (const vect1_t *)pk.H); + sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); + sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, + (const vect1_t *)pk.x); + + sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); + sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); + + SIG_PERK_VERBOSE_PRINT_challenges(challenges); + SIG_PERK_VERBOSE_PRINT_signature(signature); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.h b/crypto_sign/perk-256-short-5/m4/signature.h new file mode 100644 index 00000000..73e69475 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/signature.h @@ -0,0 +1,64 @@ + +/** + * @file signature.h + * @brief Header file for signature.c + */ + +#ifndef SIG_PERK_SIGNATURE_H +#define SIG_PERK_SIGNATURE_H + +#include +#include "data_structures.h" + +/** @struct challenge_t + * @brief This structure contains the challenges of one round of the scheme + * @var challenge_t::kappa + * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 + * @var challenge_t::alpha + * Member 'alpha' is an integer containing challenge alpha + */ +typedef struct { + uint16_t kappa[PARAM_T]; + uint16_t alpha; +} challenge_t; + +/** + * @brief Generate challenges kappa for PARAM_TAU rounds + * + * @param [out] challenge an array of PARAM_TAU challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes + * @param [out] h1 a variable containing the digest h1 + * @param [in] salt a salt + * @param [in] m a pointer to message + * @param [in] mlen length of message + * @param [in] pk_bytes a pointer to the public key bytes + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, + const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, + const perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate h2 and the challenges alpha for tau rounds + * + * @param [out] h2 a variable containing the digest h2 + * @param [out] challenge an array of tau challenge_t struct + * @param [out,in] saved_state a pointer to Keccak state + * @param [out] h1 a variable containing the digest h1 + * @param [in] instances an array of PARAM_TAU instances + */ +void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, + const digest_t h1, perk_instance_t instances[PARAM_TAU]); + +/** + * @brief Generate a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] sk a pointer to private key structure + * @param [in] message_bytes a string containing a message + * @param [in] message_length an integer containing the length of the message + */ +uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, + const uint64_t message_length); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/sort.c b/crypto_sign/perk-256-short-5/m4/sort.c new file mode 100644 index 00000000..5a335826 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/sort.c @@ -0,0 +1,128 @@ +// crypto_sort aka djbsort. +// copied from supercop-20231107/crypto_sort/int32/portable4 +// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) + +#include + +#include "djbsort.h" + +// -inline assembly using conditional execution +// -reduce instruction count by optimizing loads and stores, reducing temporaries +#define int32_MINMAX_M_M(x, offset1, offset2) \ + do \ + { \ + int32_t a, b; /* temporaries */ \ + asm volatile( \ + "ldr %0, [%4, %5, lsl #2]\n" \ + "ldr %1, [%4, %6, lsl #2]\n" \ + "cmp %0, %1 \n" \ + "itt gt \n" \ + "strgt %1, [%4, %5, lsl #2]\n" \ + "strgt %0, [%4, %6, lsl #2]\n" \ + : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ + : "r"(x), "r"(offset1), "r"(offset2) \ + : "cc"); \ + } while (0) + +#define int32_MINMAX_V_M(a, x, offset) \ + do \ + { \ + int32_t b; /* temporary */ \ + asm( \ + "ldr %1, [%3, %4, lsl #2]\n" \ + "cmp %0, %1\n" \ + "itt gt \n" \ + "strgt %0, [%3, %4, lsl #2]\n" \ + "movgt %0, %1\n" \ + : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ + : "r"(x), "r"(offset) \ + : "cc"); \ + } while (0) + +// -replace long long by size_t +void int32_sort(int32_t *x, size_t n) +{ + size_t top, p, q, r, i, j; + + if (n < 2) + { + return; + } + top = 1; + while (top < n - top) + { + top += top; + } + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + i += 2 * p; + } + for (j = i; j < n - p; ++j) + { + int32_MINMAX_M_M(x, j, j + p); + } + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + { + for (;;) + { + if (j == n - q) + { + goto done; + } + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + { + int32_MINMAX_V_M(a, x, j + r); + } + x[j + p] = a; + ++j; + } + + done:; + } + } +} diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.c b/crypto_sign/perk-256-short-5/m4/symmetric.c new file mode 100644 index 00000000..8676221d --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/symmetric.c @@ -0,0 +1,51 @@ + +/** + * @file symmetric.c + * @brief Implementation of the symmetric functions + */ + +#include "symmetric.h" + +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { + Keccak_HashInitialize_SHAKE(state); + if (salt != NULL) { + Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); + } + if (seed != NULL) { + Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); + } + Keccak_HashUpdate_SHAKE(state, &domain, 1); + Keccak_HashFinal_SHAKE(state); +} + +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { + Keccak_HashSqueeze_SHAKE(state, output, outlen); +} + +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { + Keccak_HashInitialize_SHA3(state); + Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); + + uint8_t counters[2]; + int j = 0; + if (tau != NULL) { + counters[j] = *tau; + j++; + } + if (n != NULL) { + counters[j] = *n; + j++; + } + if (j != 0) { + Keccak_HashUpdate_SHA3(state, counters, j); + } +} + +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { + Keccak_HashUpdate_SHA3(state, message, message_size); +} + +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { + Keccak_HashUpdate_SHA3(state, &domain, 1); + Keccak_HashFinal_SHA3(state, digest); +} diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.h b/crypto_sign/perk-256-short-5/m4/symmetric.h new file mode 100644 index 00000000..6bbf109a --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/symmetric.h @@ -0,0 +1,135 @@ + +/** + * @file symmetric.h + * @brief Header file for symmetric.c + */ + +#ifndef SIG_PERK_SYMMETRIC_H +#define SIG_PERK_SYMMETRIC_H + +#include +#include "fips202.h" +#include "parameters.h" + +// domains for hash and prg +#define H0 0x00 +#define H1 0x01 +#define H2 0x02 +#define H3 0x03 +#define PRG1 0x04 +#define PRG2 0x05 + +/** + * @brief Salt salt_t + * + * This structure contains the salt + */ +typedef uint8_t salt_t[SALT_BYTES]; + +/** + * @brief Digest digest_t + * + * This structure contains the digest + */ +typedef uint8_t digest_t[HASH_BYTES]; + +/** + * @brief Seed seed_t + * + * This structure defines a string containing SEED_BYTES bytes + */ +typedef uint8_t seed_t[SEED_BYTES]; + +#if (SECURITY_BYTES == 16) +#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size +#elif (SECURITY_BYTES == 24) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#elif (SECURITY_BYTES == 32) +#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size +#endif + +#if (SECURITY_BYTES == 16) +#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) + +typedef shake128incctx sig_perk_prg_state_t; +typedef sha3_256incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 24) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_384incctx sig_perk_hash_state_t; +#elif (SECURITY_BYTES == 32) +#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) +#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) +#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) +#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) +#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) +#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) + +typedef shake256incctx sig_perk_prg_state_t; +typedef sha3_512incctx sig_perk_hash_state_t; +#endif + +/** + * @brief Initialize a PRNG + * absorb the salt if not NULL and seed + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [in] domain a byte that is the domain separator. + * @param [in] salt a string containing the salt. If Null no salt is absorbed. + * @param [in] seed a string containing the seed. If Null no seed is absorbed. + */ +void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); + +/** + * @brief PRNG + * + * @param [out,in] state a pointer to the state of the PRNG + * @param [out] output pinter to the buffer to be filled + * @param [in] outlen size of the output + */ +void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); + +/** + * @brief initialize the HASH function + * absorb the salt and ctr if != 0 + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] salt a string containing the salt. + * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. + * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. + */ +void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); + +/** + * @brief HASH update + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [in] message message to be absorbed. + * @param [in] message_size size of the message. + */ +void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); + +/** + * @brief output the digest for the chosen hash function (domain) + * + * @param [out,in] state a pointer to the state of the HASH. + * @param [out] digest output digest. + * @param [in] domain domain: H0, H1 or H2. + */ +void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.c b/crypto_sign/perk-256-short-5/m4/theta_tree.c new file mode 100644 index 00000000..2b9a236b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/theta_tree.c @@ -0,0 +1,55 @@ + +/** + * @file theta_tree.c + * @brief Implementation of tree related functions + */ + +#include "theta_tree.h" +#include +#include "symmetric.h" + +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { + sig_perk_hash_state_t state; + + for (unsigned i = 0; i < (PARAM_N - 1); i++) { + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, theta_tree[to], H3); + } +} + +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { + sig_perk_hash_state_t state; + for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { + unsigned N = (1U << l); + if (j >= N) { // increment level + l++; + j = 0; + } + unsigned from = i; + uint8_t idx = i; + unsigned to = i * 2 + 1; + unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l + unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 + if (j == missing) { + memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); + } else { + sig_perk_hash_init(&state, salt, &idx, NULL); + sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); + sig_perk_hash_final(&state, partial_theta_tree[to], H3); + } + } +} + +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { + for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { + unsigned level = (1U << (i + 1U)) - 1; + unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; + memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); + } +} diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.h b/crypto_sign/perk-256-short-5/m4/theta_tree.h new file mode 100644 index 00000000..13b66143 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/theta_tree.h @@ -0,0 +1,65 @@ + +/** + * @file theta_tree.h + * @brief Header file for theta_tree.c + */ + +#ifndef SIG_PERK_THETA_TREE_H +#define SIG_PERK_THETA_TREE_H + +#include +#include "parameters.h" +#include "symmetric.h" + +#define MASTER_THETA_SEED_OFFSET 0 +#define THETA_SEEDS_OFFSET (PARAM_N - 1) + +/** + * @brief Theta theta_t + * + * This structure contains a seed of size SEED_BYTES bytes + */ +typedef uint8_t theta_t[SEED_BYTES]; + +/** + * @brief An array of Theta + * + * This structure contains an array of 2 * PARAM_N - 1 theta_t + */ +typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; + +/** + * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt + * + * @param[in] salt + * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * theta_tree[0] is the master seed + * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t + */ +void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); + +/** + * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) + * from the array of THETA_TREE_LEVELS node seeds, salt and alpha + * + * @param[in] salt + * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves + * from the array of partial_tree_seeds + * @param[in] partial_tree_seeds array of seeds (one for each level) + * @param[in] alpha missing leaf + */ +void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, + const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); + +/** + * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones + * given perk_theta_seeds_tree_t and alpha + * + * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf + * @param[in] theta_tree a complete perk_theta_seeds_tree_t + * @param[in] alpha missing leaf + */ +void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], + const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.c b/crypto_sign/perk-256-short-5/m4/verbose.c new file mode 100644 index 00000000..777e7f74 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verbose.c @@ -0,0 +1,131 @@ + +/** + * @file verbose.c + * @brief Implementation of function for printing intermediate values (VERBOSE mode) + */ + +#include "verbose.h" +#include +#include "api.h" +#include "parameters.h" + +void sig_perk_verbose_print_string(const char *var) { + printf("\n\n\n\n### %s ###", var); +} + +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%02x", input[i]); + } +} + +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { + printf("\n\n%s: ", var); + for (uint16_t i = 0; i < size; i++) { + printf("%d ", input[i]); + } +} + +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { + printf("\n\nx\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" x_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_N1; j++) { + printf("%03d ", x[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { + printf("\n\ny\n"); + for (int i = 0; i < PARAM_T; ++i) { + printf(" y_%d: ", i + 1); + for (uint16_t j = 0; j < PARAM_M; j++) { + printf("%03d ", y[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_matrix(const mat_t m_input) { + printf("\n\nH: \n"); + for (int i = 0; i < PARAM_M; i++) { + printf(" "); + for (int j = 0; j < PARAM_N1; j++) { + printf("%03d ", m_input[i][j]); + } + printf("\n"); + } +} + +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { + printf("\n\n Round %02d: ", round_number); + printf("\n theta: "); + for (int i = 0; i < SEED_BYTES; ++i) { + printf("%02x", theta[i]); + } + printf("\n cmt_1: "); + for (uint16_t i = 0; i < sizeof(cmt_t); i++) { + printf("%02x", ((uint8_t *)input)[i]); + } + printf("\n v: "); + for (uint16_t i = 0; i < PARAM_N1; i++) { + printf("%d ", v[i]); + } +} + +void sig_perk_verbose_print_challenges(challenge_t *challenges) { + printf("\n\nchallenges: "); + printf("\n\n kappa: "); + for (int i = 0; i < PARAM_TAU; i++) { + printf("\n kappa_i (round %02d): ", i + 1); + for (int j = 0; j < PARAM_T; ++j) { + printf("%03d ", challenges[i].kappa[j]); + } + } + printf("\n\n alpha: "); + for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); +} + +void sig_perk_verbose_print_signature(const perk_signature_t *signature) { + printf("\n\nsignature: "); + sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); + sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); + printf("\n\n responses"); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n\n response round %d", i + 1); + sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); + sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); + printf("\n\n z2_theta"); + for (int j = 0; j < THETA_TREE_LEVELS; ++j) { + printf("\n z2_theta seed # %d: ", j + 1); + for (int k = 0; k < SEED_BYTES; ++k) { + printf("%02x", signature->responses[i].z2_theta[j][k]); + } + } + sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); + } +} + +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { + sig_perk_verbose_print_uint8_t_array("m", m, mlen); + printf("\n\nsm(CRYPTO_BYTES):"); + for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { + if (i % 32 == 0) + printf("\n"); + printf("%02x", signature[i]); + } + printf("\n\n"); +} + +void sig_perk_verbose_print_thetas(perk_instance_t *instances) { + printf("\n\nthetas: "); + for (int i = 0; i < PARAM_TAU; ++i) { + printf("\n theta round %02d: ", i + 1); + for (int j = 0; j < SEED_BYTES; ++j) { + printf("%02x", instances[i].theta_tree[0][j]); + } + } +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.h b/crypto_sign/perk-256-short-5/m4/verbose.h new file mode 100644 index 00000000..ecd8f8e2 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verbose.h @@ -0,0 +1,129 @@ + +/** + * @file verbose.h + * @brief Header file verbose.c + */ + +#ifndef SIG_PERK_VERBOSE_H +#define SIG_PERK_VERBOSE_H + +#include +#include "arithmetic.h" +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Print a string + * + * @param [in] var a string containing the characters to print + */ +void sig_perk_verbose_print_string(const char *var); + +/** + * @brief Print in hexadecimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); + +/** + * @brief Print in decimal format a given number of bytes + * + * @param [in] var a string containing the name of the variable to be printed + * @param [in] input a string containing the data to be printed + * @param [in] size an integer that is the number of bytes to be printed + */ +void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); + +/** + * @brief Print the public key x_i + * + * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); + +/** + * @brief Print the public key y_i + * + * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 + */ +void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); + +/** + * @brief Print the values of the matrix H + * + * @param [in] m_input a matrix + */ +void sig_perk_verbose_print_matrix(const mat_t m_input); + +/** + * @brief Print the root randomness theta, commitment cmt_1 and vector v + * + * @param [in] theta a variable containing the seed theta + * @param [in] input a commitment + * @param [in] v a vector + * @param [in] round_number an integer containing the round number + */ +void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); + +/** + * @brief Print the challenges + * + * @param [in] challenges a pointer to the challenges + */ +void sig_perk_verbose_print_challenges(challenge_t *challenges); + +/** + * @brief Print the signature + * + * @param [in] signature a pointer to the signature + */ +void sig_perk_verbose_print_signature(const perk_signature_t *signature); + +/** + * @brief Print the seeds thetas in all rounds + * + * @param [in] instances a pointer to the instances of the signature + */ +void sig_perk_verbose_print_thetas(perk_instance_t *instances); + +/** + * @brief Print a message and a signature + * + * @param [in] m a string containing a message + * @param [in] mlen an integer that is the size of a message + * @param [in] signature a string containing a signature + */ +void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); + +#ifdef VERBOSE +#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ + sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ + sig_perk_verbose_print_signature_raw(m, mlen, signature) +#else +#define SIG_PERK_VERBOSE_PRINT_string(var) +#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) +#define SIG_PERK_VERBOSE_PRINT_x(x) +#define SIG_PERK_VERBOSE_PRINT_y(y) +#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) +#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) +#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) +#define SIG_PERK_VERBOSE_PRINT_signature(signature) +#define SIG_PERK_VERBOSE_PRINT_thetas(instances) +#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) +#endif + +#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.c b/crypto_sign/perk-256-short-5/m4/verify.c new file mode 100644 index 00000000..e25faa0a --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verify.c @@ -0,0 +1,160 @@ + +/** + * @file verify.c + * @brief Implementation of verify function + */ + +#include "verify.h" +#include +#include "common.h" +#include "parsing.h" + +static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, + const perk_response_t *response, const challenge_t challenge, + const uint8_t tau, salt_t salt) { + sig_perk_hash_state_t state; + cmt_t cmt_1_i; + + for (int i = PARAM_N - 1; i >= 0; --i) { + uint8_t idx = i; + if (i == 0 && (0 != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i != 0 && (i != (challenge.alpha - 1))) { + sig_perk_hash_init(&state, salt, &tau, &idx); + sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); + sig_perk_hash_final(&state, cmt_1_i, H0); + + sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); + } + if (i == (challenge.alpha - 1)) { + sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); + } + } +} + +static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, + const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, + vect1_t s_0, salt_t salt) { + sig_perk_prg_state_t state; + vect1_t v_i; + vect1_t s_i; + perm_t pi_i; + uint16_t rnd_buffer_pi_i[PARAM_N1]; + uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; + for (int i = 0; i < PARAM_N; ++i) { + if (i != (challenge.alpha - 1)) { + if (i != 0) { // skip the generation of pi_1 + sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + } else { // fetch pi_1 from z_2 + memcpy(pi_i, response->z2_pi, sizeof(perm_t)); + } + sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); + for (int j = 0; j < PARAM_N1; ++j) { + s_i[pi_i[j]] = s_0[j]; + } + sig_perk_vect1_add(s_i, s_i, v_i); + memcpy(s_0, s_i, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); + } + if (i == (challenge.alpha - 1)) { + memcpy(s_0, response->z1, sizeof(vect1_t)); + sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); + } + } +} + +static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, + const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, + const uint8_t tau) { + vect2_t tmp1, tmp2, tmp3; + sig_perk_hash_state_t state; + + sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); + sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); + sig_perk_vect2_add(tmp2, tmp2, tmp3); + } + sig_perk_vect2_sub(tmp1, tmp1, tmp2); + + sig_perk_hash_init(&state, salt, &tau, NULL); + sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); + sig_perk_hash_final(&state, cmt_1, H0); +} + +static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, + const uint8_t *message_bytes, const uint64_t message_length, + const uint8_t *pk_bytes) { + sig_perk_hash_init(hash_state, salt, NULL, NULL); + sig_perk_hash_update(hash_state, message_bytes, message_length); + sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); +} + +static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, + const vect1_t x[PARAM_T]) { + vect1_t tmp; + sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); + for (int i = 1; i < PARAM_T; i++) { + sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); + sig_perk_vect1_add(s_0, s_0, tmp); + } +} + +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes) { + perk_public_key_t public_key = {0}; + digest_t h1_prime, h2_prime; + sig_perk_hash_state_t h1_state, h2_state; + sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); + h2_state = h1_state; + sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); + + for (int i = 0; i < PARAM_TAU; ++i) { + if (challenge[i].alpha == 1) { + for (int j = 0; j < PARAM_N1; j++) { + if (signature->responses[i].z2_pi[j] != j) { + return EXIT_FAILURE; + } + } + } + } + if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { + return EXIT_FAILURE; + } + + for (int i = 0; i < PARAM_TAU; ++i) { + perk_theta_seeds_tree_t theta_tree; + vect1_t s_0; + cmt_t cmt_1 = {0}; // fix cppcheck error + + sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, + (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); + sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], + i, signature->salt); + sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); + // s_N is stored in s_0 + sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, + challenge[i], s_0, signature->salt); + sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); + sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); + } + + sig_perk_hash_final(&h1_state, h1_prime, H1); + sig_perk_hash_final(&h2_state, h2_prime, H2); + + if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.h b/crypto_sign/perk-256-short-5/m4/verify.h new file mode 100644 index 00000000..e8c8e2c9 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verify.h @@ -0,0 +1,26 @@ + +/** + * @file verify.h + * @brief Header file for verify.c + */ + +#ifndef SIG_PERK_VERIFY_H +#define SIG_PERK_VERIFY_H + +#include "data_structures.h" +#include "signature.h" + +/** + * @brief Verify a signature + * + * @param [out] signature a pointer to signature structure + * @param [in] challenge an array containing the challenges + * @param [in] message_bytes a pointer to a string containing the message + * @param [in] message_length an integer that is the size of the message + * @param [in] pk_bytes a string containing the public key + * @return int 0 if the verification is successful and 1 otherwise + */ +int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, + const uint64_t message_length, const uint8_t *pk_bytes); + +#endif \ No newline at end of file From d581941653e6220cc54903158fecb54e88e3f3e5 Mon Sep 17 00:00:00 2001 From: Marco Palumbi Date: Thu, 7 Dec 2023 13:10:59 +0000 Subject: [PATCH 048/107] use fullram linker script with some version --- mk/stm32f4discovery.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 41862137..abb213de 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -13,3 +13,5 @@ elf/boardtest-fast.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_CCM elf/crypto_kem_frodokem640aes_m4_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/mupq_pqclean_crypto_kem_frodokem640shake_opt_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/crypto_sign_dilithium5_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld +elf/crypto_sign_perk-256-%_m4_testvectors.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld +elf/crypto_sign_perk-256-fast%_m4_test.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld From 4956a307526288b5692dcc9c00861ae77028be11 Mon Sep 17 00:00:00 2001 From: Marco Palumbi Date: Thu, 7 Dec 2023 13:17:04 +0000 Subject: [PATCH 049/107] fix ldscripts for the stm32f4discovery board --- ldscripts/stm32f4discovery.ld | 2 +- ldscripts/stm32f4discovery_fullram.ld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ldscripts/stm32f4discovery.ld b/ldscripts/stm32f4discovery.ld index a3fb9f17..fb18aec5 100644 --- a/ldscripts/stm32f4discovery.ld +++ b/ldscripts/stm32f4discovery.ld @@ -58,6 +58,7 @@ SECTIONS *(COMMON) . = ALIGN(4); _ebss = .; + end = .; } >ram .ram2 : { *(.ram2*) @@ -69,6 +70,5 @@ SECTIONS } >ccm /DISCARD/ : { *(.eh_frame) } . = ALIGN(4); - end = .; } PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/ldscripts/stm32f4discovery_fullram.ld b/ldscripts/stm32f4discovery_fullram.ld index c1477e8d..c2f11263 100644 --- a/ldscripts/stm32f4discovery_fullram.ld +++ b/ldscripts/stm32f4discovery_fullram.ld @@ -57,6 +57,7 @@ SECTIONS *(COMMON) . = ALIGN(4); _ebss = .; + end = .; } >ram .ccm : { *(.ccmram*) @@ -64,6 +65,5 @@ SECTIONS } >ccm /DISCARD/ : { *(.eh_frame) } . = ALIGN(4); - end = .; } PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); From d98a1623ae6d942ad166638a66c287eb3b884e47 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 18 Dec 2023 10:07:27 +0800 Subject: [PATCH 050/107] Update Kyber poly_tomsg to fix timing leak (w/ -Os) This (partially) addresses https://github.com/mupq/pqm4/issues/319. The function poly_tomsg from the reference implementation of Kyber (which was copied into the M4-optimized implementations) would result in a variable-time udiv instruction operating on secret data when compiled with gcc using -Os. I tried a couple of versions from gcc 11 to gcc 13, but did not see any difference. This commit updates the m4-specific code to use the patch from https://github.com/pq-crystals/kyber/commit/dda29cc63af721981ee2c831cf00822e69be3220. Note that the code in PQClean has not yet been updated and hence the clean implementation within pqm4 is still vulnerable. --- crypto_kem/kyber512/m4fspeed/poly.c | 9 +++++++-- crypto_kem/kyber512/m4fstack/poly.c | 9 +++++++-- crypto_kem/kyber768/m4fspeed/poly.c | 9 +++++++-- crypto_kem/kyber768/m4fstack/poly.c | 9 +++++++-- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/crypto_kem/kyber512/m4fspeed/poly.c b/crypto_kem/kyber512/m4fspeed/poly.c index 11722cd3..1b74c0c9 100644 --- a/crypto_kem/kyber512/m4fspeed/poly.c +++ b/crypto_kem/kyber512/m4fspeed/poly.c @@ -560,13 +560,18 @@ void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { * - const poly *a: pointer to input polynomial **************************************************/ void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) { - uint16_t t; + uint32_t t; int i, j; for (i = 0; i < KYBER_SYMBYTES; i++) { msg[i] = 0; for (j = 0; j < 8; j++) { - t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1; + t = a->coeffs[8*i+j]; + t <<= 1; + t += 1665; + t *= 80635; + t >>= 28; + t &= 1; msg[i] |= t << j; } } diff --git a/crypto_kem/kyber512/m4fstack/poly.c b/crypto_kem/kyber512/m4fstack/poly.c index 1df32970..0c449a46 100644 --- a/crypto_kem/kyber512/m4fstack/poly.c +++ b/crypto_kem/kyber512/m4fstack/poly.c @@ -525,13 +525,18 @@ void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { * - const poly *a: pointer to input polynomial **************************************************/ void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) { - uint16_t t; + uint32_t t; int i, j; for (i = 0; i < KYBER_SYMBYTES; i++) { msg[i] = 0; for (j = 0; j < 8; j++) { - t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1; + t = a->coeffs[8*i+j]; + t <<= 1; + t += 1665; + t *= 80635; + t >>= 28; + t &= 1; msg[i] |= t << j; } } diff --git a/crypto_kem/kyber768/m4fspeed/poly.c b/crypto_kem/kyber768/m4fspeed/poly.c index 11e0845d..d7c63bc6 100644 --- a/crypto_kem/kyber768/m4fspeed/poly.c +++ b/crypto_kem/kyber768/m4fspeed/poly.c @@ -541,13 +541,18 @@ void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { * - const poly *a: pointer to input polynomial **************************************************/ void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) { - uint16_t t; + uint32_t t; int i, j; for (i = 0; i < KYBER_SYMBYTES; i++) { msg[i] = 0; for (j = 0; j < 8; j++) { - t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1; + t = a->coeffs[8*i+j]; + t <<= 1; + t += 1665; + t *= 80635; + t >>= 28; + t &= 1; msg[i] |= t << j; } } diff --git a/crypto_kem/kyber768/m4fstack/poly.c b/crypto_kem/kyber768/m4fstack/poly.c index 8a588455..84b1deb8 100644 --- a/crypto_kem/kyber768/m4fstack/poly.c +++ b/crypto_kem/kyber768/m4fstack/poly.c @@ -506,13 +506,18 @@ void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { * - const poly *a: pointer to input polynomial **************************************************/ void poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) { - uint16_t t; + uint32_t t; int i, j; for (i = 0; i < KYBER_SYMBYTES; i++) { msg[i] = 0; for (j = 0; j < 8; j++) { - t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1; + t = a->coeffs[8*i+j]; + t <<= 1; + t += 1665; + t *= 80635; + t >>= 28; + t &= 1; msg[i] |= t << j; } } From a7fe0c1de24edea5758ad0cd19deeed6585f7839 Mon Sep 17 00:00:00 2001 From: Marco Palumbi Date: Fri, 5 Jan 2024 18:19:56 +0000 Subject: [PATCH 051/107] use symbolic links whenever possible --- crypto_sign/perk-128-fast-5/m4/README | 44 +- crypto_sign/perk-128-fast-5/m4/api.h | 27 +- crypto_sign/perk-128-fast-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-128-fast-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-128-fast-5/m4/common.c | 103 +--- crypto_sign/perk-128-fast-5/m4/common.h | 110 +--- crypto_sign/perk-128-fast-5/m4/common_s.c | 43 +- .../perk-128-fast-5/m4/crypto_memset.c | 8 +- .../perk-128-fast-5/m4/crypto_memset.h | 19 +- .../perk-128-fast-5/m4/data_structures.h | 132 +---- crypto_sign/perk-128-fast-5/m4/djbsort.c | 13 +- crypto_sign/perk-128-fast-5/m4/djbsort.h | 17 +- crypto_sign/perk-128-fast-5/m4/keygen.c | 52 +- crypto_sign/perk-128-fast-5/m4/keygen.h | 22 +- crypto_sign/perk-128-fast-5/m4/parsing.c | 218 +------- crypto_sign/perk-128-fast-5/m4/parsing.h | 76 +-- .../perk-128-fast-5/m4/parsing_permutations.c | 426 +--------------- .../perk-128-fast-5/m4/parsing_permutations.h | 54 +- crypto_sign/perk-128-fast-5/m4/permutation.c | 92 +--- crypto_sign/perk-128-fast-5/m4/permutation.h | 112 +---- crypto_sign/perk-128-fast-5/m4/sign.c | 120 +---- crypto_sign/perk-128-fast-5/m4/signature.c | 385 +------------- crypto_sign/perk-128-fast-5/m4/signature.h | 65 +-- crypto_sign/perk-128-fast-5/m4/sort.c | 129 +---- crypto_sign/perk-128-fast-5/m4/symmetric.c | 52 +- crypto_sign/perk-128-fast-5/m4/symmetric.h | 136 +---- crypto_sign/perk-128-fast-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-128-fast-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-128-fast-5/m4/verbose.c | 132 +---- crypto_sign/perk-128-fast-5/m4/verbose.h | 130 +---- crypto_sign/perk-128-fast-5/m4/verify.c | 161 +----- crypto_sign/perk-128-fast-5/m4/verify.h | 27 +- crypto_sign/perk-128-short-3/m4/README | 44 +- crypto_sign/perk-128-short-3/m4/api.h | 27 +- crypto_sign/perk-128-short-3/m4/arithmetic.c | 155 +----- crypto_sign/perk-128-short-3/m4/arithmetic.h | 157 +----- crypto_sign/perk-128-short-3/m4/common.c | 103 +--- crypto_sign/perk-128-short-3/m4/common.h | 110 +--- crypto_sign/perk-128-short-3/m4/common_s.c | 43 +- .../perk-128-short-3/m4/crypto_memset.c | 8 +- .../perk-128-short-3/m4/crypto_memset.h | 19 +- .../perk-128-short-3/m4/data_structures.h | 132 +---- crypto_sign/perk-128-short-3/m4/djbsort.c | 13 +- crypto_sign/perk-128-short-3/m4/djbsort.h | 17 +- crypto_sign/perk-128-short-3/m4/keygen.c | 52 +- crypto_sign/perk-128-short-3/m4/keygen.h | 22 +- crypto_sign/perk-128-short-3/m4/parsing.c | 218 +------- crypto_sign/perk-128-short-3/m4/parsing.h | 76 +-- crypto_sign/perk-128-short-3/m4/permutation.c | 92 +--- crypto_sign/perk-128-short-3/m4/permutation.h | 112 +---- crypto_sign/perk-128-short-3/m4/sign.c | 120 +---- crypto_sign/perk-128-short-3/m4/signature.c | 385 +------------- crypto_sign/perk-128-short-3/m4/signature.h | 65 +-- crypto_sign/perk-128-short-3/m4/sort.c | 129 +---- crypto_sign/perk-128-short-3/m4/symmetric.c | 52 +- crypto_sign/perk-128-short-3/m4/symmetric.h | 136 +---- crypto_sign/perk-128-short-3/m4/theta_tree.c | 56 +-- crypto_sign/perk-128-short-3/m4/theta_tree.h | 66 +-- crypto_sign/perk-128-short-3/m4/verbose.c | 132 +---- crypto_sign/perk-128-short-3/m4/verbose.h | 130 +---- crypto_sign/perk-128-short-3/m4/verify.c | 161 +----- crypto_sign/perk-128-short-3/m4/verify.h | 27 +- crypto_sign/perk-128-short-5/m4/README | 44 +- crypto_sign/perk-128-short-5/m4/api.h | 27 +- crypto_sign/perk-128-short-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-128-short-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-128-short-5/m4/bn.c | 475 +----------------- crypto_sign/perk-128-short-5/m4/bn.h | 118 +---- crypto_sign/perk-128-short-5/m4/common.c | 103 +--- crypto_sign/perk-128-short-5/m4/common.h | 110 +--- crypto_sign/perk-128-short-5/m4/common_s.c | 43 +- .../perk-128-short-5/m4/crypto_memset.c | 8 +- .../perk-128-short-5/m4/crypto_memset.h | 19 +- .../perk-128-short-5/m4/data_structures.h | 132 +---- crypto_sign/perk-128-short-5/m4/djbsort.c | 13 +- crypto_sign/perk-128-short-5/m4/djbsort.h | 17 +- crypto_sign/perk-128-short-5/m4/keygen.c | 52 +- crypto_sign/perk-128-short-5/m4/keygen.h | 22 +- crypto_sign/perk-128-short-5/m4/parsing.c | 218 +------- crypto_sign/perk-128-short-5/m4/parsing.h | 76 +-- .../m4/parsing_permutations.c | 112 +---- .../m4/parsing_permutations.h | 66 +-- crypto_sign/perk-128-short-5/m4/permutation.c | 92 +--- crypto_sign/perk-128-short-5/m4/permutation.h | 112 +---- .../perk-128-short-5/m4/rank_unrank_table.h | 172 +------ crypto_sign/perk-128-short-5/m4/sign.c | 120 +---- crypto_sign/perk-128-short-5/m4/signature.c | 385 +------------- crypto_sign/perk-128-short-5/m4/signature.h | 65 +-- crypto_sign/perk-128-short-5/m4/sort.c | 129 +---- crypto_sign/perk-128-short-5/m4/symmetric.c | 52 +- crypto_sign/perk-128-short-5/m4/symmetric.h | 136 +---- crypto_sign/perk-128-short-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-128-short-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-128-short-5/m4/verbose.c | 132 +---- crypto_sign/perk-128-short-5/m4/verbose.h | 130 +---- crypto_sign/perk-128-short-5/m4/verify.c | 161 +----- crypto_sign/perk-128-short-5/m4/verify.h | 27 +- crypto_sign/perk-192-fast-3/m4/README | 44 +- crypto_sign/perk-192-fast-3/m4/api.h | 27 +- crypto_sign/perk-192-fast-3/m4/arithmetic.c | 155 +----- crypto_sign/perk-192-fast-3/m4/arithmetic.h | 157 +----- crypto_sign/perk-192-fast-3/m4/common.c | 103 +--- crypto_sign/perk-192-fast-3/m4/common.h | 110 +--- crypto_sign/perk-192-fast-3/m4/common_s.c | 43 +- .../perk-192-fast-3/m4/crypto_memset.c | 8 +- .../perk-192-fast-3/m4/crypto_memset.h | 19 +- .../perk-192-fast-3/m4/data_structures.h | 132 +---- crypto_sign/perk-192-fast-3/m4/djbsort.c | 13 +- crypto_sign/perk-192-fast-3/m4/djbsort.h | 17 +- crypto_sign/perk-192-fast-3/m4/keygen.c | 52 +- crypto_sign/perk-192-fast-3/m4/keygen.h | 22 +- crypto_sign/perk-192-fast-3/m4/parsing.c | 218 +------- crypto_sign/perk-192-fast-3/m4/parsing.h | 76 +-- .../perk-192-fast-3/m4/parsing_permutations.c | 426 +--------------- .../perk-192-fast-3/m4/parsing_permutations.h | 54 +- crypto_sign/perk-192-fast-3/m4/permutation.c | 92 +--- crypto_sign/perk-192-fast-3/m4/permutation.h | 112 +---- crypto_sign/perk-192-fast-3/m4/sign.c | 120 +---- crypto_sign/perk-192-fast-3/m4/signature.c | 385 +------------- crypto_sign/perk-192-fast-3/m4/signature.h | 65 +-- crypto_sign/perk-192-fast-3/m4/sort.c | 129 +---- crypto_sign/perk-192-fast-3/m4/symmetric.c | 52 +- crypto_sign/perk-192-fast-3/m4/symmetric.h | 136 +---- crypto_sign/perk-192-fast-3/m4/theta_tree.c | 56 +-- crypto_sign/perk-192-fast-3/m4/theta_tree.h | 66 +-- crypto_sign/perk-192-fast-3/m4/verbose.c | 132 +---- crypto_sign/perk-192-fast-3/m4/verbose.h | 130 +---- crypto_sign/perk-192-fast-3/m4/verify.c | 161 +----- crypto_sign/perk-192-fast-3/m4/verify.h | 27 +- crypto_sign/perk-192-fast-5/m4/README | 44 +- crypto_sign/perk-192-fast-5/m4/api.h | 27 +- crypto_sign/perk-192-fast-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-192-fast-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-192-fast-5/m4/common.c | 103 +--- crypto_sign/perk-192-fast-5/m4/common.h | 110 +--- crypto_sign/perk-192-fast-5/m4/common_s.c | 43 +- .../perk-192-fast-5/m4/crypto_memset.c | 8 +- .../perk-192-fast-5/m4/crypto_memset.h | 19 +- .../perk-192-fast-5/m4/data_structures.h | 132 +---- crypto_sign/perk-192-fast-5/m4/djbsort.c | 13 +- crypto_sign/perk-192-fast-5/m4/djbsort.h | 17 +- crypto_sign/perk-192-fast-5/m4/keygen.c | 52 +- crypto_sign/perk-192-fast-5/m4/keygen.h | 22 +- crypto_sign/perk-192-fast-5/m4/parsing.c | 218 +------- crypto_sign/perk-192-fast-5/m4/parsing.h | 76 +-- .../perk-192-fast-5/m4/parsing_permutations.c | 426 +--------------- .../perk-192-fast-5/m4/parsing_permutations.h | 54 +- crypto_sign/perk-192-fast-5/m4/permutation.c | 92 +--- crypto_sign/perk-192-fast-5/m4/permutation.h | 112 +---- crypto_sign/perk-192-fast-5/m4/sign.c | 120 +---- crypto_sign/perk-192-fast-5/m4/signature.c | 385 +------------- crypto_sign/perk-192-fast-5/m4/signature.h | 65 +-- crypto_sign/perk-192-fast-5/m4/sort.c | 129 +---- crypto_sign/perk-192-fast-5/m4/symmetric.c | 52 +- crypto_sign/perk-192-fast-5/m4/symmetric.h | 136 +---- crypto_sign/perk-192-fast-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-192-fast-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-192-fast-5/m4/verbose.c | 132 +---- crypto_sign/perk-192-fast-5/m4/verbose.h | 130 +---- crypto_sign/perk-192-fast-5/m4/verify.c | 161 +----- crypto_sign/perk-192-fast-5/m4/verify.h | 27 +- crypto_sign/perk-192-short-3/m4/README | 44 +- crypto_sign/perk-192-short-3/m4/api.h | 27 +- crypto_sign/perk-192-short-3/m4/arithmetic.c | 155 +----- crypto_sign/perk-192-short-3/m4/arithmetic.h | 157 +----- crypto_sign/perk-192-short-3/m4/bn.c | 475 +----------------- crypto_sign/perk-192-short-3/m4/bn.h | 118 +---- crypto_sign/perk-192-short-3/m4/common.c | 103 +--- crypto_sign/perk-192-short-3/m4/common.h | 110 +--- crypto_sign/perk-192-short-3/m4/common_s.c | 43 +- .../perk-192-short-3/m4/crypto_memset.c | 8 +- .../perk-192-short-3/m4/crypto_memset.h | 19 +- .../perk-192-short-3/m4/data_structures.h | 132 +---- crypto_sign/perk-192-short-3/m4/djbsort.c | 13 +- crypto_sign/perk-192-short-3/m4/djbsort.h | 17 +- crypto_sign/perk-192-short-3/m4/keygen.c | 52 +- crypto_sign/perk-192-short-3/m4/keygen.h | 22 +- crypto_sign/perk-192-short-3/m4/parsing.c | 218 +------- crypto_sign/perk-192-short-3/m4/parsing.h | 76 +-- .../m4/parsing_permutations.c | 112 +---- .../m4/parsing_permutations.h | 66 +-- crypto_sign/perk-192-short-3/m4/permutation.c | 92 +--- crypto_sign/perk-192-short-3/m4/permutation.h | 112 +---- .../perk-192-short-3/m4/rank_unrank_table.h | 172 +------ crypto_sign/perk-192-short-3/m4/sign.c | 120 +---- crypto_sign/perk-192-short-3/m4/signature.c | 385 +------------- crypto_sign/perk-192-short-3/m4/signature.h | 65 +-- crypto_sign/perk-192-short-3/m4/sort.c | 129 +---- crypto_sign/perk-192-short-3/m4/symmetric.c | 52 +- crypto_sign/perk-192-short-3/m4/symmetric.h | 136 +---- crypto_sign/perk-192-short-3/m4/theta_tree.c | 56 +-- crypto_sign/perk-192-short-3/m4/theta_tree.h | 66 +-- crypto_sign/perk-192-short-3/m4/verbose.c | 132 +---- crypto_sign/perk-192-short-3/m4/verbose.h | 130 +---- crypto_sign/perk-192-short-3/m4/verify.c | 161 +----- crypto_sign/perk-192-short-3/m4/verify.h | 27 +- crypto_sign/perk-192-short-5/m4/README | 44 +- crypto_sign/perk-192-short-5/m4/api.h | 27 +- crypto_sign/perk-192-short-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-192-short-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-192-short-5/m4/bn.c | 475 +----------------- crypto_sign/perk-192-short-5/m4/bn.h | 118 +---- crypto_sign/perk-192-short-5/m4/common.c | 103 +--- crypto_sign/perk-192-short-5/m4/common.h | 110 +--- crypto_sign/perk-192-short-5/m4/common_s.c | 43 +- .../perk-192-short-5/m4/crypto_memset.c | 8 +- .../perk-192-short-5/m4/crypto_memset.h | 19 +- .../perk-192-short-5/m4/data_structures.h | 132 +---- crypto_sign/perk-192-short-5/m4/djbsort.c | 13 +- crypto_sign/perk-192-short-5/m4/djbsort.h | 17 +- crypto_sign/perk-192-short-5/m4/keygen.c | 52 +- crypto_sign/perk-192-short-5/m4/keygen.h | 22 +- crypto_sign/perk-192-short-5/m4/parsing.c | 218 +------- crypto_sign/perk-192-short-5/m4/parsing.h | 76 +-- .../m4/parsing_permutations.c | 112 +---- .../m4/parsing_permutations.h | 66 +-- crypto_sign/perk-192-short-5/m4/permutation.c | 92 +--- crypto_sign/perk-192-short-5/m4/permutation.h | 112 +---- .../perk-192-short-5/m4/rank_unrank_table.h | 172 +------ crypto_sign/perk-192-short-5/m4/sign.c | 120 +---- crypto_sign/perk-192-short-5/m4/signature.c | 385 +------------- crypto_sign/perk-192-short-5/m4/signature.h | 65 +-- crypto_sign/perk-192-short-5/m4/sort.c | 129 +---- crypto_sign/perk-192-short-5/m4/symmetric.c | 52 +- crypto_sign/perk-192-short-5/m4/symmetric.h | 136 +---- crypto_sign/perk-192-short-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-192-short-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-192-short-5/m4/verbose.c | 132 +---- crypto_sign/perk-192-short-5/m4/verbose.h | 130 +---- crypto_sign/perk-192-short-5/m4/verify.c | 161 +----- crypto_sign/perk-192-short-5/m4/verify.h | 27 +- crypto_sign/perk-256-fast-3/m4/README | 44 +- crypto_sign/perk-256-fast-3/m4/api.h | 27 +- crypto_sign/perk-256-fast-3/m4/arithmetic.c | 155 +----- crypto_sign/perk-256-fast-3/m4/arithmetic.h | 157 +----- crypto_sign/perk-256-fast-3/m4/common.c | 103 +--- crypto_sign/perk-256-fast-3/m4/common.h | 110 +--- crypto_sign/perk-256-fast-3/m4/common_s.c | 43 +- .../perk-256-fast-3/m4/crypto_memset.c | 8 +- .../perk-256-fast-3/m4/crypto_memset.h | 19 +- .../perk-256-fast-3/m4/data_structures.h | 132 +---- crypto_sign/perk-256-fast-3/m4/djbsort.c | 13 +- crypto_sign/perk-256-fast-3/m4/djbsort.h | 17 +- crypto_sign/perk-256-fast-3/m4/keygen.c | 52 +- crypto_sign/perk-256-fast-3/m4/keygen.h | 22 +- crypto_sign/perk-256-fast-3/m4/parsing.c | 218 +------- crypto_sign/perk-256-fast-3/m4/parsing.h | 76 +-- .../perk-256-fast-3/m4/parsing_permutations.c | 426 +--------------- .../perk-256-fast-3/m4/parsing_permutations.h | 54 +- crypto_sign/perk-256-fast-3/m4/permutation.c | 92 +--- crypto_sign/perk-256-fast-3/m4/permutation.h | 112 +---- crypto_sign/perk-256-fast-3/m4/sign.c | 120 +---- crypto_sign/perk-256-fast-3/m4/signature.c | 385 +------------- crypto_sign/perk-256-fast-3/m4/signature.h | 65 +-- crypto_sign/perk-256-fast-3/m4/sort.c | 129 +---- crypto_sign/perk-256-fast-3/m4/symmetric.c | 52 +- crypto_sign/perk-256-fast-3/m4/symmetric.h | 136 +---- crypto_sign/perk-256-fast-3/m4/theta_tree.c | 56 +-- crypto_sign/perk-256-fast-3/m4/theta_tree.h | 66 +-- crypto_sign/perk-256-fast-3/m4/verbose.c | 132 +---- crypto_sign/perk-256-fast-3/m4/verbose.h | 130 +---- crypto_sign/perk-256-fast-3/m4/verify.c | 161 +----- crypto_sign/perk-256-fast-3/m4/verify.h | 27 +- crypto_sign/perk-256-fast-5/m4/README | 44 +- crypto_sign/perk-256-fast-5/m4/api.h | 27 +- crypto_sign/perk-256-fast-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-256-fast-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-256-fast-5/m4/common.c | 103 +--- crypto_sign/perk-256-fast-5/m4/common.h | 110 +--- crypto_sign/perk-256-fast-5/m4/common_s.c | 43 +- .../perk-256-fast-5/m4/crypto_memset.c | 8 +- .../perk-256-fast-5/m4/crypto_memset.h | 19 +- .../perk-256-fast-5/m4/data_structures.h | 132 +---- crypto_sign/perk-256-fast-5/m4/djbsort.c | 13 +- crypto_sign/perk-256-fast-5/m4/djbsort.h | 17 +- crypto_sign/perk-256-fast-5/m4/keygen.c | 52 +- crypto_sign/perk-256-fast-5/m4/keygen.h | 22 +- crypto_sign/perk-256-fast-5/m4/parsing.c | 218 +------- crypto_sign/perk-256-fast-5/m4/parsing.h | 76 +-- .../perk-256-fast-5/m4/parsing_permutations.c | 426 +--------------- .../perk-256-fast-5/m4/parsing_permutations.h | 54 +- crypto_sign/perk-256-fast-5/m4/permutation.c | 92 +--- crypto_sign/perk-256-fast-5/m4/permutation.h | 112 +---- crypto_sign/perk-256-fast-5/m4/sign.c | 120 +---- crypto_sign/perk-256-fast-5/m4/signature.c | 385 +------------- crypto_sign/perk-256-fast-5/m4/signature.h | 65 +-- crypto_sign/perk-256-fast-5/m4/sort.c | 129 +---- crypto_sign/perk-256-fast-5/m4/symmetric.c | 52 +- crypto_sign/perk-256-fast-5/m4/symmetric.h | 136 +---- crypto_sign/perk-256-fast-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-256-fast-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-256-fast-5/m4/verbose.c | 132 +---- crypto_sign/perk-256-fast-5/m4/verbose.h | 130 +---- crypto_sign/perk-256-fast-5/m4/verify.c | 161 +----- crypto_sign/perk-256-fast-5/m4/verify.h | 27 +- crypto_sign/perk-256-short-3/m4/README | 44 +- crypto_sign/perk-256-short-3/m4/api.h | 27 +- crypto_sign/perk-256-short-3/m4/arithmetic.c | 155 +----- crypto_sign/perk-256-short-3/m4/arithmetic.h | 157 +----- crypto_sign/perk-256-short-3/m4/bn.c | 475 +----------------- crypto_sign/perk-256-short-3/m4/bn.h | 118 +---- crypto_sign/perk-256-short-3/m4/common.c | 103 +--- crypto_sign/perk-256-short-3/m4/common.h | 110 +--- crypto_sign/perk-256-short-3/m4/common_s.c | 43 +- .../perk-256-short-3/m4/crypto_memset.c | 8 +- .../perk-256-short-3/m4/crypto_memset.h | 19 +- .../perk-256-short-3/m4/data_structures.h | 132 +---- crypto_sign/perk-256-short-3/m4/djbsort.c | 13 +- crypto_sign/perk-256-short-3/m4/djbsort.h | 17 +- crypto_sign/perk-256-short-3/m4/keygen.c | 52 +- crypto_sign/perk-256-short-3/m4/keygen.h | 22 +- crypto_sign/perk-256-short-3/m4/parsing.c | 218 +------- crypto_sign/perk-256-short-3/m4/parsing.h | 76 +-- .../m4/parsing_permutations.c | 112 +---- .../m4/parsing_permutations.h | 66 +-- crypto_sign/perk-256-short-3/m4/permutation.c | 92 +--- crypto_sign/perk-256-short-3/m4/permutation.h | 112 +---- .../perk-256-short-3/m4/rank_unrank_table.h | 172 +------ crypto_sign/perk-256-short-3/m4/sign.c | 120 +---- crypto_sign/perk-256-short-3/m4/signature.c | 385 +------------- crypto_sign/perk-256-short-3/m4/signature.h | 65 +-- crypto_sign/perk-256-short-3/m4/sort.c | 129 +---- crypto_sign/perk-256-short-3/m4/symmetric.c | 52 +- crypto_sign/perk-256-short-3/m4/symmetric.h | 136 +---- crypto_sign/perk-256-short-3/m4/theta_tree.c | 56 +-- crypto_sign/perk-256-short-3/m4/theta_tree.h | 66 +-- crypto_sign/perk-256-short-3/m4/verbose.c | 132 +---- crypto_sign/perk-256-short-3/m4/verbose.h | 130 +---- crypto_sign/perk-256-short-3/m4/verify.c | 161 +----- crypto_sign/perk-256-short-3/m4/verify.h | 27 +- crypto_sign/perk-256-short-5/m4/README | 44 +- crypto_sign/perk-256-short-5/m4/api.h | 27 +- crypto_sign/perk-256-short-5/m4/arithmetic.c | 155 +----- crypto_sign/perk-256-short-5/m4/arithmetic.h | 157 +----- crypto_sign/perk-256-short-5/m4/bn.c | 475 +----------------- crypto_sign/perk-256-short-5/m4/bn.h | 118 +---- crypto_sign/perk-256-short-5/m4/common.c | 103 +--- crypto_sign/perk-256-short-5/m4/common.h | 110 +--- crypto_sign/perk-256-short-5/m4/common_s.c | 43 +- .../perk-256-short-5/m4/crypto_memset.c | 8 +- .../perk-256-short-5/m4/crypto_memset.h | 19 +- .../perk-256-short-5/m4/data_structures.h | 132 +---- crypto_sign/perk-256-short-5/m4/djbsort.c | 13 +- crypto_sign/perk-256-short-5/m4/djbsort.h | 17 +- crypto_sign/perk-256-short-5/m4/keygen.c | 52 +- crypto_sign/perk-256-short-5/m4/keygen.h | 22 +- crypto_sign/perk-256-short-5/m4/parsing.c | 218 +------- crypto_sign/perk-256-short-5/m4/parsing.h | 76 +-- .../m4/parsing_permutations.c | 112 +---- .../m4/parsing_permutations.h | 66 +-- crypto_sign/perk-256-short-5/m4/permutation.c | 92 +--- crypto_sign/perk-256-short-5/m4/permutation.h | 112 +---- .../perk-256-short-5/m4/rank_unrank_table.h | 172 +------ crypto_sign/perk-256-short-5/m4/sign.c | 120 +---- crypto_sign/perk-256-short-5/m4/signature.c | 385 +------------- crypto_sign/perk-256-short-5/m4/signature.h | 65 +-- crypto_sign/perk-256-short-5/m4/sort.c | 129 +---- crypto_sign/perk-256-short-5/m4/symmetric.c | 52 +- crypto_sign/perk-256-short-5/m4/symmetric.h | 136 +---- crypto_sign/perk-256-short-5/m4/theta_tree.c | 56 +-- crypto_sign/perk-256-short-5/m4/theta_tree.h | 66 +-- crypto_sign/perk-256-short-5/m4/verbose.c | 132 +---- crypto_sign/perk-256-short-5/m4/verbose.h | 130 +---- crypto_sign/perk-256-short-5/m4/verify.c | 161 +----- crypto_sign/perk-256-short-5/m4/verify.h | 27 +- 365 files changed, 365 insertions(+), 38199 deletions(-) mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/README mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-128-fast-5/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/README mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/api.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/common.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/common.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-128-short-3/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/README mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/bn.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/bn.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/rank_unrank_table.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-128-short-5/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/README mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/api.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/common.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/common.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-192-fast-3/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/README mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-192-fast-5/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/README mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/api.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/bn.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/bn.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/common.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/common.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/rank_unrank_table.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-192-short-3/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/README mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/bn.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/bn.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/rank_unrank_table.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-192-short-5/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/README mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/api.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/common.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/common.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-256-fast-3/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/README mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-256-fast-5/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/README mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/api.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/bn.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/bn.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/common.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/common.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/rank_unrank_table.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-256-short-3/m4/verify.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/README mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/api.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/arithmetic.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/arithmetic.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/bn.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/bn.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/common.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/common.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/common_s.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/crypto_memset.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/crypto_memset.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/data_structures.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/djbsort.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/djbsort.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/keygen.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/keygen.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/parsing.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/parsing.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/parsing_permutations.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/parsing_permutations.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/permutation.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/permutation.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/rank_unrank_table.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/sign.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/signature.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/signature.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/sort.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/symmetric.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/symmetric.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/theta_tree.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/theta_tree.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/verbose.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/verbose.h mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/verify.c mode change 100644 => 120000 crypto_sign/perk-256-short-5/m4/verify.h diff --git a/crypto_sign/perk-128-fast-5/m4/README b/crypto_sign/perk-128-fast-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-128-fast-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-128-fast-5/m4/README b/crypto_sign/perk-128-fast-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/api.h b/crypto_sign/perk-128-fast-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-128-fast-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-128-fast-5/m4/api.h b/crypto_sign/perk-128-fast-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.c b/crypto_sign/perk-128-fast-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-128-fast-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.c b/crypto_sign/perk-128-fast-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.h b/crypto_sign/perk-128-fast-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-128-fast-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/arithmetic.h b/crypto_sign/perk-128-fast-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.c b/crypto_sign/perk-128-fast-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-128-fast-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.c b/crypto_sign/perk-128-fast-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.h b/crypto_sign/perk-128-fast-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-128-fast-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common.h b/crypto_sign/perk-128-fast-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/common_s.c b/crypto_sign/perk-128-fast-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-128-fast-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-128-fast-5/m4/common_s.c b/crypto_sign/perk-128-fast-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.c b/crypto_sign/perk-128-fast-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-128-fast-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.c b/crypto_sign/perk-128-fast-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.h b/crypto_sign/perk-128-fast-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-128-fast-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-fast-5/m4/crypto_memset.h b/crypto_sign/perk-128-fast-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/data_structures.h b/crypto_sign/perk-128-fast-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-128-fast-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/data_structures.h b/crypto_sign/perk-128-fast-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.c b/crypto_sign/perk-128-fast-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-128-fast-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.c b/crypto_sign/perk-128-fast-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.h b/crypto_sign/perk-128-fast-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-128-fast-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-128-fast-5/m4/djbsort.h b/crypto_sign/perk-128-fast-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.c b/crypto_sign/perk-128-fast-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-128-fast-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.c b/crypto_sign/perk-128-fast-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.h b/crypto_sign/perk-128-fast-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-128-fast-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/keygen.h b/crypto_sign/perk-128-fast-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.c b/crypto_sign/perk-128-fast-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-128-fast-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.c b/crypto_sign/perk-128-fast-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.h b/crypto_sign/perk-128-fast-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-128-fast-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing.h b/crypto_sign/perk-128-fast-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c deleted file mode 100644 index 39acbcf6..00000000 --- a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c +++ /dev/null @@ -1,425 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -// bits needed to store two permutation coefficients -#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) -#define PARAM_N1_BITSx2 13 -#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) -#define PARAM_N1_BITSx2 14 -#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) -#define PARAM_N1_BITSx2 15 -#else -#error PARAM_N1 bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 14) -/** - * @brief store a 7 bit value in a byte array at bit position i*7 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 7 bit value to store - */ -static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7F; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 7: - sb[k + 0] |= val << 1; - break; - } -} - -/** - * @brief load a 7 bit value from a byte array at bit position i*7 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint8_t loaded value - */ -static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { - uint8_t val = 0; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - val = (sb[k + 0] & 0x7F); - break; - case 1: - val = sb[k + 0] >> 7; - val |= (sb[k + 1] & 0x3F) << 1; - break; - case 2: - val = sb[k + 0] >> 6; - val |= (sb[k + 1] & 0x1F) << 2; - break; - case 3: - val = sb[k + 0] >> 5; - val |= (sb[k + 1] & 0x0F) << 3; - break; - case 4: - val = sb[k + 0] >> 4; - val |= (sb[k + 1] & 0x07) << 4; - break; - case 5: - val = sb[k + 0] >> 3; - val |= (sb[k + 1] & 0x03) << 5; - break; - case 6: - val = sb[k + 0] >> 2; - val |= (sb[k + 1] & 0x01) << 6; - break; - case 7: - val = sb[k + 0] >> 1; - break; - default: - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 13) -/** - * @brief store a 13 bit value in a byte array at bit position i*13 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 13 bit value to store - */ -static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x1FFF; - int k = (i * 13) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 2: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 3: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - case 6: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 7: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - } -} - -/** - * @brief load a 13 bit value from a byte array at bit position i*13 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 13) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; - break; - case 1: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x03) << 11; - break; - case 2: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; - break; - case 3: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x01) << 12; - break; - case 5: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; - break; - case 6: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x07) << 10; - break; - case 7: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 15) -/** - * @brief store a 15 bit value in a byte array at bit position i*15 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 15 bit value to store - */ -static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7FFF; - int k = (i * 15) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - sb[k + 2] = val >> 13; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - sb[k + 2] = val >> 14; - break; - case 7: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - } -} - -/** - * @brief load a 15 bit value from a byte array at bit position i*15 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 15) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; - break; - case 1: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; - break; - case 2: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; - break; - case 3: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x07) << 12; - break; - case 5: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - val |= ((uint16_t)sb[k + 2] & 0x03) << 13; - break; - case 6: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; - val |= ((uint16_t)sb[k + 2] & 0x01) << 14; - break; - case 7: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; - break; - } - - return val; -} -#endif - -#if (PARAM_Q_BITS != 10) -#error PARAM_Q bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 13) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_13bit_from_bytearray(sb, i); - *c0 = val % 90; - *c1 = val / 90; -} -#elif (PARAM_N1_BITSx2 == 14) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_7bit_in_bytearray(sb, i * 2 + 0, c0); - store_7bit_in_bytearray(sb, i * 2 + 1, c1); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); - *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); -} -#elif (PARAM_N1_BITSx2 == 15) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_15bit_from_bytearray(sb, i); - *c0 = val % 181; - *c1 = val / 181; -} -#else -#error PARAM_N1 bit size not supported -#endif - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; - uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; - store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); - } -} - -/** - * @brief check the permutations to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param responses perk_response_t array of size PARAM_TAU to be checked - * @return int != 0 if a not valid permutation is found - */ -static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { - return 1; - } - } - return 0; -} - -#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) -static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0; - uint16_t z2_pi1; - - load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); - signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; - signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z2_p1_unused_mask) { - // unused bits after the z2_pi != 0 - return EXIT_FAILURE; - } - - if (permutations_not_valid(signature->responses)) { - // loaded permutations are not valid - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c new file mode 120000 index 00000000..3787fa0e --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h deleted file mode 100644 index b622b736..00000000 --- a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h +++ /dev/null @@ -1,53 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -/** - * @brief check the permutation to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param p input permutation to be checked - * @return int - */ -static inline int sig_perk_permutation_not_valid(const perm_t p) { - uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; - - for (unsigned i = 0; i < sizeof(c); i++) { - if (p[i] >= sizeof(c)) - return 1; - if (c[p[i]]) - return 1; - c[p[i]] = 1; - } - return 0; -} - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h new file mode 120000 index 00000000..7deb60e5 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.c b/crypto_sign/perk-128-fast-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-128-fast-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.c b/crypto_sign/perk-128-fast-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.h b/crypto_sign/perk-128-fast-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-128-fast-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/permutation.h b/crypto_sign/perk-128-fast-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/sign.c b/crypto_sign/perk-128-fast-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-128-fast-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/sign.c b/crypto_sign/perk-128-fast-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.c b/crypto_sign/perk-128-fast-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-128-fast-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.c b/crypto_sign/perk-128-fast-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.h b/crypto_sign/perk-128-fast-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-128-fast-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/signature.h b/crypto_sign/perk-128-fast-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/sort.c b/crypto_sign/perk-128-fast-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-128-fast-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-128-fast-5/m4/sort.c b/crypto_sign/perk-128-fast-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.c b/crypto_sign/perk-128-fast-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-128-fast-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.c b/crypto_sign/perk-128-fast-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.h b/crypto_sign/perk-128-fast-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-128-fast-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/symmetric.h b/crypto_sign/perk-128-fast-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.c b/crypto_sign/perk-128-fast-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-128-fast-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.c b/crypto_sign/perk-128-fast-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.h b/crypto_sign/perk-128-fast-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-128-fast-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/theta_tree.h b/crypto_sign/perk-128-fast-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.c b/crypto_sign/perk-128-fast-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-128-fast-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.c b/crypto_sign/perk-128-fast-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.h b/crypto_sign/perk-128-fast-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-128-fast-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verbose.h b/crypto_sign/perk-128-fast-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.c b/crypto_sign/perk-128-fast-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-128-fast-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.c b/crypto_sign/perk-128-fast-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.h b/crypto_sign/perk-128-fast-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-128-fast-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-fast-5/m4/verify.h b/crypto_sign/perk-128-fast-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-128-fast-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/README b/crypto_sign/perk-128-short-3/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-128-short-3/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-128-short-3/m4/README b/crypto_sign/perk-128-short-3/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/api.h b/crypto_sign/perk-128-short-3/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-128-short-3/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-128-short-3/m4/api.h b/crypto_sign/perk-128-short-3/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.c b/crypto_sign/perk-128-short-3/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-128-short-3/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.c b/crypto_sign/perk-128-short-3/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.h b/crypto_sign/perk-128-short-3/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-128-short-3/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/arithmetic.h b/crypto_sign/perk-128-short-3/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common.c b/crypto_sign/perk-128-short-3/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-128-short-3/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common.c b/crypto_sign/perk-128-short-3/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common.h b/crypto_sign/perk-128-short-3/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-128-short-3/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common.h b/crypto_sign/perk-128-short-3/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/common_s.c b/crypto_sign/perk-128-short-3/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-128-short-3/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-128-short-3/m4/common_s.c b/crypto_sign/perk-128-short-3/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.c b/crypto_sign/perk-128-short-3/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-128-short-3/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.c b/crypto_sign/perk-128-short-3/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.h b/crypto_sign/perk-128-short-3/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-128-short-3/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-short-3/m4/crypto_memset.h b/crypto_sign/perk-128-short-3/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/data_structures.h b/crypto_sign/perk-128-short-3/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-128-short-3/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/data_structures.h b/crypto_sign/perk-128-short-3/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.c b/crypto_sign/perk-128-short-3/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-128-short-3/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.c b/crypto_sign/perk-128-short-3/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.h b/crypto_sign/perk-128-short-3/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-128-short-3/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-128-short-3/m4/djbsort.h b/crypto_sign/perk-128-short-3/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/keygen.c b/crypto_sign/perk-128-short-3/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-128-short-3/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/keygen.c b/crypto_sign/perk-128-short-3/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/keygen.h b/crypto_sign/perk-128-short-3/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-128-short-3/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/keygen.h b/crypto_sign/perk-128-short-3/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing.c b/crypto_sign/perk-128-short-3/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-128-short-3/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing.c b/crypto_sign/perk-128-short-3/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing.h b/crypto_sign/perk-128-short-3/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-128-short-3/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/parsing.h b/crypto_sign/perk-128-short-3/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.c b/crypto_sign/perk-128-short-3/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-128-short-3/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.c b/crypto_sign/perk-128-short-3/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.h b/crypto_sign/perk-128-short-3/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-128-short-3/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/permutation.h b/crypto_sign/perk-128-short-3/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/sign.c b/crypto_sign/perk-128-short-3/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-128-short-3/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/sign.c b/crypto_sign/perk-128-short-3/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.c b/crypto_sign/perk-128-short-3/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-128-short-3/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.c b/crypto_sign/perk-128-short-3/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.h b/crypto_sign/perk-128-short-3/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-128-short-3/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/signature.h b/crypto_sign/perk-128-short-3/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/sort.c b/crypto_sign/perk-128-short-3/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-128-short-3/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-128-short-3/m4/sort.c b/crypto_sign/perk-128-short-3/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.c b/crypto_sign/perk-128-short-3/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-128-short-3/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.c b/crypto_sign/perk-128-short-3/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.h b/crypto_sign/perk-128-short-3/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-128-short-3/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/symmetric.h b/crypto_sign/perk-128-short-3/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.c b/crypto_sign/perk-128-short-3/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-128-short-3/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.c b/crypto_sign/perk-128-short-3/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.h b/crypto_sign/perk-128-short-3/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-128-short-3/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/theta_tree.h b/crypto_sign/perk-128-short-3/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.c b/crypto_sign/perk-128-short-3/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-128-short-3/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.c b/crypto_sign/perk-128-short-3/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.h b/crypto_sign/perk-128-short-3/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-128-short-3/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verbose.h b/crypto_sign/perk-128-short-3/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.c b/crypto_sign/perk-128-short-3/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-128-short-3/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.c b/crypto_sign/perk-128-short-3/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.h b/crypto_sign/perk-128-short-3/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-128-short-3/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-3/m4/verify.h b/crypto_sign/perk-128-short-3/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-128-short-3/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/README b/crypto_sign/perk-128-short-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-128-short-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-128-short-5/m4/README b/crypto_sign/perk-128-short-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/api.h b/crypto_sign/perk-128-short-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-128-short-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-128-short-5/m4/api.h b/crypto_sign/perk-128-short-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.c b/crypto_sign/perk-128-short-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-128-short-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.c b/crypto_sign/perk-128-short-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.h b/crypto_sign/perk-128-short-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-128-short-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/arithmetic.h b/crypto_sign/perk-128-short-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/bn.c b/crypto_sign/perk-128-short-5/m4/bn.c deleted file mode 100644 index b676feb3..00000000 --- a/crypto_sign/perk-128-short-5/m4/bn.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include -#include "bn.h" - - - -/* Functions for shifting number in-place. */ -static void _lshift_one_bit(struct bn* a); -static void _rshift_one_bit(struct bn* a); -static void _lshift_word(struct bn* a, int nwords); -static void _rshift_word(struct bn* a, int nwords); - - - -/* Public / Exported functions. */ -void bignum_init(struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - n->array[i] = 0; - } -} - - -void bignum_from_int(struct bn* n, DTYPE_TMP i) -{ - require(n, "n is null"); - - bignum_init(n); - - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE -#if (WORD_SIZE == 1) - n->array[0] = (i & 0x000000ff); - n->array[1] = (i & 0x0000ff00) >> 8; - n->array[2] = (i & 0x00ff0000) >> 16; - n->array[3] = (i & 0xff000000) >> 24; -#elif (WORD_SIZE == 2) - n->array[0] = (i & 0x0000ffff); - n->array[1] = (i & 0xffff0000) >> 16; -#elif (WORD_SIZE == 4) - n->array[0] = i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n->array[1] = tmp; -#endif -#endif -} - - -int bignum_to_int(struct bn* n) -{ - require(n, "n is null"); - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n->array[0]; - ret += n->array[1] << 8; - ret += n->array[2] << 16; - ret += n->array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n->array[0]; - ret += n->array[1] << 16; -#elif (WORD_SIZE == 4) - ret += (int)n->array[0]; -#endif - - return ret; -} - -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; - carry = (tmp > MAX_VAL); - c->array[i] = (tmp & MAX_VAL); - } -} - - -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b->array[i] + borrow; - res = (tmp1 - tmp2); - c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } -} - - -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - bignum_init(c); - - if (bignum_is_zero(a)) {return;} - if (bignum_is_zero(b)) {return;} - - struct bn tmp; - struct bn max_val; - bignum_from_int(&max_val, MAX_VAL); - - struct bn a1; - DTYPE_TMP a0; - struct bn b1; - DTYPE_TMP b0; - struct bn z0; - struct bn z1; - struct bn z2; - - bignum_rshift(a, &a1, WORD_SIZE*8); - bignum_rshift(b, &b1, WORD_SIZE*8); - a0 = (DTYPE_TMP)(a->array[0]); - b0 = (DTYPE_TMP)(b->array[0]); - DTYPE_TMP z0_small = a0*b0; - - bignum_init(&z0); - z0.array[0] = z0_small & MAX_VAL; - z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); - if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { - bignum_assign(c, &z0); - return; - } - bignum_mul(&a1, &b1, &z2); - struct bn a0_big; - struct bn b0_big; - bignum_from_int(&a0_big, a0); - bignum_from_int(&b0_big, b0); - - struct bn tmpa; - struct bn tmpb; - struct bn tmpz1; - bignum_add(&a1, &a0_big, &tmpa); - bignum_add(&b1, &b0_big, &tmpb); - bignum_mul(&tmpa, &tmpb, &tmpz1); - bignum_sub(&tmpz1, &z2, &tmpa); - bignum_sub(&tmpa, &z0, &z1); - - bignum_lshift(&z2, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z1, c); - bignum_lshift(c, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z0, c); -} - - -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn current; - struct bn denom; - struct bn tmp; - - bignum_from_int(¤t, 1); // int current = 1; - bignum_assign(&denom, b); // denom = b - bignum_assign(&tmp, a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { - { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) - { - overflow = true; - break; - } - _lshift_one_bit(¤t); // current <<= 1; - _lshift_one_bit(&denom); // denom <<= 1; - } - if (!overflow) - { - _rshift_one_bit(&denom); // denom >>= 1; - _rshift_one_bit(¤t); // current >>= 1; - } - bignum_init(c); // int answer = 0; - - while (!bignum_is_zero(¤t)) // while (current != 0) - { - if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) - { - bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; - bignum_or(c, ¤t, c); // answer |= current; - } - _rshift_one_bit(¤t); // current >>= 1; - _rshift_one_bit(&denom); // denom >>= 1; - } // return answer; -} - - -void bignum_lshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b->array[i] <<= nbits; - } -} - - -void bignum_rshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b->array[i] >>= nbits; - } - -} - - -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) -{ - /* - Take divmod and throw away div part - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - bignum_divmod(a,b,&tmp,c); -} - -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) -{ - /* - Puts a%b in d - and a/b in c - - mod(a,b) = a - ((a / b) * b) - - example: - mod(8, 3) = 8 - ((8 / 3) * 3) = 2 - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - /* c = (a / b) */ - bignum_div(a, b, c); - - /* tmp = (c * b) */ - bignum_mul(c, b, &tmp); - - /* c = a - tmp */ - bignum_sub(a, &tmp, d); -} - -void bignum_or(struct bn* a, struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - c->array[i] = (a->array[i] | b->array[i]); - } -} - -int bignum_cmp(const struct bn *a, const struct bn *b) -{ - require(a, "a is null"); - require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do - { - i -= 1; /* Decrement first, to start with last array element */ - if (a->array[i] > b->array[i]) - { - return LARGER; - } - else if (a->array[i] < b->array[i]) - { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -int bignum_is_zero(const struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - if (n->array[i]) - { - return 0; - } - } - - return 1; -} - -void bignum_assign(struct bn* dst, const struct bn* src) -{ - require(dst, "dst is null"); - require(src, "src is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - dst->array[i] = src->array[i]; - } -} - - -/* Private / Static functions. */ -static void _rshift_word(struct bn* a, int nwords) -{ - /* Naive method: */ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - if (nwords >= BN_ARRAY_SIZE) - { - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } - return; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) - { - a->array[i] = a->array[i + nwords]; - } - for (; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } -} - - -static void _lshift_word(struct bn* a, int nwords) -{ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) - { - a->array[i] = a->array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) - { - a->array[i] = 0; - } -} - - -static void _lshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a->array[0] <<= 1; -} - - -static void _rshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a->array[BN_ARRAY_SIZE - 1] >>= 1; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/bn.c b/crypto_sign/perk-128-short-5/m4/bn.c new file mode 120000 index 00000000..f7757f12 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/bn.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/bn.h b/crypto_sign/perk-128-short-5/m4/bn.h deleted file mode 100644 index c0debe59..00000000 --- a/crypto_sign/perk-128-short-5/m4/bn.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && msg) - - -/* Data-holding structure: array of DTYPEs */ -struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -}; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - - - -/* Initialization functions: */ -void bignum_init(struct bn* n); -void bignum_from_int(struct bn* n, DTYPE_TMP i); -int bignum_to_int(struct bn* n); - -/* Basic arithmetic operations: */ -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - -/* Bitwise operations: */ -void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ -void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ -void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ - -/* Special operators and comparison */ -int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ -int bignum_is_zero(const struct bn* n); /* For comparison with zero */ -void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ - - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/crypto_sign/perk-128-short-5/m4/bn.h b/crypto_sign/perk-128-short-5/m4/bn.h new file mode 120000 index 00000000..644cc71b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/bn.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common.c b/crypto_sign/perk-128-short-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-128-short-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common.c b/crypto_sign/perk-128-short-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common.h b/crypto_sign/perk-128-short-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-128-short-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common.h b/crypto_sign/perk-128-short-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/common_s.c b/crypto_sign/perk-128-short-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-128-short-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-128-short-5/m4/common_s.c b/crypto_sign/perk-128-short-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.c b/crypto_sign/perk-128-short-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-128-short-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.c b/crypto_sign/perk-128-short-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.h b/crypto_sign/perk-128-short-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-128-short-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-128-short-5/m4/crypto_memset.h b/crypto_sign/perk-128-short-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/data_structures.h b/crypto_sign/perk-128-short-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-128-short-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/data_structures.h b/crypto_sign/perk-128-short-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.c b/crypto_sign/perk-128-short-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-128-short-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.c b/crypto_sign/perk-128-short-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.h b/crypto_sign/perk-128-short-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-128-short-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-128-short-5/m4/djbsort.h b/crypto_sign/perk-128-short-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/keygen.c b/crypto_sign/perk-128-short-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-128-short-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/keygen.c b/crypto_sign/perk-128-short-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/keygen.h b/crypto_sign/perk-128-short-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-128-short-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/keygen.h b/crypto_sign/perk-128-short-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing.c b/crypto_sign/perk-128-short-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-128-short-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing.c b/crypto_sign/perk-128-short-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing.h b/crypto_sign/perk-128-short-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-128-short-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing.h b/crypto_sign/perk-128-short-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.c b/crypto_sign/perk-128-short-5/m4/parsing_permutations.c deleted file mode 100644 index 6edb9a7e..00000000 --- a/crypto_sign/perk-128-short-5/m4/parsing_permutations.c +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "rank_unrank_table.h" -#include "symmetric.h" - -#define PARAM_RANK_UNRANK_LEN_T \ - ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ - -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { - struct bn mul, code, tmp; - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - bignum_init(&code); - for (int i = 0; i < PARAM_N1; ++i) { - uint8_t ctr = in_p[i]; - uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - if (node & 0x1) { - ctr -= T[(node >> 1) << 1]; - } - T[node] += 1; - node = node >> 1; - } - T[node] += 1; - bignum_from_int(&tmp, PARAM_N1 - i); - bignum_mul(&code, &tmp, &mul); - bignum_from_int(&tmp, ctr); - bignum_add(&mul, &tmp, &code); - } - - memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); - memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); -} - -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { - struct bn code, tmp, tmp2, tmp3; - bignum_init(&code); - - memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); - - // validate the permutation encoding to be < n! - if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { - return EXIT_FAILURE; - } - - bignum_mod(&code, &factorial[PARAM_N1], &tmp); - bignum_assign(&tmp3, &tmp); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); - out_p[0] = bignum_to_int(&tmp); - - for (int i = 1; i < PARAM_N1 - 1; ++i) { - bignum_assign(&tmp3, &tmp2); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); - out_p[i] = bignum_to_int(&tmp); - } - - bignum_div(&tmp2, &factorial[0], &tmp); - out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { - for (int j = 0; j < (1 << i); ++j) { - T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); - } - } - - for (int i = 0; i < PARAM_N1; ++i) { - int digit = out_p[i]; - uint16_t node = 1; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - T[node] -= 1; - node <<= 1; - if (digit >= T[node]) { - digit -= T[node]; - node += 1; - } - } - T[node] = 0; - out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); - } - - return EXIT_SUCCESS; -} - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < (PARAM_TAU); i++) { - sig_perk_perm_encode(signature->responses[i].z2_pi, sb); - sb += PARAM_PERM_COMPRESSION_BYTES; - } -} - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - sb += PARAM_PERM_COMPRESSION_BYTES; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.c b/crypto_sign/perk-128-short-5/m4/parsing_permutations.c new file mode 120000 index 00000000..4227070c --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.h b/crypto_sign/perk-128-short-5/m4/parsing_permutations.h deleted file mode 100644 index 52c64e70..00000000 --- a/crypto_sign/perk-128-short-5/m4/parsing_permutations.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Permutation rank encoding. Encode a permutation into a bytearray. - * - * @param in_p input permutation - * @param out_buff output buffer byte string - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); - -/** - * @brief Permutation unrank decoding. Decode a bytearray into a permutation. - * - * @param in_buff input buffer byte string - * @param out_p output permutation - * @return EXIT_SUCCESS or EXIT_FAILURE - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/parsing_permutations.h b/crypto_sign/perk-128-short-5/m4/parsing_permutations.h new file mode 120000 index 00000000..f78f116d --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.c b/crypto_sign/perk-128-short-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-128-short-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.c b/crypto_sign/perk-128-short-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.h b/crypto_sign/perk-128-short-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-128-short-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/permutation.h b/crypto_sign/perk-128-short-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h deleted file mode 100644 index c530d04f..00000000 --- a/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file rank_unrank_table.h - * @brief Look-up table used in rank/unrank compression. - * For the GMP version, the encoding is in base-62 - * For tiny-bignum, the setting is for 32 bit architectures - * - * Each i-th value is i! encoded in base-62. - * - */ - -#ifndef SIG_PKP_RANK_UNRANK_TABLE_H -#define SIG_PKP_RANK_UNRANK_TABLE_H - -#include "bn.h" - -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} - -}; - -#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h new file mode 120000 index 00000000..0466ec6b --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/rank_unrank_table.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./rank_unrank_table.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/sign.c b/crypto_sign/perk-128-short-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-128-short-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/sign.c b/crypto_sign/perk-128-short-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.c b/crypto_sign/perk-128-short-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-128-short-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.c b/crypto_sign/perk-128-short-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.h b/crypto_sign/perk-128-short-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-128-short-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/signature.h b/crypto_sign/perk-128-short-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/sort.c b/crypto_sign/perk-128-short-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-128-short-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-128-short-5/m4/sort.c b/crypto_sign/perk-128-short-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.c b/crypto_sign/perk-128-short-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-128-short-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.c b/crypto_sign/perk-128-short-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.h b/crypto_sign/perk-128-short-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-128-short-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/symmetric.h b/crypto_sign/perk-128-short-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.c b/crypto_sign/perk-128-short-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-128-short-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.c b/crypto_sign/perk-128-short-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.h b/crypto_sign/perk-128-short-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-128-short-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/theta_tree.h b/crypto_sign/perk-128-short-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.c b/crypto_sign/perk-128-short-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-128-short-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.c b/crypto_sign/perk-128-short-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.h b/crypto_sign/perk-128-short-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-128-short-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verbose.h b/crypto_sign/perk-128-short-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.c b/crypto_sign/perk-128-short-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-128-short-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.c b/crypto_sign/perk-128-short-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.h b/crypto_sign/perk-128-short-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-128-short-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-128-short-5/m4/verify.h b/crypto_sign/perk-128-short-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-128-short-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/README b/crypto_sign/perk-192-fast-3/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-192-fast-3/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-192-fast-3/m4/README b/crypto_sign/perk-192-fast-3/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/api.h b/crypto_sign/perk-192-fast-3/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-192-fast-3/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-192-fast-3/m4/api.h b/crypto_sign/perk-192-fast-3/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.c b/crypto_sign/perk-192-fast-3/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-192-fast-3/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.c b/crypto_sign/perk-192-fast-3/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.h b/crypto_sign/perk-192-fast-3/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-192-fast-3/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/arithmetic.h b/crypto_sign/perk-192-fast-3/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.c b/crypto_sign/perk-192-fast-3/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-192-fast-3/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.c b/crypto_sign/perk-192-fast-3/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.h b/crypto_sign/perk-192-fast-3/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-192-fast-3/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common.h b/crypto_sign/perk-192-fast-3/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/common_s.c b/crypto_sign/perk-192-fast-3/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-192-fast-3/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-192-fast-3/m4/common_s.c b/crypto_sign/perk-192-fast-3/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.c b/crypto_sign/perk-192-fast-3/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-192-fast-3/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.c b/crypto_sign/perk-192-fast-3/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.h b/crypto_sign/perk-192-fast-3/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-192-fast-3/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-fast-3/m4/crypto_memset.h b/crypto_sign/perk-192-fast-3/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/data_structures.h b/crypto_sign/perk-192-fast-3/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-192-fast-3/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/data_structures.h b/crypto_sign/perk-192-fast-3/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.c b/crypto_sign/perk-192-fast-3/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-192-fast-3/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.c b/crypto_sign/perk-192-fast-3/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.h b/crypto_sign/perk-192-fast-3/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-192-fast-3/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-192-fast-3/m4/djbsort.h b/crypto_sign/perk-192-fast-3/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.c b/crypto_sign/perk-192-fast-3/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-192-fast-3/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.c b/crypto_sign/perk-192-fast-3/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.h b/crypto_sign/perk-192-fast-3/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-192-fast-3/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/keygen.h b/crypto_sign/perk-192-fast-3/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.c b/crypto_sign/perk-192-fast-3/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-192-fast-3/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.c b/crypto_sign/perk-192-fast-3/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.h b/crypto_sign/perk-192-fast-3/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-192-fast-3/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing.h b/crypto_sign/perk-192-fast-3/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c deleted file mode 100644 index 39acbcf6..00000000 --- a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c +++ /dev/null @@ -1,425 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -// bits needed to store two permutation coefficients -#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) -#define PARAM_N1_BITSx2 13 -#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) -#define PARAM_N1_BITSx2 14 -#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) -#define PARAM_N1_BITSx2 15 -#else -#error PARAM_N1 bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 14) -/** - * @brief store a 7 bit value in a byte array at bit position i*7 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 7 bit value to store - */ -static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7F; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 7: - sb[k + 0] |= val << 1; - break; - } -} - -/** - * @brief load a 7 bit value from a byte array at bit position i*7 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint8_t loaded value - */ -static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { - uint8_t val = 0; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - val = (sb[k + 0] & 0x7F); - break; - case 1: - val = sb[k + 0] >> 7; - val |= (sb[k + 1] & 0x3F) << 1; - break; - case 2: - val = sb[k + 0] >> 6; - val |= (sb[k + 1] & 0x1F) << 2; - break; - case 3: - val = sb[k + 0] >> 5; - val |= (sb[k + 1] & 0x0F) << 3; - break; - case 4: - val = sb[k + 0] >> 4; - val |= (sb[k + 1] & 0x07) << 4; - break; - case 5: - val = sb[k + 0] >> 3; - val |= (sb[k + 1] & 0x03) << 5; - break; - case 6: - val = sb[k + 0] >> 2; - val |= (sb[k + 1] & 0x01) << 6; - break; - case 7: - val = sb[k + 0] >> 1; - break; - default: - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 13) -/** - * @brief store a 13 bit value in a byte array at bit position i*13 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 13 bit value to store - */ -static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x1FFF; - int k = (i * 13) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 2: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 3: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - case 6: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 7: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - } -} - -/** - * @brief load a 13 bit value from a byte array at bit position i*13 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 13) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; - break; - case 1: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x03) << 11; - break; - case 2: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; - break; - case 3: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x01) << 12; - break; - case 5: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; - break; - case 6: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x07) << 10; - break; - case 7: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 15) -/** - * @brief store a 15 bit value in a byte array at bit position i*15 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 15 bit value to store - */ -static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7FFF; - int k = (i * 15) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - sb[k + 2] = val >> 13; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - sb[k + 2] = val >> 14; - break; - case 7: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - } -} - -/** - * @brief load a 15 bit value from a byte array at bit position i*15 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 15) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; - break; - case 1: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; - break; - case 2: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; - break; - case 3: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x07) << 12; - break; - case 5: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - val |= ((uint16_t)sb[k + 2] & 0x03) << 13; - break; - case 6: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; - val |= ((uint16_t)sb[k + 2] & 0x01) << 14; - break; - case 7: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; - break; - } - - return val; -} -#endif - -#if (PARAM_Q_BITS != 10) -#error PARAM_Q bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 13) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_13bit_from_bytearray(sb, i); - *c0 = val % 90; - *c1 = val / 90; -} -#elif (PARAM_N1_BITSx2 == 14) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_7bit_in_bytearray(sb, i * 2 + 0, c0); - store_7bit_in_bytearray(sb, i * 2 + 1, c1); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); - *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); -} -#elif (PARAM_N1_BITSx2 == 15) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_15bit_from_bytearray(sb, i); - *c0 = val % 181; - *c1 = val / 181; -} -#else -#error PARAM_N1 bit size not supported -#endif - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; - uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; - store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); - } -} - -/** - * @brief check the permutations to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param responses perk_response_t array of size PARAM_TAU to be checked - * @return int != 0 if a not valid permutation is found - */ -static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { - return 1; - } - } - return 0; -} - -#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) -static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0; - uint16_t z2_pi1; - - load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); - signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; - signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z2_p1_unused_mask) { - // unused bits after the z2_pi != 0 - return EXIT_FAILURE; - } - - if (permutations_not_valid(signature->responses)) { - // loaded permutations are not valid - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c new file mode 120000 index 00000000..3787fa0e --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h deleted file mode 100644 index b622b736..00000000 --- a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h +++ /dev/null @@ -1,53 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -/** - * @brief check the permutation to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param p input permutation to be checked - * @return int - */ -static inline int sig_perk_permutation_not_valid(const perm_t p) { - uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; - - for (unsigned i = 0; i < sizeof(c); i++) { - if (p[i] >= sizeof(c)) - return 1; - if (c[p[i]]) - return 1; - c[p[i]] = 1; - } - return 0; -} - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h new file mode 120000 index 00000000..7deb60e5 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.c b/crypto_sign/perk-192-fast-3/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-192-fast-3/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.c b/crypto_sign/perk-192-fast-3/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.h b/crypto_sign/perk-192-fast-3/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-192-fast-3/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/permutation.h b/crypto_sign/perk-192-fast-3/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/sign.c b/crypto_sign/perk-192-fast-3/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-192-fast-3/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/sign.c b/crypto_sign/perk-192-fast-3/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.c b/crypto_sign/perk-192-fast-3/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-192-fast-3/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.c b/crypto_sign/perk-192-fast-3/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.h b/crypto_sign/perk-192-fast-3/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-192-fast-3/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/signature.h b/crypto_sign/perk-192-fast-3/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/sort.c b/crypto_sign/perk-192-fast-3/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-192-fast-3/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-192-fast-3/m4/sort.c b/crypto_sign/perk-192-fast-3/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.c b/crypto_sign/perk-192-fast-3/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-192-fast-3/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.c b/crypto_sign/perk-192-fast-3/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.h b/crypto_sign/perk-192-fast-3/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-192-fast-3/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/symmetric.h b/crypto_sign/perk-192-fast-3/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.c b/crypto_sign/perk-192-fast-3/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-192-fast-3/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.c b/crypto_sign/perk-192-fast-3/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.h b/crypto_sign/perk-192-fast-3/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-192-fast-3/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/theta_tree.h b/crypto_sign/perk-192-fast-3/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.c b/crypto_sign/perk-192-fast-3/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-192-fast-3/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.c b/crypto_sign/perk-192-fast-3/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.h b/crypto_sign/perk-192-fast-3/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-192-fast-3/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verbose.h b/crypto_sign/perk-192-fast-3/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.c b/crypto_sign/perk-192-fast-3/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-192-fast-3/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.c b/crypto_sign/perk-192-fast-3/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.h b/crypto_sign/perk-192-fast-3/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-192-fast-3/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-3/m4/verify.h b/crypto_sign/perk-192-fast-3/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-192-fast-3/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/README b/crypto_sign/perk-192-fast-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-192-fast-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-192-fast-5/m4/README b/crypto_sign/perk-192-fast-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/api.h b/crypto_sign/perk-192-fast-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-192-fast-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-192-fast-5/m4/api.h b/crypto_sign/perk-192-fast-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.c b/crypto_sign/perk-192-fast-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-192-fast-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.c b/crypto_sign/perk-192-fast-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.h b/crypto_sign/perk-192-fast-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-192-fast-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/arithmetic.h b/crypto_sign/perk-192-fast-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.c b/crypto_sign/perk-192-fast-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-192-fast-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.c b/crypto_sign/perk-192-fast-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.h b/crypto_sign/perk-192-fast-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-192-fast-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common.h b/crypto_sign/perk-192-fast-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/common_s.c b/crypto_sign/perk-192-fast-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-192-fast-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-192-fast-5/m4/common_s.c b/crypto_sign/perk-192-fast-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.c b/crypto_sign/perk-192-fast-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-192-fast-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.c b/crypto_sign/perk-192-fast-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.h b/crypto_sign/perk-192-fast-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-192-fast-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-fast-5/m4/crypto_memset.h b/crypto_sign/perk-192-fast-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/data_structures.h b/crypto_sign/perk-192-fast-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-192-fast-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/data_structures.h b/crypto_sign/perk-192-fast-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.c b/crypto_sign/perk-192-fast-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-192-fast-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.c b/crypto_sign/perk-192-fast-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.h b/crypto_sign/perk-192-fast-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-192-fast-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-192-fast-5/m4/djbsort.h b/crypto_sign/perk-192-fast-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.c b/crypto_sign/perk-192-fast-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-192-fast-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.c b/crypto_sign/perk-192-fast-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.h b/crypto_sign/perk-192-fast-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-192-fast-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/keygen.h b/crypto_sign/perk-192-fast-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.c b/crypto_sign/perk-192-fast-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-192-fast-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.c b/crypto_sign/perk-192-fast-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.h b/crypto_sign/perk-192-fast-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-192-fast-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing.h b/crypto_sign/perk-192-fast-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c deleted file mode 100644 index 39acbcf6..00000000 --- a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c +++ /dev/null @@ -1,425 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -// bits needed to store two permutation coefficients -#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) -#define PARAM_N1_BITSx2 13 -#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) -#define PARAM_N1_BITSx2 14 -#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) -#define PARAM_N1_BITSx2 15 -#else -#error PARAM_N1 bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 14) -/** - * @brief store a 7 bit value in a byte array at bit position i*7 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 7 bit value to store - */ -static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7F; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 7: - sb[k + 0] |= val << 1; - break; - } -} - -/** - * @brief load a 7 bit value from a byte array at bit position i*7 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint8_t loaded value - */ -static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { - uint8_t val = 0; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - val = (sb[k + 0] & 0x7F); - break; - case 1: - val = sb[k + 0] >> 7; - val |= (sb[k + 1] & 0x3F) << 1; - break; - case 2: - val = sb[k + 0] >> 6; - val |= (sb[k + 1] & 0x1F) << 2; - break; - case 3: - val = sb[k + 0] >> 5; - val |= (sb[k + 1] & 0x0F) << 3; - break; - case 4: - val = sb[k + 0] >> 4; - val |= (sb[k + 1] & 0x07) << 4; - break; - case 5: - val = sb[k + 0] >> 3; - val |= (sb[k + 1] & 0x03) << 5; - break; - case 6: - val = sb[k + 0] >> 2; - val |= (sb[k + 1] & 0x01) << 6; - break; - case 7: - val = sb[k + 0] >> 1; - break; - default: - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 13) -/** - * @brief store a 13 bit value in a byte array at bit position i*13 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 13 bit value to store - */ -static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x1FFF; - int k = (i * 13) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 2: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 3: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - case 6: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 7: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - } -} - -/** - * @brief load a 13 bit value from a byte array at bit position i*13 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 13) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; - break; - case 1: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x03) << 11; - break; - case 2: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; - break; - case 3: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x01) << 12; - break; - case 5: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; - break; - case 6: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x07) << 10; - break; - case 7: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 15) -/** - * @brief store a 15 bit value in a byte array at bit position i*15 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 15 bit value to store - */ -static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7FFF; - int k = (i * 15) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - sb[k + 2] = val >> 13; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - sb[k + 2] = val >> 14; - break; - case 7: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - } -} - -/** - * @brief load a 15 bit value from a byte array at bit position i*15 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 15) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; - break; - case 1: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; - break; - case 2: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; - break; - case 3: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x07) << 12; - break; - case 5: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - val |= ((uint16_t)sb[k + 2] & 0x03) << 13; - break; - case 6: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; - val |= ((uint16_t)sb[k + 2] & 0x01) << 14; - break; - case 7: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; - break; - } - - return val; -} -#endif - -#if (PARAM_Q_BITS != 10) -#error PARAM_Q bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 13) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_13bit_from_bytearray(sb, i); - *c0 = val % 90; - *c1 = val / 90; -} -#elif (PARAM_N1_BITSx2 == 14) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_7bit_in_bytearray(sb, i * 2 + 0, c0); - store_7bit_in_bytearray(sb, i * 2 + 1, c1); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); - *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); -} -#elif (PARAM_N1_BITSx2 == 15) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_15bit_from_bytearray(sb, i); - *c0 = val % 181; - *c1 = val / 181; -} -#else -#error PARAM_N1 bit size not supported -#endif - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; - uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; - store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); - } -} - -/** - * @brief check the permutations to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param responses perk_response_t array of size PARAM_TAU to be checked - * @return int != 0 if a not valid permutation is found - */ -static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { - return 1; - } - } - return 0; -} - -#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) -static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0; - uint16_t z2_pi1; - - load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); - signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; - signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z2_p1_unused_mask) { - // unused bits after the z2_pi != 0 - return EXIT_FAILURE; - } - - if (permutations_not_valid(signature->responses)) { - // loaded permutations are not valid - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c new file mode 120000 index 00000000..3787fa0e --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h deleted file mode 100644 index b622b736..00000000 --- a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h +++ /dev/null @@ -1,53 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -/** - * @brief check the permutation to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param p input permutation to be checked - * @return int - */ -static inline int sig_perk_permutation_not_valid(const perm_t p) { - uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; - - for (unsigned i = 0; i < sizeof(c); i++) { - if (p[i] >= sizeof(c)) - return 1; - if (c[p[i]]) - return 1; - c[p[i]] = 1; - } - return 0; -} - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h new file mode 120000 index 00000000..7deb60e5 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.c b/crypto_sign/perk-192-fast-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-192-fast-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.c b/crypto_sign/perk-192-fast-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.h b/crypto_sign/perk-192-fast-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-192-fast-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/permutation.h b/crypto_sign/perk-192-fast-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/sign.c b/crypto_sign/perk-192-fast-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-192-fast-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/sign.c b/crypto_sign/perk-192-fast-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.c b/crypto_sign/perk-192-fast-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-192-fast-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.c b/crypto_sign/perk-192-fast-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.h b/crypto_sign/perk-192-fast-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-192-fast-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/signature.h b/crypto_sign/perk-192-fast-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/sort.c b/crypto_sign/perk-192-fast-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-192-fast-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-192-fast-5/m4/sort.c b/crypto_sign/perk-192-fast-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.c b/crypto_sign/perk-192-fast-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-192-fast-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.c b/crypto_sign/perk-192-fast-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.h b/crypto_sign/perk-192-fast-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-192-fast-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/symmetric.h b/crypto_sign/perk-192-fast-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.c b/crypto_sign/perk-192-fast-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-192-fast-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.c b/crypto_sign/perk-192-fast-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.h b/crypto_sign/perk-192-fast-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-192-fast-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/theta_tree.h b/crypto_sign/perk-192-fast-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.c b/crypto_sign/perk-192-fast-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-192-fast-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.c b/crypto_sign/perk-192-fast-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.h b/crypto_sign/perk-192-fast-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-192-fast-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verbose.h b/crypto_sign/perk-192-fast-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.c b/crypto_sign/perk-192-fast-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-192-fast-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.c b/crypto_sign/perk-192-fast-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.h b/crypto_sign/perk-192-fast-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-192-fast-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-fast-5/m4/verify.h b/crypto_sign/perk-192-fast-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-192-fast-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/README b/crypto_sign/perk-192-short-3/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-192-short-3/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-192-short-3/m4/README b/crypto_sign/perk-192-short-3/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/api.h b/crypto_sign/perk-192-short-3/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-192-short-3/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-192-short-3/m4/api.h b/crypto_sign/perk-192-short-3/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.c b/crypto_sign/perk-192-short-3/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-192-short-3/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.c b/crypto_sign/perk-192-short-3/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.h b/crypto_sign/perk-192-short-3/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-192-short-3/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/arithmetic.h b/crypto_sign/perk-192-short-3/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/bn.c b/crypto_sign/perk-192-short-3/m4/bn.c deleted file mode 100644 index b676feb3..00000000 --- a/crypto_sign/perk-192-short-3/m4/bn.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include -#include "bn.h" - - - -/* Functions for shifting number in-place. */ -static void _lshift_one_bit(struct bn* a); -static void _rshift_one_bit(struct bn* a); -static void _lshift_word(struct bn* a, int nwords); -static void _rshift_word(struct bn* a, int nwords); - - - -/* Public / Exported functions. */ -void bignum_init(struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - n->array[i] = 0; - } -} - - -void bignum_from_int(struct bn* n, DTYPE_TMP i) -{ - require(n, "n is null"); - - bignum_init(n); - - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE -#if (WORD_SIZE == 1) - n->array[0] = (i & 0x000000ff); - n->array[1] = (i & 0x0000ff00) >> 8; - n->array[2] = (i & 0x00ff0000) >> 16; - n->array[3] = (i & 0xff000000) >> 24; -#elif (WORD_SIZE == 2) - n->array[0] = (i & 0x0000ffff); - n->array[1] = (i & 0xffff0000) >> 16; -#elif (WORD_SIZE == 4) - n->array[0] = i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n->array[1] = tmp; -#endif -#endif -} - - -int bignum_to_int(struct bn* n) -{ - require(n, "n is null"); - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n->array[0]; - ret += n->array[1] << 8; - ret += n->array[2] << 16; - ret += n->array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n->array[0]; - ret += n->array[1] << 16; -#elif (WORD_SIZE == 4) - ret += (int)n->array[0]; -#endif - - return ret; -} - -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; - carry = (tmp > MAX_VAL); - c->array[i] = (tmp & MAX_VAL); - } -} - - -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b->array[i] + borrow; - res = (tmp1 - tmp2); - c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } -} - - -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - bignum_init(c); - - if (bignum_is_zero(a)) {return;} - if (bignum_is_zero(b)) {return;} - - struct bn tmp; - struct bn max_val; - bignum_from_int(&max_val, MAX_VAL); - - struct bn a1; - DTYPE_TMP a0; - struct bn b1; - DTYPE_TMP b0; - struct bn z0; - struct bn z1; - struct bn z2; - - bignum_rshift(a, &a1, WORD_SIZE*8); - bignum_rshift(b, &b1, WORD_SIZE*8); - a0 = (DTYPE_TMP)(a->array[0]); - b0 = (DTYPE_TMP)(b->array[0]); - DTYPE_TMP z0_small = a0*b0; - - bignum_init(&z0); - z0.array[0] = z0_small & MAX_VAL; - z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); - if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { - bignum_assign(c, &z0); - return; - } - bignum_mul(&a1, &b1, &z2); - struct bn a0_big; - struct bn b0_big; - bignum_from_int(&a0_big, a0); - bignum_from_int(&b0_big, b0); - - struct bn tmpa; - struct bn tmpb; - struct bn tmpz1; - bignum_add(&a1, &a0_big, &tmpa); - bignum_add(&b1, &b0_big, &tmpb); - bignum_mul(&tmpa, &tmpb, &tmpz1); - bignum_sub(&tmpz1, &z2, &tmpa); - bignum_sub(&tmpa, &z0, &z1); - - bignum_lshift(&z2, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z1, c); - bignum_lshift(c, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z0, c); -} - - -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn current; - struct bn denom; - struct bn tmp; - - bignum_from_int(¤t, 1); // int current = 1; - bignum_assign(&denom, b); // denom = b - bignum_assign(&tmp, a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { - { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) - { - overflow = true; - break; - } - _lshift_one_bit(¤t); // current <<= 1; - _lshift_one_bit(&denom); // denom <<= 1; - } - if (!overflow) - { - _rshift_one_bit(&denom); // denom >>= 1; - _rshift_one_bit(¤t); // current >>= 1; - } - bignum_init(c); // int answer = 0; - - while (!bignum_is_zero(¤t)) // while (current != 0) - { - if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) - { - bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; - bignum_or(c, ¤t, c); // answer |= current; - } - _rshift_one_bit(¤t); // current >>= 1; - _rshift_one_bit(&denom); // denom >>= 1; - } // return answer; -} - - -void bignum_lshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b->array[i] <<= nbits; - } -} - - -void bignum_rshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b->array[i] >>= nbits; - } - -} - - -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) -{ - /* - Take divmod and throw away div part - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - bignum_divmod(a,b,&tmp,c); -} - -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) -{ - /* - Puts a%b in d - and a/b in c - - mod(a,b) = a - ((a / b) * b) - - example: - mod(8, 3) = 8 - ((8 / 3) * 3) = 2 - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - /* c = (a / b) */ - bignum_div(a, b, c); - - /* tmp = (c * b) */ - bignum_mul(c, b, &tmp); - - /* c = a - tmp */ - bignum_sub(a, &tmp, d); -} - -void bignum_or(struct bn* a, struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - c->array[i] = (a->array[i] | b->array[i]); - } -} - -int bignum_cmp(const struct bn *a, const struct bn *b) -{ - require(a, "a is null"); - require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do - { - i -= 1; /* Decrement first, to start with last array element */ - if (a->array[i] > b->array[i]) - { - return LARGER; - } - else if (a->array[i] < b->array[i]) - { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -int bignum_is_zero(const struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - if (n->array[i]) - { - return 0; - } - } - - return 1; -} - -void bignum_assign(struct bn* dst, const struct bn* src) -{ - require(dst, "dst is null"); - require(src, "src is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - dst->array[i] = src->array[i]; - } -} - - -/* Private / Static functions. */ -static void _rshift_word(struct bn* a, int nwords) -{ - /* Naive method: */ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - if (nwords >= BN_ARRAY_SIZE) - { - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } - return; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) - { - a->array[i] = a->array[i + nwords]; - } - for (; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } -} - - -static void _lshift_word(struct bn* a, int nwords) -{ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) - { - a->array[i] = a->array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) - { - a->array[i] = 0; - } -} - - -static void _lshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a->array[0] <<= 1; -} - - -static void _rshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a->array[BN_ARRAY_SIZE - 1] >>= 1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/bn.c b/crypto_sign/perk-192-short-3/m4/bn.c new file mode 120000 index 00000000..f7757f12 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/bn.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/bn.h b/crypto_sign/perk-192-short-3/m4/bn.h deleted file mode 100644 index c0debe59..00000000 --- a/crypto_sign/perk-192-short-3/m4/bn.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && msg) - - -/* Data-holding structure: array of DTYPEs */ -struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -}; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - - - -/* Initialization functions: */ -void bignum_init(struct bn* n); -void bignum_from_int(struct bn* n, DTYPE_TMP i); -int bignum_to_int(struct bn* n); - -/* Basic arithmetic operations: */ -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - -/* Bitwise operations: */ -void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ -void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ -void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ - -/* Special operators and comparison */ -int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ -int bignum_is_zero(const struct bn* n); /* For comparison with zero */ -void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ - - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/crypto_sign/perk-192-short-3/m4/bn.h b/crypto_sign/perk-192-short-3/m4/bn.h new file mode 120000 index 00000000..644cc71b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/bn.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common.c b/crypto_sign/perk-192-short-3/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-192-short-3/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common.c b/crypto_sign/perk-192-short-3/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common.h b/crypto_sign/perk-192-short-3/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-192-short-3/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common.h b/crypto_sign/perk-192-short-3/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/common_s.c b/crypto_sign/perk-192-short-3/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-192-short-3/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-192-short-3/m4/common_s.c b/crypto_sign/perk-192-short-3/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.c b/crypto_sign/perk-192-short-3/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-192-short-3/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.c b/crypto_sign/perk-192-short-3/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.h b/crypto_sign/perk-192-short-3/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-192-short-3/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-short-3/m4/crypto_memset.h b/crypto_sign/perk-192-short-3/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/data_structures.h b/crypto_sign/perk-192-short-3/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-192-short-3/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/data_structures.h b/crypto_sign/perk-192-short-3/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.c b/crypto_sign/perk-192-short-3/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-192-short-3/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.c b/crypto_sign/perk-192-short-3/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.h b/crypto_sign/perk-192-short-3/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-192-short-3/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-192-short-3/m4/djbsort.h b/crypto_sign/perk-192-short-3/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/keygen.c b/crypto_sign/perk-192-short-3/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-192-short-3/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/keygen.c b/crypto_sign/perk-192-short-3/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/keygen.h b/crypto_sign/perk-192-short-3/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-192-short-3/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/keygen.h b/crypto_sign/perk-192-short-3/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing.c b/crypto_sign/perk-192-short-3/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-192-short-3/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing.c b/crypto_sign/perk-192-short-3/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing.h b/crypto_sign/perk-192-short-3/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-192-short-3/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing.h b/crypto_sign/perk-192-short-3/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.c b/crypto_sign/perk-192-short-3/m4/parsing_permutations.c deleted file mode 100644 index 6edb9a7e..00000000 --- a/crypto_sign/perk-192-short-3/m4/parsing_permutations.c +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "rank_unrank_table.h" -#include "symmetric.h" - -#define PARAM_RANK_UNRANK_LEN_T \ - ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ - -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { - struct bn mul, code, tmp; - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - bignum_init(&code); - for (int i = 0; i < PARAM_N1; ++i) { - uint8_t ctr = in_p[i]; - uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - if (node & 0x1) { - ctr -= T[(node >> 1) << 1]; - } - T[node] += 1; - node = node >> 1; - } - T[node] += 1; - bignum_from_int(&tmp, PARAM_N1 - i); - bignum_mul(&code, &tmp, &mul); - bignum_from_int(&tmp, ctr); - bignum_add(&mul, &tmp, &code); - } - - memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); - memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); -} - -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { - struct bn code, tmp, tmp2, tmp3; - bignum_init(&code); - - memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); - - // validate the permutation encoding to be < n! - if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { - return EXIT_FAILURE; - } - - bignum_mod(&code, &factorial[PARAM_N1], &tmp); - bignum_assign(&tmp3, &tmp); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); - out_p[0] = bignum_to_int(&tmp); - - for (int i = 1; i < PARAM_N1 - 1; ++i) { - bignum_assign(&tmp3, &tmp2); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); - out_p[i] = bignum_to_int(&tmp); - } - - bignum_div(&tmp2, &factorial[0], &tmp); - out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { - for (int j = 0; j < (1 << i); ++j) { - T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); - } - } - - for (int i = 0; i < PARAM_N1; ++i) { - int digit = out_p[i]; - uint16_t node = 1; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - T[node] -= 1; - node <<= 1; - if (digit >= T[node]) { - digit -= T[node]; - node += 1; - } - } - T[node] = 0; - out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); - } - - return EXIT_SUCCESS; -} - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < (PARAM_TAU); i++) { - sig_perk_perm_encode(signature->responses[i].z2_pi, sb); - sb += PARAM_PERM_COMPRESSION_BYTES; - } -} - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - sb += PARAM_PERM_COMPRESSION_BYTES; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.c b/crypto_sign/perk-192-short-3/m4/parsing_permutations.c new file mode 120000 index 00000000..4227070c --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.h b/crypto_sign/perk-192-short-3/m4/parsing_permutations.h deleted file mode 100644 index 52c64e70..00000000 --- a/crypto_sign/perk-192-short-3/m4/parsing_permutations.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Permutation rank encoding. Encode a permutation into a bytearray. - * - * @param in_p input permutation - * @param out_buff output buffer byte string - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); - -/** - * @brief Permutation unrank decoding. Decode a bytearray into a permutation. - * - * @param in_buff input buffer byte string - * @param out_p output permutation - * @return EXIT_SUCCESS or EXIT_FAILURE - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/parsing_permutations.h b/crypto_sign/perk-192-short-3/m4/parsing_permutations.h new file mode 120000 index 00000000..f78f116d --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.c b/crypto_sign/perk-192-short-3/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-192-short-3/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.c b/crypto_sign/perk-192-short-3/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.h b/crypto_sign/perk-192-short-3/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-192-short-3/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/permutation.h b/crypto_sign/perk-192-short-3/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h deleted file mode 100644 index c530d04f..00000000 --- a/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file rank_unrank_table.h - * @brief Look-up table used in rank/unrank compression. - * For the GMP version, the encoding is in base-62 - * For tiny-bignum, the setting is for 32 bit architectures - * - * Each i-th value is i! encoded in base-62. - * - */ - -#ifndef SIG_PKP_RANK_UNRANK_TABLE_H -#define SIG_PKP_RANK_UNRANK_TABLE_H - -#include "bn.h" - -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} - -}; - -#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h new file mode 120000 index 00000000..0466ec6b --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/rank_unrank_table.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./rank_unrank_table.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/sign.c b/crypto_sign/perk-192-short-3/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-192-short-3/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/sign.c b/crypto_sign/perk-192-short-3/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.c b/crypto_sign/perk-192-short-3/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-192-short-3/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.c b/crypto_sign/perk-192-short-3/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.h b/crypto_sign/perk-192-short-3/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-192-short-3/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/signature.h b/crypto_sign/perk-192-short-3/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/sort.c b/crypto_sign/perk-192-short-3/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-192-short-3/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-192-short-3/m4/sort.c b/crypto_sign/perk-192-short-3/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.c b/crypto_sign/perk-192-short-3/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-192-short-3/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.c b/crypto_sign/perk-192-short-3/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.h b/crypto_sign/perk-192-short-3/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-192-short-3/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/symmetric.h b/crypto_sign/perk-192-short-3/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.c b/crypto_sign/perk-192-short-3/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-192-short-3/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.c b/crypto_sign/perk-192-short-3/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.h b/crypto_sign/perk-192-short-3/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-192-short-3/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/theta_tree.h b/crypto_sign/perk-192-short-3/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.c b/crypto_sign/perk-192-short-3/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-192-short-3/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.c b/crypto_sign/perk-192-short-3/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.h b/crypto_sign/perk-192-short-3/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-192-short-3/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verbose.h b/crypto_sign/perk-192-short-3/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.c b/crypto_sign/perk-192-short-3/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-192-short-3/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.c b/crypto_sign/perk-192-short-3/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.h b/crypto_sign/perk-192-short-3/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-192-short-3/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-3/m4/verify.h b/crypto_sign/perk-192-short-3/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-192-short-3/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/README b/crypto_sign/perk-192-short-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-192-short-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-192-short-5/m4/README b/crypto_sign/perk-192-short-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/api.h b/crypto_sign/perk-192-short-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-192-short-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-192-short-5/m4/api.h b/crypto_sign/perk-192-short-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.c b/crypto_sign/perk-192-short-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-192-short-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.c b/crypto_sign/perk-192-short-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.h b/crypto_sign/perk-192-short-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-192-short-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/arithmetic.h b/crypto_sign/perk-192-short-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/bn.c b/crypto_sign/perk-192-short-5/m4/bn.c deleted file mode 100644 index b676feb3..00000000 --- a/crypto_sign/perk-192-short-5/m4/bn.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include -#include "bn.h" - - - -/* Functions for shifting number in-place. */ -static void _lshift_one_bit(struct bn* a); -static void _rshift_one_bit(struct bn* a); -static void _lshift_word(struct bn* a, int nwords); -static void _rshift_word(struct bn* a, int nwords); - - - -/* Public / Exported functions. */ -void bignum_init(struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - n->array[i] = 0; - } -} - - -void bignum_from_int(struct bn* n, DTYPE_TMP i) -{ - require(n, "n is null"); - - bignum_init(n); - - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE -#if (WORD_SIZE == 1) - n->array[0] = (i & 0x000000ff); - n->array[1] = (i & 0x0000ff00) >> 8; - n->array[2] = (i & 0x00ff0000) >> 16; - n->array[3] = (i & 0xff000000) >> 24; -#elif (WORD_SIZE == 2) - n->array[0] = (i & 0x0000ffff); - n->array[1] = (i & 0xffff0000) >> 16; -#elif (WORD_SIZE == 4) - n->array[0] = i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n->array[1] = tmp; -#endif -#endif -} - - -int bignum_to_int(struct bn* n) -{ - require(n, "n is null"); - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n->array[0]; - ret += n->array[1] << 8; - ret += n->array[2] << 16; - ret += n->array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n->array[0]; - ret += n->array[1] << 16; -#elif (WORD_SIZE == 4) - ret += (int)n->array[0]; -#endif - - return ret; -} - -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; - carry = (tmp > MAX_VAL); - c->array[i] = (tmp & MAX_VAL); - } -} - - -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b->array[i] + borrow; - res = (tmp1 - tmp2); - c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } -} - - -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - bignum_init(c); - - if (bignum_is_zero(a)) {return;} - if (bignum_is_zero(b)) {return;} - - struct bn tmp; - struct bn max_val; - bignum_from_int(&max_val, MAX_VAL); - - struct bn a1; - DTYPE_TMP a0; - struct bn b1; - DTYPE_TMP b0; - struct bn z0; - struct bn z1; - struct bn z2; - - bignum_rshift(a, &a1, WORD_SIZE*8); - bignum_rshift(b, &b1, WORD_SIZE*8); - a0 = (DTYPE_TMP)(a->array[0]); - b0 = (DTYPE_TMP)(b->array[0]); - DTYPE_TMP z0_small = a0*b0; - - bignum_init(&z0); - z0.array[0] = z0_small & MAX_VAL; - z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); - if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { - bignum_assign(c, &z0); - return; - } - bignum_mul(&a1, &b1, &z2); - struct bn a0_big; - struct bn b0_big; - bignum_from_int(&a0_big, a0); - bignum_from_int(&b0_big, b0); - - struct bn tmpa; - struct bn tmpb; - struct bn tmpz1; - bignum_add(&a1, &a0_big, &tmpa); - bignum_add(&b1, &b0_big, &tmpb); - bignum_mul(&tmpa, &tmpb, &tmpz1); - bignum_sub(&tmpz1, &z2, &tmpa); - bignum_sub(&tmpa, &z0, &z1); - - bignum_lshift(&z2, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z1, c); - bignum_lshift(c, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z0, c); -} - - -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn current; - struct bn denom; - struct bn tmp; - - bignum_from_int(¤t, 1); // int current = 1; - bignum_assign(&denom, b); // denom = b - bignum_assign(&tmp, a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { - { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) - { - overflow = true; - break; - } - _lshift_one_bit(¤t); // current <<= 1; - _lshift_one_bit(&denom); // denom <<= 1; - } - if (!overflow) - { - _rshift_one_bit(&denom); // denom >>= 1; - _rshift_one_bit(¤t); // current >>= 1; - } - bignum_init(c); // int answer = 0; - - while (!bignum_is_zero(¤t)) // while (current != 0) - { - if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) - { - bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; - bignum_or(c, ¤t, c); // answer |= current; - } - _rshift_one_bit(¤t); // current >>= 1; - _rshift_one_bit(&denom); // denom >>= 1; - } // return answer; -} - - -void bignum_lshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b->array[i] <<= nbits; - } -} - - -void bignum_rshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b->array[i] >>= nbits; - } - -} - - -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) -{ - /* - Take divmod and throw away div part - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - bignum_divmod(a,b,&tmp,c); -} - -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) -{ - /* - Puts a%b in d - and a/b in c - - mod(a,b) = a - ((a / b) * b) - - example: - mod(8, 3) = 8 - ((8 / 3) * 3) = 2 - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - /* c = (a / b) */ - bignum_div(a, b, c); - - /* tmp = (c * b) */ - bignum_mul(c, b, &tmp); - - /* c = a - tmp */ - bignum_sub(a, &tmp, d); -} - -void bignum_or(struct bn* a, struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - c->array[i] = (a->array[i] | b->array[i]); - } -} - -int bignum_cmp(const struct bn *a, const struct bn *b) -{ - require(a, "a is null"); - require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do - { - i -= 1; /* Decrement first, to start with last array element */ - if (a->array[i] > b->array[i]) - { - return LARGER; - } - else if (a->array[i] < b->array[i]) - { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -int bignum_is_zero(const struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - if (n->array[i]) - { - return 0; - } - } - - return 1; -} - -void bignum_assign(struct bn* dst, const struct bn* src) -{ - require(dst, "dst is null"); - require(src, "src is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - dst->array[i] = src->array[i]; - } -} - - -/* Private / Static functions. */ -static void _rshift_word(struct bn* a, int nwords) -{ - /* Naive method: */ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - if (nwords >= BN_ARRAY_SIZE) - { - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } - return; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) - { - a->array[i] = a->array[i + nwords]; - } - for (; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } -} - - -static void _lshift_word(struct bn* a, int nwords) -{ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) - { - a->array[i] = a->array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) - { - a->array[i] = 0; - } -} - - -static void _lshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a->array[0] <<= 1; -} - - -static void _rshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a->array[BN_ARRAY_SIZE - 1] >>= 1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/bn.c b/crypto_sign/perk-192-short-5/m4/bn.c new file mode 120000 index 00000000..f7757f12 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/bn.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/bn.h b/crypto_sign/perk-192-short-5/m4/bn.h deleted file mode 100644 index c0debe59..00000000 --- a/crypto_sign/perk-192-short-5/m4/bn.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && msg) - - -/* Data-holding structure: array of DTYPEs */ -struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -}; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - - - -/* Initialization functions: */ -void bignum_init(struct bn* n); -void bignum_from_int(struct bn* n, DTYPE_TMP i); -int bignum_to_int(struct bn* n); - -/* Basic arithmetic operations: */ -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - -/* Bitwise operations: */ -void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ -void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ -void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ - -/* Special operators and comparison */ -int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ -int bignum_is_zero(const struct bn* n); /* For comparison with zero */ -void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ - - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/crypto_sign/perk-192-short-5/m4/bn.h b/crypto_sign/perk-192-short-5/m4/bn.h new file mode 120000 index 00000000..644cc71b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/bn.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common.c b/crypto_sign/perk-192-short-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-192-short-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common.c b/crypto_sign/perk-192-short-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common.h b/crypto_sign/perk-192-short-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-192-short-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common.h b/crypto_sign/perk-192-short-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/common_s.c b/crypto_sign/perk-192-short-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-192-short-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-192-short-5/m4/common_s.c b/crypto_sign/perk-192-short-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.c b/crypto_sign/perk-192-short-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-192-short-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.c b/crypto_sign/perk-192-short-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.h b/crypto_sign/perk-192-short-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-192-short-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-192-short-5/m4/crypto_memset.h b/crypto_sign/perk-192-short-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/data_structures.h b/crypto_sign/perk-192-short-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-192-short-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/data_structures.h b/crypto_sign/perk-192-short-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.c b/crypto_sign/perk-192-short-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-192-short-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.c b/crypto_sign/perk-192-short-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.h b/crypto_sign/perk-192-short-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-192-short-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-192-short-5/m4/djbsort.h b/crypto_sign/perk-192-short-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/keygen.c b/crypto_sign/perk-192-short-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-192-short-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/keygen.c b/crypto_sign/perk-192-short-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/keygen.h b/crypto_sign/perk-192-short-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-192-short-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/keygen.h b/crypto_sign/perk-192-short-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing.c b/crypto_sign/perk-192-short-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-192-short-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing.c b/crypto_sign/perk-192-short-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing.h b/crypto_sign/perk-192-short-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-192-short-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing.h b/crypto_sign/perk-192-short-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.c b/crypto_sign/perk-192-short-5/m4/parsing_permutations.c deleted file mode 100644 index 6edb9a7e..00000000 --- a/crypto_sign/perk-192-short-5/m4/parsing_permutations.c +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "rank_unrank_table.h" -#include "symmetric.h" - -#define PARAM_RANK_UNRANK_LEN_T \ - ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ - -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { - struct bn mul, code, tmp; - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - bignum_init(&code); - for (int i = 0; i < PARAM_N1; ++i) { - uint8_t ctr = in_p[i]; - uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - if (node & 0x1) { - ctr -= T[(node >> 1) << 1]; - } - T[node] += 1; - node = node >> 1; - } - T[node] += 1; - bignum_from_int(&tmp, PARAM_N1 - i); - bignum_mul(&code, &tmp, &mul); - bignum_from_int(&tmp, ctr); - bignum_add(&mul, &tmp, &code); - } - - memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); - memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); -} - -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { - struct bn code, tmp, tmp2, tmp3; - bignum_init(&code); - - memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); - - // validate the permutation encoding to be < n! - if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { - return EXIT_FAILURE; - } - - bignum_mod(&code, &factorial[PARAM_N1], &tmp); - bignum_assign(&tmp3, &tmp); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); - out_p[0] = bignum_to_int(&tmp); - - for (int i = 1; i < PARAM_N1 - 1; ++i) { - bignum_assign(&tmp3, &tmp2); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); - out_p[i] = bignum_to_int(&tmp); - } - - bignum_div(&tmp2, &factorial[0], &tmp); - out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { - for (int j = 0; j < (1 << i); ++j) { - T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); - } - } - - for (int i = 0; i < PARAM_N1; ++i) { - int digit = out_p[i]; - uint16_t node = 1; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - T[node] -= 1; - node <<= 1; - if (digit >= T[node]) { - digit -= T[node]; - node += 1; - } - } - T[node] = 0; - out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); - } - - return EXIT_SUCCESS; -} - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < (PARAM_TAU); i++) { - sig_perk_perm_encode(signature->responses[i].z2_pi, sb); - sb += PARAM_PERM_COMPRESSION_BYTES; - } -} - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - sb += PARAM_PERM_COMPRESSION_BYTES; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.c b/crypto_sign/perk-192-short-5/m4/parsing_permutations.c new file mode 120000 index 00000000..4227070c --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.h b/crypto_sign/perk-192-short-5/m4/parsing_permutations.h deleted file mode 100644 index 52c64e70..00000000 --- a/crypto_sign/perk-192-short-5/m4/parsing_permutations.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Permutation rank encoding. Encode a permutation into a bytearray. - * - * @param in_p input permutation - * @param out_buff output buffer byte string - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); - -/** - * @brief Permutation unrank decoding. Decode a bytearray into a permutation. - * - * @param in_buff input buffer byte string - * @param out_p output permutation - * @return EXIT_SUCCESS or EXIT_FAILURE - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/parsing_permutations.h b/crypto_sign/perk-192-short-5/m4/parsing_permutations.h new file mode 120000 index 00000000..f78f116d --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.c b/crypto_sign/perk-192-short-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-192-short-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.c b/crypto_sign/perk-192-short-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.h b/crypto_sign/perk-192-short-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-192-short-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/permutation.h b/crypto_sign/perk-192-short-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h deleted file mode 100644 index c530d04f..00000000 --- a/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file rank_unrank_table.h - * @brief Look-up table used in rank/unrank compression. - * For the GMP version, the encoding is in base-62 - * For tiny-bignum, the setting is for 32 bit architectures - * - * Each i-th value is i! encoded in base-62. - * - */ - -#ifndef SIG_PKP_RANK_UNRANK_TABLE_H -#define SIG_PKP_RANK_UNRANK_TABLE_H - -#include "bn.h" - -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} - -}; - -#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h new file mode 120000 index 00000000..0466ec6b --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/rank_unrank_table.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./rank_unrank_table.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/sign.c b/crypto_sign/perk-192-short-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-192-short-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/sign.c b/crypto_sign/perk-192-short-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.c b/crypto_sign/perk-192-short-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-192-short-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.c b/crypto_sign/perk-192-short-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.h b/crypto_sign/perk-192-short-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-192-short-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/signature.h b/crypto_sign/perk-192-short-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/sort.c b/crypto_sign/perk-192-short-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-192-short-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-192-short-5/m4/sort.c b/crypto_sign/perk-192-short-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.c b/crypto_sign/perk-192-short-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-192-short-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.c b/crypto_sign/perk-192-short-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.h b/crypto_sign/perk-192-short-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-192-short-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/symmetric.h b/crypto_sign/perk-192-short-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.c b/crypto_sign/perk-192-short-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-192-short-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.c b/crypto_sign/perk-192-short-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.h b/crypto_sign/perk-192-short-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-192-short-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/theta_tree.h b/crypto_sign/perk-192-short-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.c b/crypto_sign/perk-192-short-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-192-short-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.c b/crypto_sign/perk-192-short-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.h b/crypto_sign/perk-192-short-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-192-short-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verbose.h b/crypto_sign/perk-192-short-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.c b/crypto_sign/perk-192-short-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-192-short-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.c b/crypto_sign/perk-192-short-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.h b/crypto_sign/perk-192-short-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-192-short-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-192-short-5/m4/verify.h b/crypto_sign/perk-192-short-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-192-short-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/README b/crypto_sign/perk-256-fast-3/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-256-fast-3/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-256-fast-3/m4/README b/crypto_sign/perk-256-fast-3/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/api.h b/crypto_sign/perk-256-fast-3/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-256-fast-3/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-256-fast-3/m4/api.h b/crypto_sign/perk-256-fast-3/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.c b/crypto_sign/perk-256-fast-3/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-256-fast-3/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.c b/crypto_sign/perk-256-fast-3/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.h b/crypto_sign/perk-256-fast-3/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-256-fast-3/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/arithmetic.h b/crypto_sign/perk-256-fast-3/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.c b/crypto_sign/perk-256-fast-3/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-256-fast-3/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.c b/crypto_sign/perk-256-fast-3/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.h b/crypto_sign/perk-256-fast-3/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-256-fast-3/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common.h b/crypto_sign/perk-256-fast-3/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/common_s.c b/crypto_sign/perk-256-fast-3/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-256-fast-3/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-256-fast-3/m4/common_s.c b/crypto_sign/perk-256-fast-3/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.c b/crypto_sign/perk-256-fast-3/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-256-fast-3/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.c b/crypto_sign/perk-256-fast-3/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.h b/crypto_sign/perk-256-fast-3/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-256-fast-3/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-fast-3/m4/crypto_memset.h b/crypto_sign/perk-256-fast-3/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/data_structures.h b/crypto_sign/perk-256-fast-3/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-256-fast-3/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/data_structures.h b/crypto_sign/perk-256-fast-3/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.c b/crypto_sign/perk-256-fast-3/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-256-fast-3/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.c b/crypto_sign/perk-256-fast-3/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.h b/crypto_sign/perk-256-fast-3/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-256-fast-3/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-256-fast-3/m4/djbsort.h b/crypto_sign/perk-256-fast-3/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.c b/crypto_sign/perk-256-fast-3/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-256-fast-3/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.c b/crypto_sign/perk-256-fast-3/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.h b/crypto_sign/perk-256-fast-3/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-256-fast-3/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/keygen.h b/crypto_sign/perk-256-fast-3/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.c b/crypto_sign/perk-256-fast-3/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-256-fast-3/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.c b/crypto_sign/perk-256-fast-3/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.h b/crypto_sign/perk-256-fast-3/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-256-fast-3/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing.h b/crypto_sign/perk-256-fast-3/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c deleted file mode 100644 index 39acbcf6..00000000 --- a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c +++ /dev/null @@ -1,425 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -// bits needed to store two permutation coefficients -#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) -#define PARAM_N1_BITSx2 13 -#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) -#define PARAM_N1_BITSx2 14 -#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) -#define PARAM_N1_BITSx2 15 -#else -#error PARAM_N1 bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 14) -/** - * @brief store a 7 bit value in a byte array at bit position i*7 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 7 bit value to store - */ -static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7F; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 7: - sb[k + 0] |= val << 1; - break; - } -} - -/** - * @brief load a 7 bit value from a byte array at bit position i*7 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint8_t loaded value - */ -static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { - uint8_t val = 0; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - val = (sb[k + 0] & 0x7F); - break; - case 1: - val = sb[k + 0] >> 7; - val |= (sb[k + 1] & 0x3F) << 1; - break; - case 2: - val = sb[k + 0] >> 6; - val |= (sb[k + 1] & 0x1F) << 2; - break; - case 3: - val = sb[k + 0] >> 5; - val |= (sb[k + 1] & 0x0F) << 3; - break; - case 4: - val = sb[k + 0] >> 4; - val |= (sb[k + 1] & 0x07) << 4; - break; - case 5: - val = sb[k + 0] >> 3; - val |= (sb[k + 1] & 0x03) << 5; - break; - case 6: - val = sb[k + 0] >> 2; - val |= (sb[k + 1] & 0x01) << 6; - break; - case 7: - val = sb[k + 0] >> 1; - break; - default: - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 13) -/** - * @brief store a 13 bit value in a byte array at bit position i*13 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 13 bit value to store - */ -static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x1FFF; - int k = (i * 13) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 2: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 3: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - case 6: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 7: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - } -} - -/** - * @brief load a 13 bit value from a byte array at bit position i*13 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 13) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; - break; - case 1: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x03) << 11; - break; - case 2: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; - break; - case 3: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x01) << 12; - break; - case 5: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; - break; - case 6: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x07) << 10; - break; - case 7: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 15) -/** - * @brief store a 15 bit value in a byte array at bit position i*15 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 15 bit value to store - */ -static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7FFF; - int k = (i * 15) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - sb[k + 2] = val >> 13; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - sb[k + 2] = val >> 14; - break; - case 7: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - } -} - -/** - * @brief load a 15 bit value from a byte array at bit position i*15 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 15) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; - break; - case 1: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; - break; - case 2: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; - break; - case 3: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x07) << 12; - break; - case 5: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - val |= ((uint16_t)sb[k + 2] & 0x03) << 13; - break; - case 6: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; - val |= ((uint16_t)sb[k + 2] & 0x01) << 14; - break; - case 7: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; - break; - } - - return val; -} -#endif - -#if (PARAM_Q_BITS != 10) -#error PARAM_Q bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 13) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_13bit_from_bytearray(sb, i); - *c0 = val % 90; - *c1 = val / 90; -} -#elif (PARAM_N1_BITSx2 == 14) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_7bit_in_bytearray(sb, i * 2 + 0, c0); - store_7bit_in_bytearray(sb, i * 2 + 1, c1); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); - *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); -} -#elif (PARAM_N1_BITSx2 == 15) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_15bit_from_bytearray(sb, i); - *c0 = val % 181; - *c1 = val / 181; -} -#else -#error PARAM_N1 bit size not supported -#endif - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; - uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; - store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); - } -} - -/** - * @brief check the permutations to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param responses perk_response_t array of size PARAM_TAU to be checked - * @return int != 0 if a not valid permutation is found - */ -static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { - return 1; - } - } - return 0; -} - -#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) -static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0; - uint16_t z2_pi1; - - load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); - signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; - signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z2_p1_unused_mask) { - // unused bits after the z2_pi != 0 - return EXIT_FAILURE; - } - - if (permutations_not_valid(signature->responses)) { - // loaded permutations are not valid - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c new file mode 120000 index 00000000..3787fa0e --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h deleted file mode 100644 index b622b736..00000000 --- a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h +++ /dev/null @@ -1,53 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -/** - * @brief check the permutation to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param p input permutation to be checked - * @return int - */ -static inline int sig_perk_permutation_not_valid(const perm_t p) { - uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; - - for (unsigned i = 0; i < sizeof(c); i++) { - if (p[i] >= sizeof(c)) - return 1; - if (c[p[i]]) - return 1; - c[p[i]] = 1; - } - return 0; -} - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h new file mode 120000 index 00000000..7deb60e5 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.c b/crypto_sign/perk-256-fast-3/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-256-fast-3/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.c b/crypto_sign/perk-256-fast-3/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.h b/crypto_sign/perk-256-fast-3/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-256-fast-3/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/permutation.h b/crypto_sign/perk-256-fast-3/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/sign.c b/crypto_sign/perk-256-fast-3/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-256-fast-3/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/sign.c b/crypto_sign/perk-256-fast-3/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.c b/crypto_sign/perk-256-fast-3/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-256-fast-3/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.c b/crypto_sign/perk-256-fast-3/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.h b/crypto_sign/perk-256-fast-3/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-256-fast-3/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/signature.h b/crypto_sign/perk-256-fast-3/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/sort.c b/crypto_sign/perk-256-fast-3/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-256-fast-3/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-256-fast-3/m4/sort.c b/crypto_sign/perk-256-fast-3/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.c b/crypto_sign/perk-256-fast-3/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-256-fast-3/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.c b/crypto_sign/perk-256-fast-3/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.h b/crypto_sign/perk-256-fast-3/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-256-fast-3/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/symmetric.h b/crypto_sign/perk-256-fast-3/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.c b/crypto_sign/perk-256-fast-3/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-256-fast-3/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.c b/crypto_sign/perk-256-fast-3/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.h b/crypto_sign/perk-256-fast-3/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-256-fast-3/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/theta_tree.h b/crypto_sign/perk-256-fast-3/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.c b/crypto_sign/perk-256-fast-3/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-256-fast-3/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.c b/crypto_sign/perk-256-fast-3/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.h b/crypto_sign/perk-256-fast-3/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-256-fast-3/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verbose.h b/crypto_sign/perk-256-fast-3/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.c b/crypto_sign/perk-256-fast-3/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-256-fast-3/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.c b/crypto_sign/perk-256-fast-3/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.h b/crypto_sign/perk-256-fast-3/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-256-fast-3/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-3/m4/verify.h b/crypto_sign/perk-256-fast-3/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-256-fast-3/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/README b/crypto_sign/perk-256-fast-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-256-fast-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-256-fast-5/m4/README b/crypto_sign/perk-256-fast-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/api.h b/crypto_sign/perk-256-fast-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-256-fast-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-256-fast-5/m4/api.h b/crypto_sign/perk-256-fast-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.c b/crypto_sign/perk-256-fast-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-256-fast-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.c b/crypto_sign/perk-256-fast-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.h b/crypto_sign/perk-256-fast-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-256-fast-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/arithmetic.h b/crypto_sign/perk-256-fast-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.c b/crypto_sign/perk-256-fast-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-256-fast-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.c b/crypto_sign/perk-256-fast-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.h b/crypto_sign/perk-256-fast-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-256-fast-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common.h b/crypto_sign/perk-256-fast-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/common_s.c b/crypto_sign/perk-256-fast-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-256-fast-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-256-fast-5/m4/common_s.c b/crypto_sign/perk-256-fast-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.c b/crypto_sign/perk-256-fast-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-256-fast-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.c b/crypto_sign/perk-256-fast-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.h b/crypto_sign/perk-256-fast-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-256-fast-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-fast-5/m4/crypto_memset.h b/crypto_sign/perk-256-fast-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/data_structures.h b/crypto_sign/perk-256-fast-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-256-fast-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/data_structures.h b/crypto_sign/perk-256-fast-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.c b/crypto_sign/perk-256-fast-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-256-fast-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.c b/crypto_sign/perk-256-fast-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.h b/crypto_sign/perk-256-fast-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-256-fast-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-256-fast-5/m4/djbsort.h b/crypto_sign/perk-256-fast-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.c b/crypto_sign/perk-256-fast-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-256-fast-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.c b/crypto_sign/perk-256-fast-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.h b/crypto_sign/perk-256-fast-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-256-fast-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/keygen.h b/crypto_sign/perk-256-fast-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.c b/crypto_sign/perk-256-fast-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-256-fast-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.c b/crypto_sign/perk-256-fast-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.h b/crypto_sign/perk-256-fast-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-256-fast-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing.h b/crypto_sign/perk-256-fast-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c deleted file mode 100644 index 39acbcf6..00000000 --- a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c +++ /dev/null @@ -1,425 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -// bits needed to store two permutation coefficients -#if (PARAM_N1 > 64) && (PARAM_N1 <= 90) -#define PARAM_N1_BITSx2 13 -#elif (PARAM_N1 > 90) && (PARAM_N1 <= 128) -#define PARAM_N1_BITSx2 14 -#elif (PARAM_N1 > 128) && (PARAM_N1 <= 181) -#define PARAM_N1_BITSx2 15 -#else -#error PARAM_N1 bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 14) -/** - * @brief store a 7 bit value in a byte array at bit position i*7 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 7 bit value to store - */ -static inline void store_7bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7F; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 7: - sb[k + 0] |= val << 1; - break; - } -} - -/** - * @brief load a 7 bit value from a byte array at bit position i*7 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint8_t loaded value - */ -static inline uint8_t load_7bit_from_bytearray(const uint8_t* sb, int i) { - uint8_t val = 0; - int k = (i * 7) / 8; - switch (i % 8) { - case 0: - val = (sb[k + 0] & 0x7F); - break; - case 1: - val = sb[k + 0] >> 7; - val |= (sb[k + 1] & 0x3F) << 1; - break; - case 2: - val = sb[k + 0] >> 6; - val |= (sb[k + 1] & 0x1F) << 2; - break; - case 3: - val = sb[k + 0] >> 5; - val |= (sb[k + 1] & 0x0F) << 3; - break; - case 4: - val = sb[k + 0] >> 4; - val |= (sb[k + 1] & 0x07) << 4; - break; - case 5: - val = sb[k + 0] >> 3; - val |= (sb[k + 1] & 0x03) << 5; - break; - case 6: - val = sb[k + 0] >> 2; - val |= (sb[k + 1] & 0x01) << 6; - break; - case 7: - val = sb[k + 0] >> 1; - break; - default: - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 13) -/** - * @brief store a 13 bit value in a byte array at bit position i*13 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 13 bit value to store - */ -static inline void store_13bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x1FFF; - int k = (i * 13) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 2: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - break; - case 3: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - case 6: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 7: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - break; - } -} - -/** - * @brief load a 13 bit value from a byte array at bit position i*13 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_13bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 13) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x1F) << 8; - break; - case 1: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x03) << 11; - break; - case 2: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 6; - break; - case 3: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 9; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x01) << 12; - break; - case 5: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0x3F) << 7; - break; - case 6: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x07) << 10; - break; - case 7: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - break; - } - - return val; -} -#endif - -#if (PARAM_N1_BITSx2 == 15) -/** - * @brief store a 15 bit value in a byte array at bit position i*15 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 15 bit value to store - */ -static inline void store_15bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x7FFF; - int k = (i * 15) / 8; - switch (i % 8) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 0] |= val << 7; - sb[k + 1] = val >> 1; - sb[k + 2] = val >> 9; - break; - case 2: - sb[k + 0] |= val << 6; - sb[k + 1] = val >> 2; - sb[k + 2] = val >> 10; - break; - case 3: - sb[k + 0] |= val << 5; - sb[k + 1] = val >> 3; - sb[k + 2] = val >> 11; - break; - case 4: - sb[k + 0] |= val << 4; - sb[k + 1] = val >> 4; - sb[k + 2] = val >> 12; - break; - case 5: - sb[k + 0] |= val << 3; - sb[k + 1] = val >> 5; - sb[k + 2] = val >> 13; - break; - case 6: - sb[k + 0] |= val << 2; - sb[k + 1] = val >> 6; - sb[k + 2] = val >> 14; - break; - case 7: - sb[k + 0] |= val << 1; - sb[k + 1] = val >> 7; - break; - } -} - -/** - * @brief load a 15 bit value from a byte array at bit position i*15 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_15bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i * 15) / 8; - uint16_t val = 0; - switch (i % 8) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x7F) << 8; - break; - case 1: - val = sb[k + 0] >> 7; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 1; - val |= ((uint16_t)sb[k + 2] & 0x3F) << 9; - break; - case 2: - val = sb[k + 0] >> 6; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 2; - val |= ((uint16_t)sb[k + 2] & 0x1F) << 10; - break; - case 3: - val = sb[k + 0] >> 5; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 3; - val |= ((uint16_t)sb[k + 2] & 0x0F) << 11; - break; - case 4: - val = sb[k + 0] >> 4; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 4; - val |= ((uint16_t)sb[k + 2] & 0x07) << 12; - break; - case 5: - val = sb[k + 0] >> 3; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 5; - val |= ((uint16_t)sb[k + 2] & 0x03) << 13; - break; - case 6: - val = sb[k + 0] >> 2; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 6; - val |= ((uint16_t)sb[k + 2] & 0x01) << 14; - break; - case 7: - val = sb[k + 0] >> 1; - val |= ((uint16_t)sb[k + 1] & 0xFF) << 7; - break; - } - - return val; -} -#endif - -#if (PARAM_Q_BITS != 10) -#error PARAM_Q bit size not supported -#endif - -#if (PARAM_N1_BITSx2 == 13) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_13bit_in_bytearray(sb, i, (c1 * 90) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_13bit_from_bytearray(sb, i); - *c0 = val % 90; - *c1 = val / 90; -} -#elif (PARAM_N1_BITSx2 == 14) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_7bit_in_bytearray(sb, i * 2 + 0, c0); - store_7bit_in_bytearray(sb, i * 2 + 1, c1); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - *c0 = load_7bit_from_bytearray(sb, i * 2 + 0); - *c1 = load_7bit_from_bytearray(sb, i * 2 + 1); -} -#elif (PARAM_N1_BITSx2 == 15) -static void store_2_perm_coeff_to_bytearray(uint8_t* sb, int i, uint16_t c0, uint16_t c1) { - store_15bit_in_bytearray(sb, i, (c1 * 181) + c0); -} - -static void load_2_perm_coeff_from_bytearray(uint16_t* c0, uint16_t* c1, const uint8_t* sb, int i) { - uint16_t val = load_15bit_from_bytearray(sb, i); - *c0 = val % 181; - *c1 = val / 181; -} -#else -#error PARAM_N1 bit size not supported -#endif - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0 = signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1]; - uint16_t z2_pi1 = signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1]; - store_2_perm_coeff_to_bytearray(sb, i, z2_pi0, z2_pi1); - } -} - -/** - * @brief check the permutations to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param responses perk_response_t array of size PARAM_TAU to be checked - * @return int != 0 if a not valid permutation is found - */ -static int permutations_not_valid(const perk_response_t responses[PARAM_TAU]) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_permutation_not_valid(responses[i].z2_pi)) { - return 1; - } - } - return 0; -} - -#define Z2_PI_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) % 8 + 1) -static const uint8_t z2_p1_unused_mask = (uint8_t)(((1U << (Z2_PI_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < ((PARAM_TAU * PARAM_N1) / 2); i++) { - uint16_t z2_pi0; - uint16_t z2_pi1; - - load_2_perm_coeff_from_bytearray(&z2_pi0, &z2_pi1, sb, i); - signature->responses[(i * 2 + 0) / PARAM_N1].z2_pi[(i * 2 + 0) % PARAM_N1] = z2_pi0; - signature->responses[(i * 2 + 1) / PARAM_N1].z2_pi[(i * 2 + 1) % PARAM_N1] = z2_pi1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_N1_BITSx2 / 2 + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z2_p1_unused_mask) { - // unused bits after the z2_pi != 0 - return EXIT_FAILURE; - } - - if (permutations_not_valid(signature->responses)) { - // loaded permutations are not valid - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c new file mode 120000 index 00000000..3787fa0e --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h deleted file mode 100644 index b622b736..00000000 --- a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h +++ /dev/null @@ -1,53 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -/** - * @brief check the permutation to be valid: - * - coefficients < PARAM_N1 - * - no coefficient duplicates - * - * @param p input permutation to be checked - * @return int - */ -static inline int sig_perk_permutation_not_valid(const perm_t p) { - uint8_t c[sizeof(perm_t) / sizeof(**((perm_t*)0))] = {0}; - - for (unsigned i = 0; i < sizeof(c); i++) { - if (p[i] >= sizeof(c)) - return 1; - if (c[p[i]]) - return 1; - c[p[i]] = 1; - } - return 0; -} - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h new file mode 120000 index 00000000..7deb60e5 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.c b/crypto_sign/perk-256-fast-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-256-fast-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.c b/crypto_sign/perk-256-fast-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.h b/crypto_sign/perk-256-fast-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-256-fast-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/permutation.h b/crypto_sign/perk-256-fast-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/sign.c b/crypto_sign/perk-256-fast-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-256-fast-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/sign.c b/crypto_sign/perk-256-fast-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.c b/crypto_sign/perk-256-fast-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-256-fast-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.c b/crypto_sign/perk-256-fast-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.h b/crypto_sign/perk-256-fast-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-256-fast-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/signature.h b/crypto_sign/perk-256-fast-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/sort.c b/crypto_sign/perk-256-fast-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-256-fast-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-256-fast-5/m4/sort.c b/crypto_sign/perk-256-fast-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.c b/crypto_sign/perk-256-fast-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-256-fast-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.c b/crypto_sign/perk-256-fast-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.h b/crypto_sign/perk-256-fast-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-256-fast-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/symmetric.h b/crypto_sign/perk-256-fast-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.c b/crypto_sign/perk-256-fast-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-256-fast-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.c b/crypto_sign/perk-256-fast-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.h b/crypto_sign/perk-256-fast-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-256-fast-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/theta_tree.h b/crypto_sign/perk-256-fast-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.c b/crypto_sign/perk-256-fast-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-256-fast-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.c b/crypto_sign/perk-256-fast-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.h b/crypto_sign/perk-256-fast-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-256-fast-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verbose.h b/crypto_sign/perk-256-fast-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.c b/crypto_sign/perk-256-fast-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-256-fast-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.c b/crypto_sign/perk-256-fast-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.h b/crypto_sign/perk-256-fast-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-256-fast-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-fast-5/m4/verify.h b/crypto_sign/perk-256-fast-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-256-fast-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/README b/crypto_sign/perk-256-short-3/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-256-short-3/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-256-short-3/m4/README b/crypto_sign/perk-256-short-3/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/api.h b/crypto_sign/perk-256-short-3/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-256-short-3/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-256-short-3/m4/api.h b/crypto_sign/perk-256-short-3/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.c b/crypto_sign/perk-256-short-3/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-256-short-3/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.c b/crypto_sign/perk-256-short-3/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.h b/crypto_sign/perk-256-short-3/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-256-short-3/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/arithmetic.h b/crypto_sign/perk-256-short-3/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/bn.c b/crypto_sign/perk-256-short-3/m4/bn.c deleted file mode 100644 index b676feb3..00000000 --- a/crypto_sign/perk-256-short-3/m4/bn.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include -#include "bn.h" - - - -/* Functions for shifting number in-place. */ -static void _lshift_one_bit(struct bn* a); -static void _rshift_one_bit(struct bn* a); -static void _lshift_word(struct bn* a, int nwords); -static void _rshift_word(struct bn* a, int nwords); - - - -/* Public / Exported functions. */ -void bignum_init(struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - n->array[i] = 0; - } -} - - -void bignum_from_int(struct bn* n, DTYPE_TMP i) -{ - require(n, "n is null"); - - bignum_init(n); - - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE -#if (WORD_SIZE == 1) - n->array[0] = (i & 0x000000ff); - n->array[1] = (i & 0x0000ff00) >> 8; - n->array[2] = (i & 0x00ff0000) >> 16; - n->array[3] = (i & 0xff000000) >> 24; -#elif (WORD_SIZE == 2) - n->array[0] = (i & 0x0000ffff); - n->array[1] = (i & 0xffff0000) >> 16; -#elif (WORD_SIZE == 4) - n->array[0] = i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n->array[1] = tmp; -#endif -#endif -} - - -int bignum_to_int(struct bn* n) -{ - require(n, "n is null"); - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n->array[0]; - ret += n->array[1] << 8; - ret += n->array[2] << 16; - ret += n->array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n->array[0]; - ret += n->array[1] << 16; -#elif (WORD_SIZE == 4) - ret += (int)n->array[0]; -#endif - - return ret; -} - -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; - carry = (tmp > MAX_VAL); - c->array[i] = (tmp & MAX_VAL); - } -} - - -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b->array[i] + borrow; - res = (tmp1 - tmp2); - c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } -} - - -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - bignum_init(c); - - if (bignum_is_zero(a)) {return;} - if (bignum_is_zero(b)) {return;} - - struct bn tmp; - struct bn max_val; - bignum_from_int(&max_val, MAX_VAL); - - struct bn a1; - DTYPE_TMP a0; - struct bn b1; - DTYPE_TMP b0; - struct bn z0; - struct bn z1; - struct bn z2; - - bignum_rshift(a, &a1, WORD_SIZE*8); - bignum_rshift(b, &b1, WORD_SIZE*8); - a0 = (DTYPE_TMP)(a->array[0]); - b0 = (DTYPE_TMP)(b->array[0]); - DTYPE_TMP z0_small = a0*b0; - - bignum_init(&z0); - z0.array[0] = z0_small & MAX_VAL; - z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); - if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { - bignum_assign(c, &z0); - return; - } - bignum_mul(&a1, &b1, &z2); - struct bn a0_big; - struct bn b0_big; - bignum_from_int(&a0_big, a0); - bignum_from_int(&b0_big, b0); - - struct bn tmpa; - struct bn tmpb; - struct bn tmpz1; - bignum_add(&a1, &a0_big, &tmpa); - bignum_add(&b1, &b0_big, &tmpb); - bignum_mul(&tmpa, &tmpb, &tmpz1); - bignum_sub(&tmpz1, &z2, &tmpa); - bignum_sub(&tmpa, &z0, &z1); - - bignum_lshift(&z2, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z1, c); - bignum_lshift(c, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z0, c); -} - - -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn current; - struct bn denom; - struct bn tmp; - - bignum_from_int(¤t, 1); // int current = 1; - bignum_assign(&denom, b); // denom = b - bignum_assign(&tmp, a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { - { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) - { - overflow = true; - break; - } - _lshift_one_bit(¤t); // current <<= 1; - _lshift_one_bit(&denom); // denom <<= 1; - } - if (!overflow) - { - _rshift_one_bit(&denom); // denom >>= 1; - _rshift_one_bit(¤t); // current >>= 1; - } - bignum_init(c); // int answer = 0; - - while (!bignum_is_zero(¤t)) // while (current != 0) - { - if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) - { - bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; - bignum_or(c, ¤t, c); // answer |= current; - } - _rshift_one_bit(¤t); // current >>= 1; - _rshift_one_bit(&denom); // denom >>= 1; - } // return answer; -} - - -void bignum_lshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b->array[i] <<= nbits; - } -} - - -void bignum_rshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b->array[i] >>= nbits; - } - -} - - -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) -{ - /* - Take divmod and throw away div part - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - bignum_divmod(a,b,&tmp,c); -} - -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) -{ - /* - Puts a%b in d - and a/b in c - - mod(a,b) = a - ((a / b) * b) - - example: - mod(8, 3) = 8 - ((8 / 3) * 3) = 2 - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - /* c = (a / b) */ - bignum_div(a, b, c); - - /* tmp = (c * b) */ - bignum_mul(c, b, &tmp); - - /* c = a - tmp */ - bignum_sub(a, &tmp, d); -} - -void bignum_or(struct bn* a, struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - c->array[i] = (a->array[i] | b->array[i]); - } -} - -int bignum_cmp(const struct bn *a, const struct bn *b) -{ - require(a, "a is null"); - require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do - { - i -= 1; /* Decrement first, to start with last array element */ - if (a->array[i] > b->array[i]) - { - return LARGER; - } - else if (a->array[i] < b->array[i]) - { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -int bignum_is_zero(const struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - if (n->array[i]) - { - return 0; - } - } - - return 1; -} - -void bignum_assign(struct bn* dst, const struct bn* src) -{ - require(dst, "dst is null"); - require(src, "src is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - dst->array[i] = src->array[i]; - } -} - - -/* Private / Static functions. */ -static void _rshift_word(struct bn* a, int nwords) -{ - /* Naive method: */ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - if (nwords >= BN_ARRAY_SIZE) - { - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } - return; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) - { - a->array[i] = a->array[i + nwords]; - } - for (; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } -} - - -static void _lshift_word(struct bn* a, int nwords) -{ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) - { - a->array[i] = a->array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) - { - a->array[i] = 0; - } -} - - -static void _lshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a->array[0] <<= 1; -} - - -static void _rshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a->array[BN_ARRAY_SIZE - 1] >>= 1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/bn.c b/crypto_sign/perk-256-short-3/m4/bn.c new file mode 120000 index 00000000..f7757f12 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/bn.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/bn.h b/crypto_sign/perk-256-short-3/m4/bn.h deleted file mode 100644 index c0debe59..00000000 --- a/crypto_sign/perk-256-short-3/m4/bn.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && msg) - - -/* Data-holding structure: array of DTYPEs */ -struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -}; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - - - -/* Initialization functions: */ -void bignum_init(struct bn* n); -void bignum_from_int(struct bn* n, DTYPE_TMP i); -int bignum_to_int(struct bn* n); - -/* Basic arithmetic operations: */ -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - -/* Bitwise operations: */ -void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ -void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ -void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ - -/* Special operators and comparison */ -int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ -int bignum_is_zero(const struct bn* n); /* For comparison with zero */ -void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ - - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/crypto_sign/perk-256-short-3/m4/bn.h b/crypto_sign/perk-256-short-3/m4/bn.h new file mode 120000 index 00000000..644cc71b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/bn.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common.c b/crypto_sign/perk-256-short-3/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-256-short-3/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common.c b/crypto_sign/perk-256-short-3/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common.h b/crypto_sign/perk-256-short-3/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-256-short-3/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common.h b/crypto_sign/perk-256-short-3/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/common_s.c b/crypto_sign/perk-256-short-3/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-256-short-3/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-256-short-3/m4/common_s.c b/crypto_sign/perk-256-short-3/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.c b/crypto_sign/perk-256-short-3/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-256-short-3/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.c b/crypto_sign/perk-256-short-3/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.h b/crypto_sign/perk-256-short-3/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-256-short-3/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-short-3/m4/crypto_memset.h b/crypto_sign/perk-256-short-3/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/data_structures.h b/crypto_sign/perk-256-short-3/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-256-short-3/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/data_structures.h b/crypto_sign/perk-256-short-3/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.c b/crypto_sign/perk-256-short-3/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-256-short-3/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.c b/crypto_sign/perk-256-short-3/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.h b/crypto_sign/perk-256-short-3/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-256-short-3/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-256-short-3/m4/djbsort.h b/crypto_sign/perk-256-short-3/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/keygen.c b/crypto_sign/perk-256-short-3/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-256-short-3/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/keygen.c b/crypto_sign/perk-256-short-3/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/keygen.h b/crypto_sign/perk-256-short-3/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-256-short-3/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/keygen.h b/crypto_sign/perk-256-short-3/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing.c b/crypto_sign/perk-256-short-3/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-256-short-3/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing.c b/crypto_sign/perk-256-short-3/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing.h b/crypto_sign/perk-256-short-3/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-256-short-3/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing.h b/crypto_sign/perk-256-short-3/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.c b/crypto_sign/perk-256-short-3/m4/parsing_permutations.c deleted file mode 100644 index 6edb9a7e..00000000 --- a/crypto_sign/perk-256-short-3/m4/parsing_permutations.c +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "rank_unrank_table.h" -#include "symmetric.h" - -#define PARAM_RANK_UNRANK_LEN_T \ - ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ - -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { - struct bn mul, code, tmp; - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - bignum_init(&code); - for (int i = 0; i < PARAM_N1; ++i) { - uint8_t ctr = in_p[i]; - uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - if (node & 0x1) { - ctr -= T[(node >> 1) << 1]; - } - T[node] += 1; - node = node >> 1; - } - T[node] += 1; - bignum_from_int(&tmp, PARAM_N1 - i); - bignum_mul(&code, &tmp, &mul); - bignum_from_int(&tmp, ctr); - bignum_add(&mul, &tmp, &code); - } - - memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); - memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); -} - -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { - struct bn code, tmp, tmp2, tmp3; - bignum_init(&code); - - memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); - - // validate the permutation encoding to be < n! - if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { - return EXIT_FAILURE; - } - - bignum_mod(&code, &factorial[PARAM_N1], &tmp); - bignum_assign(&tmp3, &tmp); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); - out_p[0] = bignum_to_int(&tmp); - - for (int i = 1; i < PARAM_N1 - 1; ++i) { - bignum_assign(&tmp3, &tmp2); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); - out_p[i] = bignum_to_int(&tmp); - } - - bignum_div(&tmp2, &factorial[0], &tmp); - out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { - for (int j = 0; j < (1 << i); ++j) { - T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); - } - } - - for (int i = 0; i < PARAM_N1; ++i) { - int digit = out_p[i]; - uint16_t node = 1; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - T[node] -= 1; - node <<= 1; - if (digit >= T[node]) { - digit -= T[node]; - node += 1; - } - } - T[node] = 0; - out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); - } - - return EXIT_SUCCESS; -} - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < (PARAM_TAU); i++) { - sig_perk_perm_encode(signature->responses[i].z2_pi, sb); - sb += PARAM_PERM_COMPRESSION_BYTES; - } -} - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - sb += PARAM_PERM_COMPRESSION_BYTES; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.c b/crypto_sign/perk-256-short-3/m4/parsing_permutations.c new file mode 120000 index 00000000..4227070c --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.h b/crypto_sign/perk-256-short-3/m4/parsing_permutations.h deleted file mode 100644 index 52c64e70..00000000 --- a/crypto_sign/perk-256-short-3/m4/parsing_permutations.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Permutation rank encoding. Encode a permutation into a bytearray. - * - * @param in_p input permutation - * @param out_buff output buffer byte string - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); - -/** - * @brief Permutation unrank decoding. Decode a bytearray into a permutation. - * - * @param in_buff input buffer byte string - * @param out_p output permutation - * @return EXIT_SUCCESS or EXIT_FAILURE - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/parsing_permutations.h b/crypto_sign/perk-256-short-3/m4/parsing_permutations.h new file mode 120000 index 00000000..f78f116d --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.c b/crypto_sign/perk-256-short-3/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-256-short-3/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.c b/crypto_sign/perk-256-short-3/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.h b/crypto_sign/perk-256-short-3/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-256-short-3/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/permutation.h b/crypto_sign/perk-256-short-3/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h deleted file mode 100644 index c530d04f..00000000 --- a/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file rank_unrank_table.h - * @brief Look-up table used in rank/unrank compression. - * For the GMP version, the encoding is in base-62 - * For tiny-bignum, the setting is for 32 bit architectures - * - * Each i-th value is i! encoded in base-62. - * - */ - -#ifndef SIG_PKP_RANK_UNRANK_TABLE_H -#define SIG_PKP_RANK_UNRANK_TABLE_H - -#include "bn.h" - -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} - -}; - -#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h new file mode 120000 index 00000000..0466ec6b --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/rank_unrank_table.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./rank_unrank_table.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/sign.c b/crypto_sign/perk-256-short-3/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-256-short-3/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/sign.c b/crypto_sign/perk-256-short-3/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.c b/crypto_sign/perk-256-short-3/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-256-short-3/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.c b/crypto_sign/perk-256-short-3/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.h b/crypto_sign/perk-256-short-3/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-256-short-3/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/signature.h b/crypto_sign/perk-256-short-3/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/sort.c b/crypto_sign/perk-256-short-3/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-256-short-3/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-256-short-3/m4/sort.c b/crypto_sign/perk-256-short-3/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.c b/crypto_sign/perk-256-short-3/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-256-short-3/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.c b/crypto_sign/perk-256-short-3/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.h b/crypto_sign/perk-256-short-3/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-256-short-3/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/symmetric.h b/crypto_sign/perk-256-short-3/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.c b/crypto_sign/perk-256-short-3/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-256-short-3/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.c b/crypto_sign/perk-256-short-3/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.h b/crypto_sign/perk-256-short-3/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-256-short-3/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/theta_tree.h b/crypto_sign/perk-256-short-3/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.c b/crypto_sign/perk-256-short-3/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-256-short-3/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.c b/crypto_sign/perk-256-short-3/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.h b/crypto_sign/perk-256-short-3/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-256-short-3/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verbose.h b/crypto_sign/perk-256-short-3/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.c b/crypto_sign/perk-256-short-3/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-256-short-3/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.c b/crypto_sign/perk-256-short-3/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.h b/crypto_sign/perk-256-short-3/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-256-short-3/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-3/m4/verify.h b/crypto_sign/perk-256-short-3/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-256-short-3/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/README b/crypto_sign/perk-256-short-5/m4/README deleted file mode 100644 index 864ffbb9..00000000 --- a/crypto_sign/perk-256-short-5/m4/README +++ /dev/null @@ -1,43 +0,0 @@ -+=============================================================================+ -| | -| *********************************************** | -| * POST-QUANTUM CRYPTO STANDARDIZATION * | -| *********************************************** | -| | -|=============================================================================| -| | -| Proposal: PERK | -| | -| Submitters (by alphabetical order): | -| - Najwa AARAJ | -| - Slim BETTAIEB | -| [main contact] - Loïc BIDOUX | -| - Alessandro BUDRONI | -| - Victor DYSERYN | -| - Andre ESSER | -| [backup contact] - Philippe GABORIT | -| - Mukul KULKARNI | -| - Victor MATEU | -| - Marco PALUMBI | -| - Lucas PERIN | -| - Jean-Pierre TILLICH | -| | -| Inventors: Same as submitters | -| | -| Developers: Same as submitters | -| | -| Owners: Same as submitters | -| | -+=============================================================================+ - -This archive is a proposal in response to NIST's call for proposal for standar- -dization of quantum-resistant digital signature schemes. - -PERK provides POST-QUANTUM SIGNATURES and targets NIST's -security levels 1, 3, and 5. - -=============================================================================== - -Implementation compliant with version v1.1 of 2023/10/16 -https://pqc-perk.org/ - diff --git a/crypto_sign/perk-256-short-5/m4/README b/crypto_sign/perk-256-short-5/m4/README new file mode 120000 index 00000000..2146f215 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/README @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./README \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/api.h b/crypto_sign/perk-256-short-5/m4/api.h deleted file mode 100644 index 3478f831..00000000 --- a/crypto_sign/perk-256-short-5/m4/api.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file api.h - * @brief NIST SIGN API - */ - -#ifndef SIG_PERK_API_H -#define SIG_PERK_API_H - -#include -#include "parameters.h" - -#define CRYPTO_ALGNAME "PERK" - -#define CRYPTO_PUBLICKEYBYTES PUBLIC_KEY_BYTES -#define CRYPTO_SECRETKEYBYTES PRIVATE_KEY_BYTES -#define CRYPTO_BYTES SIGNATURE_BYTES - -// As a technicality, the public key is appended to the secret key in order to respect the NIST API. -// Without this constraint, CRYPTO_SECRETKEYBYTES would be defined as SECURITY_BYTES - -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk); -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk); -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk); - -#endif diff --git a/crypto_sign/perk-256-short-5/m4/api.h b/crypto_sign/perk-256-short-5/m4/api.h new file mode 120000 index 00000000..d4bd0ac1 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/api.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./api.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.c b/crypto_sign/perk-256-short-5/m4/arithmetic.c deleted file mode 100644 index 3b9f86a5..00000000 --- a/crypto_sign/perk-256-short-5/m4/arithmetic.c +++ /dev/null @@ -1,154 +0,0 @@ - -/** - * @file arithmetic.c - * @brief Implementation of arithmetic related functions - */ - -#include "arithmetic.h" -#include -#include -#include "permutation.h" -#include "symmetric.h" - -static inline int16_t caddq(int16_t a) { - a += (a >> 15U) & PARAM_Q; // NOLINT(hicpp-signed-bitwise): behavior tested in unit tests - return a; -} - -static uint16_t multiplicativeInverse(uint16_t a) { - // assume a != 0 - // compute a^(q-2) mod q - uint16_t result = 1; - uint16_t exponent = PARAM_Q - 2; - - while (exponent > 0) { - if ((exponent & 0x1) == 1) { - result = sig_perk_barrett_reduce32((uint32_t)result * (uint32_t)a); - } - a = sig_perk_barrett_reduce32((uint32_t)a * (uint32_t)a); - exponent >>= 1; - } - - return result; -} - -int sig_perk_vect1_compute_rank(vect1_t in[PARAM_T]) { - int rank = 0; - int row, col; - - vect1_t x[PARAM_T]; - memcpy(x, in, sizeof(vect1_t) * PARAM_T); - for (col = 0; col < PARAM_N1; col++) { - int pivot_found = 0; - - // Find a non-zero pivot in the current column - for (int i = rank; i < PARAM_T; i++) { - if (x[i][col] != 0) { - row = i; - pivot_found = 1; - break; - } - } - - if (pivot_found) { - // Swap the current row with the row containing the pivot - for (int i = 0; i < PARAM_N1; i++) { - int temp = x[rank][i]; - x[rank][i] = x[row][i]; - x[row][i] = temp; - } - - // Perform row operations to eliminate entries below the pivot - for (row = rank + 1; row < PARAM_T; row++) { - uint16_t multiplier = - sig_perk_barrett_reduce32((uint32_t)x[row][col] * (uint32_t)multiplicativeInverse(x[rank][col])); - for (int i = col; i < PARAM_N1; i++) { - x[row][i] -= sig_perk_barrett_reduce32((uint32_t)multiplier * (uint32_t)x[rank][i]); - } - } - rank++; - } - if (rank == PARAM_T) - break; - } - return rank; -} - -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input) { - for (uint16_t i = 0; i < PARAM_N1; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int i = 0, rank; - do { - while (i < PARAM_N1 * PARAM_T) { - int j = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((i < PARAM_N1 * PARAM_T) && (j < PRNG_BLOCK_SIZE / 2)) { - output[i / PARAM_N1][i % PARAM_N1] = PARAM_Q_MASK & rnd_buff[j++]; - if (output[i / PARAM_N1][i % PARAM_N1] < PARAM_Q) { // accept the sample - i++; - } - } - } - // make sure the vectors x are linearly independent - rank = sig_perk_vect1_compute_rank(output); - } while (rank != PARAM_T); -} - -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - // we assume v1 and v2 already reduced - o[i] = caddq((int16_t)((int16_t)v1[i] + (int16_t)v2[i] - PARAM_Q)); - } -} - -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - o[i] = caddq((int16_t)((int16_t)v1[i] - (int16_t)v2[i])); - } -} - -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input) { - for (uint16_t i = 0; i < PARAM_M; ++i) { - output[i] = sig_perk_barrett_reduce32((uint32_t)scalar * (uint32_t)input[i]); - } -} - -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg) { - uint16_t rnd_buff[PRNG_BLOCK_SIZE / 2]; - // generate randomness - int j = 0; - while (j < PARAM_M * PARAM_N1) { - int k = 0; - sig_perk_prg(prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - while ((j < PARAM_M * PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - m_output[j / PARAM_N1][j % PARAM_N1] = PARAM_Q_MASK & rnd_buff[k++]; - if (m_output[j / PARAM_N1][j % PARAM_N1] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input) { - uint32_t tmp = 0; - for (int i = 0; i < PARAM_M; ++i) { - for (int j = 0; j < PARAM_N1; ++j) { - tmp += ((uint32_t)m_input[i][j]) * ((uint32_t)v_input[j]); - } - output[i] = sig_perk_barrett_reduce32(tmp); - tmp = 0; - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.c b/crypto_sign/perk-256-short-5/m4/arithmetic.c new file mode 120000 index 00000000..c83a28aa --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/arithmetic.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.h b/crypto_sign/perk-256-short-5/m4/arithmetic.h deleted file mode 100644 index 06d8d43b..00000000 --- a/crypto_sign/perk-256-short-5/m4/arithmetic.h +++ /dev/null @@ -1,156 +0,0 @@ - -/** - * @file arithmetic.h - * @brief Header file for arithmetic.c - */ - -#ifndef SIG_PERK_ARITHMETIC_H -#define SIG_PERK_ARITHMETIC_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define SHBIT16 25 -#define SHBIT32 41 - -/** - * @brief Vector vect1_t - * - * This structure contains a vector of size PARAM_N1 - */ -typedef uint16_t vect1_t[PARAM_N1]; - -/** - * @brief Vector vect2_t - * - * This structure contains a vector of size PARAM_M - */ -typedef uint16_t vect2_t[PARAM_M]; - -/** - * @brief Matrix mat_t - * - * This structure contains a matrix represented as a vector of vectors of type vect1_t - */ -typedef vect1_t mat_t[PARAM_M]; - -/** - * @brief perform barrett reduction on a 16 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 65535 (0xFFFF) - * - * @param a 16 bit input - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce16(uint16_t a) { - uint16_t t; - const uint32_t v = ((((uint32_t)1U << SHBIT16) / PARAM_Q)); - - t = ((v * a + v) >> SHBIT16); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief perform barrett reduction on a 32 bit input value - * output range 0 <= out < PARAM_Q - * input range: - * - PARAM_Q == 1021: 0 <= a <= 4294967295 (0xFFFFFFFF) - * - * @param a 32 bit input value - * @return uint16_t output - */ -static inline uint16_t sig_perk_barrett_reduce32(uint32_t a) { - uint32_t t; - const uint64_t v = (((uint64_t)1U << SHBIT32) / PARAM_Q); - - t = ((v * a + v) >> SHBIT32); // NOLINT(hicpp-signed-bitwise): tested in unit tests - t *= PARAM_Q; - return (uint16_t)(a - t); -} - -/** - * @brief Add in Fq two vect1_t vectors - * - * @details The prototype of this function differs from the others in this file due to - * a false positive warning with GCC 13 (-Wstringop-overflow) when compiling with -O3. - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect1_add(uint16_t *o, const uint16_t *v1, const uint16_t *v2); - -/** - * @brief Multiplication in Fq of a vect1_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect1_t - */ -void sig_perk_vect1_mult_scalar_vect(vect1_t output, const uint16_t scalar, const vect1_t input); - -/** - * @brief Given a list of PARAM_T vectors vect1_t, compute the rank of the matrix - * formed by these. Used to test the linear dependence. - * - * @param [in] x list of vectors to be seen as a matrix - * @returns the rank of the matrix - */ -int sig_perk_vect1_compute_rank(vect1_t x[PARAM_T]); - -/** - * @brief Sample uniformly at random a list of PARAM_T vect1_t vectors in Fq - * - * @param [out] output an array of vectors vect1_t containing the result - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_vect1_set_random_list(vect1_t output[PARAM_T], sig_perk_prg_state_t *prg); - -/** - * @brief Add in Fq two vect2_t vectors - * - * @param [out] o a vector containing the result - * @param [in] v1 a vector - * @param [in] v2 a vector - */ -void sig_perk_vect2_add(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Subtract in Fq two vect2_t vectors - * - * @param [out] o vector containing the result - * @param [in] v1 vector - * @param [in] v2 vector - */ -void sig_perk_vect2_sub(vect2_t o, const vect2_t v1, const vect2_t v2); - -/** - * @brief Multiplication in Fq of a vect2_t vector by a scalar - * - * @param [out] output vector containing the result - * @param [in] scalar a scalar in Fq - * @param [in] input a vector of type vect2_t - */ -void sig_perk_vect2_mult_scalar_vect(vect2_t output, const uint16_t scalar, const vect2_t input); - -/** - * @brief Generate a (PARAM_M x PARAM_N1) random matrix in Fq - * - * @param [out] m_output a matrix - * @param [out,in] prg PRG state to squeeze - */ -void sig_perk_mat_set_random(mat_t m_output, sig_perk_prg_state_t *prg); - -/** - * @brief Compute a matrix vector multiplication in Fq - * - * @param [out] output a vector - * @param [in] m_input a matrix - * @param [in] v_input a vector - */ -void sig_perk_mat_vect_mul(vect2_t output, const mat_t m_input, const vect1_t v_input); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/arithmetic.h b/crypto_sign/perk-256-short-5/m4/arithmetic.h new file mode 120000 index 00000000..fcd2b59d --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/arithmetic.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./arithmetic.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/bn.c b/crypto_sign/perk-256-short-5/m4/bn.c deleted file mode 100644 index b676feb3..00000000 --- a/crypto_sign/perk-256-short-5/m4/bn.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include -#include "bn.h" - - - -/* Functions for shifting number in-place. */ -static void _lshift_one_bit(struct bn* a); -static void _rshift_one_bit(struct bn* a); -static void _lshift_word(struct bn* a, int nwords); -static void _rshift_word(struct bn* a, int nwords); - - - -/* Public / Exported functions. */ -void bignum_init(struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - n->array[i] = 0; - } -} - - -void bignum_from_int(struct bn* n, DTYPE_TMP i) -{ - require(n, "n is null"); - - bignum_init(n); - - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE -#if (WORD_SIZE == 1) - n->array[0] = (i & 0x000000ff); - n->array[1] = (i & 0x0000ff00) >> 8; - n->array[2] = (i & 0x00ff0000) >> 16; - n->array[3] = (i & 0xff000000) >> 24; -#elif (WORD_SIZE == 2) - n->array[0] = (i & 0x0000ffff); - n->array[1] = (i & 0xffff0000) >> 16; -#elif (WORD_SIZE == 4) - n->array[0] = i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n->array[1] = tmp; -#endif -#endif -} - - -int bignum_to_int(struct bn* n) -{ - require(n, "n is null"); - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n->array[0]; - ret += n->array[1] << 8; - ret += n->array[2] << 16; - ret += n->array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n->array[0]; - ret += n->array[1] << 16; -#elif (WORD_SIZE == 4) - ret += (int)n->array[0]; -#endif - - return ret; -} - -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; - carry = (tmp > MAX_VAL); - c->array[i] = (tmp & MAX_VAL); - } -} - - -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b->array[i] + borrow; - res = (tmp1 - tmp2); - c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } -} - - -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - bignum_init(c); - - if (bignum_is_zero(a)) {return;} - if (bignum_is_zero(b)) {return;} - - struct bn tmp; - struct bn max_val; - bignum_from_int(&max_val, MAX_VAL); - - struct bn a1; - DTYPE_TMP a0; - struct bn b1; - DTYPE_TMP b0; - struct bn z0; - struct bn z1; - struct bn z2; - - bignum_rshift(a, &a1, WORD_SIZE*8); - bignum_rshift(b, &b1, WORD_SIZE*8); - a0 = (DTYPE_TMP)(a->array[0]); - b0 = (DTYPE_TMP)(b->array[0]); - DTYPE_TMP z0_small = a0*b0; - - bignum_init(&z0); - z0.array[0] = z0_small & MAX_VAL; - z0.array[1] = (z0_small & (MAX_VAL << (WORD_SIZE*8))) >> (WORD_SIZE*8); - if (bignum_is_zero(&a1) && bignum_is_zero(&b1)) { - bignum_assign(c, &z0); - return; - } - bignum_mul(&a1, &b1, &z2); - struct bn a0_big; - struct bn b0_big; - bignum_from_int(&a0_big, a0); - bignum_from_int(&b0_big, b0); - - struct bn tmpa; - struct bn tmpb; - struct bn tmpz1; - bignum_add(&a1, &a0_big, &tmpa); - bignum_add(&b1, &b0_big, &tmpb); - bignum_mul(&tmpa, &tmpb, &tmpz1); - bignum_sub(&tmpz1, &z2, &tmpa); - bignum_sub(&tmpa, &z0, &z1); - - bignum_lshift(&z2, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z1, c); - bignum_lshift(c, &tmp, WORD_SIZE*8); - bignum_add(&tmp, &z0, c); -} - - -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn current; - struct bn denom; - struct bn tmp; - - bignum_from_int(¤t, 1); // int current = 1; - bignum_assign(&denom, b); // denom = b - bignum_assign(&tmp, a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - while (bignum_cmp(&denom, a) != LARGER) // while (denom <= a) { - { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) - { - overflow = true; - break; - } - _lshift_one_bit(¤t); // current <<= 1; - _lshift_one_bit(&denom); // denom <<= 1; - } - if (!overflow) - { - _rshift_one_bit(&denom); // denom >>= 1; - _rshift_one_bit(¤t); // current >>= 1; - } - bignum_init(c); // int answer = 0; - - while (!bignum_is_zero(¤t)) // while (current != 0) - { - if (bignum_cmp(&tmp, &denom) != SMALLER) // if (dividend >= denom) - { - bignum_sub(&tmp, &denom, &tmp); // dividend -= denom; - bignum_or(c, ¤t, c); // answer |= current; - } - _rshift_one_bit(¤t); // current >>= 1; - _rshift_one_bit(&denom); // denom >>= 1; - } // return answer; -} - - -void bignum_lshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b->array[i] <<= nbits; - } -} - - -void bignum_rshift(const struct bn* a, struct bn* b, int nbits) -{ - require(a, "a is null"); - require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bignum_assign(b, a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) - { - _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) - { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b->array[i] >>= nbits; - } - -} - - -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c) -{ - /* - Take divmod and throw away div part - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - bignum_divmod(a,b,&tmp,c); -} - -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d) -{ - /* - Puts a%b in d - and a/b in c - - mod(a,b) = a - ((a / b) * b) - - example: - mod(8, 3) = 8 - ((8 / 3) * 3) = 2 - */ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - struct bn tmp; - - /* c = (a / b) */ - bignum_div(a, b, c); - - /* tmp = (c * b) */ - bignum_mul(c, b, &tmp); - - /* c = a - tmp */ - bignum_sub(a, &tmp, d); -} - -void bignum_or(struct bn* a, struct bn* b, struct bn* c) -{ - require(a, "a is null"); - require(b, "b is null"); - require(c, "c is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - c->array[i] = (a->array[i] | b->array[i]); - } -} - -int bignum_cmp(const struct bn *a, const struct bn *b) -{ - require(a, "a is null"); - require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do - { - i -= 1; /* Decrement first, to start with last array element */ - if (a->array[i] > b->array[i]) - { - return LARGER; - } - else if (a->array[i] < b->array[i]) - { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -int bignum_is_zero(const struct bn* n) -{ - require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - if (n->array[i]) - { - return 0; - } - } - - return 1; -} - -void bignum_assign(struct bn* dst, const struct bn* src) -{ - require(dst, "dst is null"); - require(src, "src is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - dst->array[i] = src->array[i]; - } -} - - -/* Private / Static functions. */ -static void _rshift_word(struct bn* a, int nwords) -{ - /* Naive method: */ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - if (nwords >= BN_ARRAY_SIZE) - { - for (i = 0; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } - return; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) - { - a->array[i] = a->array[i + nwords]; - } - for (; i < BN_ARRAY_SIZE; ++i) - { - a->array[i] = 0; - } -} - - -static void _lshift_word(struct bn* a, int nwords) -{ - require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) - { - a->array[i] = a->array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) - { - a->array[i] = 0; - } -} - - -static void _lshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) - { - a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a->array[0] <<= 1; -} - - -static void _rshift_one_bit(struct bn* a) -{ - require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) - { - a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a->array[BN_ARRAY_SIZE - 1] >>= 1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/bn.c b/crypto_sign/perk-256-short-5/m4/bn.c new file mode 120000 index 00000000..f7757f12 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/bn.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/bn.h b/crypto_sign/perk-256-short-5/m4/bn.h deleted file mode 100644 index c0debe59..00000000 --- a/crypto_sign/perk-256-short-5/m4/bn.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -*/ - -#include -#include - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && msg) - - -/* Data-holding structure: array of DTYPEs */ -struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -}; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - - - -/* Initialization functions: */ -void bignum_init(struct bn* n); -void bignum_from_int(struct bn* n, DTYPE_TMP i); -int bignum_to_int(struct bn* n); - -/* Basic arithmetic operations: */ -void bignum_add(const struct bn* a, const struct bn* b, struct bn* c); /* c = a + b */ -void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c); /* c = a - b */ -void bignum_mul(const struct bn* a, const struct bn* b, struct bn* c); /* c = a * b */ -void bignum_div(const struct bn* a, const struct bn* b, struct bn* c); /* c = a / b */ -void bignum_mod(const struct bn* a, const struct bn* b, struct bn* c); /* c = a % b */ -void bignum_divmod(const struct bn* a, const struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - -/* Bitwise operations: */ -void bignum_or(struct bn* a, struct bn* b, struct bn* c); /* c = a | b */ -void bignum_lshift(const struct bn* a, struct bn* b, int nbits); /* b = a << nbits */ -void bignum_rshift(const struct bn* a, struct bn* b, int nbits); /* b = a >> nbits */ - -/* Special operators and comparison */ -int bignum_cmp(const struct bn* a, const struct bn* b); /* Compare: returns LARGER, EQUAL or SMALLER */ -int bignum_is_zero(const struct bn* n); /* For comparison with zero */ -void bignum_assign(struct bn* dst, const struct bn* src); /* Copy src into dst -- dst := src */ - - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/crypto_sign/perk-256-short-5/m4/bn.h b/crypto_sign/perk-256-short-5/m4/bn.h new file mode 120000 index 00000000..644cc71b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/bn.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./bn.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common.c b/crypto_sign/perk-256-short-5/m4/common.c deleted file mode 100644 index 0ba860c9..00000000 --- a/crypto_sign/perk-256-short-5/m4/common.c +++ /dev/null @@ -1,102 +0,0 @@ - -/** - * @file common.c - * @brief Common functions - */ - -#include "common.h" -#include -#include "crypto_memset.h" -#include "symmetric.h" - -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input(pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} - -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta) { - // To make easier the times4 optimized implementation - // we reinitialise the PRNG with a different domain separator, thus we use - // PRG1 to sample the pi_i and PRG2 to sample the v_i - sig_perk_prg_init(state, PRG2, salt, theta); - int j = 0; - while (j < PARAM_N1) { - int k = 0; - sig_perk_prg(state, (uint8_t *)rnd_buff_v_i, (PRNG_BLOCK_SIZE / 2) * sizeof(uint16_t)); - while ((j < PARAM_N1) && (k < PRNG_BLOCK_SIZE / 2)) { - v_i[j] = PARAM_Q_MASK & rnd_buff_v_i[k++]; - if (v_i[j] < PARAM_Q) { // accept the sample - j++; - } - } - } -} - -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, - const perk_theta_seeds_tree_t theta_tree) { - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i[i], salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - sig_perk_gen_one_v_i(v_i[i], salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi) { - vect1_t tmp_vect; - perm_t tmp_compose_perm; - - sig_perk_perm_compose_inv(tmp_compose_perm, pi, pi_i[0]); - sig_perk_perm_vect_permute(o, tmp_compose_perm, v_i[0]); - for (int i = 1; i < PARAM_N - 1; ++i) { - sig_perk_perm_compose_inv(tmp_compose_perm, tmp_compose_perm, pi_i[i]); - sig_perk_perm_vect_permute(tmp_vect, tmp_compose_perm, v_i[i]); - sig_perk_vect1_add(o, o, tmp_vect); - } - sig_perk_vect1_add(o, o, v_i[PARAM_N - 1]); -} - -// Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau) { - for (int i = 0; i < PARAM_N; ++i) { - sig_perk_hash_state_t state; - uint8_t idx = i; - if (i == 0) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->pi_i[0], PARAM_N1); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[PARAM_N - 1], H0); - } else { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, instance->theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, instance->cmt_1_i[(PARAM_N - 1) - i], H0); - } - } -} - -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi) { - sig_perk_gen_pi_i_and_v_i(instance->pi_i, instance->v_i, salt, (const theta_t *)instance->theta_tree); - sig_perk_perm_gen_pi_1(instance->pi_i, pi); - sig_perk_gen_commitment_cmt_1_i(instance, salt, tau); -} - -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v) { - sig_perk_hash_state_t state; - vect2_t tmp; - sig_perk_mat_vect_mul(tmp, H, v); - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp, sizeof(tmp)); - sig_perk_hash_final(&state, cmt_1, H0); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common.c b/crypto_sign/perk-256-short-5/m4/common.c new file mode 120000 index 00000000..455b7524 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common.h b/crypto_sign/perk-256-short-5/m4/common.h deleted file mode 100644 index 649f2dc8..00000000 --- a/crypto_sign/perk-256-short-5/m4/common.h +++ /dev/null @@ -1,109 +0,0 @@ - -/** - * @file common.h - * @brief Header file for common.c - */ - -#ifndef SIG_PERK_COMMON_H -#define SIG_PERK_COMMON_H - -#include "data_structures.h" -#include "permutation.h" -#include "symmetric.h" - -/** - * @brief Generate a set of pi_i and v_i - * - * @param [out] pi_i a pointer to permutations - * @param [out] v_i a pointer to vectors v_i - * @param [in] salt a salt - * @param [in] theta_tree a tree of seeds - */ -void sig_perk_gen_pi_i_and_v_i(perm_t *pi_i, vect1_t *v_i, const salt_t salt, const perk_theta_seeds_tree_t theta_tree); - -/** - * @brief Generate one pi_i - * - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i(perm_t pi_i, const salt_t salt, uint16_t rnd_buffer_pi_i[PARAM_N1], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate one pi_i and compose with pi_comp - * - * @param [out,in] pi_comp pointer to the permutation to be composed with the sampled one - * @param [out] pi_i a pointer to the permutation sampled - * @param [in] salt a salt - * @param [out,in] rnd_buffer_pi_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta); - -/** - * @brief Generate one v_i - * - * @param [out] v_i - * @param [in] salt a salt - * @param [out,in] rnd_buff_v_i memory buffer used to sample randomness. - * must be erased by the caller - * @param [out,in] state state for the prg used to sample randomness. - * must be erased by the caller - * @param [in] theta the seed for the prg - */ -void sig_perk_gen_one_v_i(vect1_t v_i, const salt_t salt, uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2], - sig_perk_prg_state_t *state, const theta_t theta); - -/** - * @brief Generate the vector v - * - * @param [out] o a variable containing the vector v - * @param [in] pi_i a pointer to permutations pi_i - * @param [in] v_i a pointer to vectors v_i - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_vect_v(vect1_t o, perm_t *pi_i, vect1_t *v_i, const perm_t pi); - -/** - * @brief Compute commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance pointer to struct instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - */ -void sig_perk_gen_commitment_cmt_1_i(perk_instance_t *instance, salt_t salt, uint8_t tau); - -/** - * @brief Generate commitments cmt_1,i (for i in 1,...,N) for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] pi a variable containing the secret permutation pi - */ -void sig_perk_gen_instance_commitments(perk_instance_t *instance, salt_t salt, uint8_t tau, const perm_t pi); - -/** - * @brief Compute commitment cmt_1 for one round of the scheme - * - * @param [out,in] instance a pointer to an instance - * @param [in] salt a salt - * @param [in] tau an integer that is the index in 0,...,tau - * @param [in] H a variable containing the public matrix H - * @param [in] v a variable containing to vectors v_i - */ -void sig_perk_gen_instance_commitment_cmt_1(cmt_t cmt_1, const salt_t salt, uint8_t tau, const mat_t H, - const vect1_t v); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common.h b/crypto_sign/perk-256-short-5/m4/common.h new file mode 120000 index 00000000..4ab4e7de --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/common_s.c b/crypto_sign/perk-256-short-5/m4/common_s.c deleted file mode 100644 index 9bbb7b67..00000000 --- a/crypto_sign/perk-256-short-5/m4/common_s.c +++ /dev/null @@ -1,42 +0,0 @@ - -/** - * @file common_s.c - * @brief Streamlined common functions - */ - -#include "common.h" -#include "djbsort.h" -#include "permutation.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | pi_comp[i] << 8U | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint8_t)(0xFF & buffer[i]); - pi_comp[i] = (uint8_t)((0xFF00 & buffer[i]) >> 8U); - } - return EXIT_SUCCESS; -} - -void sig_perk_gen_one_pi_i_and_compose(perm_t pi_comp, perm_t pi_i, const salt_t salt, - uint16_t rnd_buffer_pi_i[PARAM_N1], sig_perk_prg_state_t *state, - const theta_t theta) { - sig_perk_prg_init(state, PRG1, salt, theta); - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - while (sig_perk_perm_gen_given_random_input_and_compose(pi_comp, pi_i, rnd_buffer_pi_i) != EXIT_SUCCESS) { - sig_perk_prg(state, (uint8_t *)rnd_buffer_pi_i, PARAM_N1 * sizeof(uint16_t)); - } -} diff --git a/crypto_sign/perk-256-short-5/m4/common_s.c b/crypto_sign/perk-256-short-5/m4/common_s.c new file mode 120000 index 00000000..a969e47e --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/common_s.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./common_s.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.c b/crypto_sign/perk-256-short-5/m4/crypto_memset.c deleted file mode 100644 index 531c15a9..00000000 --- a/crypto_sign/perk-256-short-5/m4/crypto_memset.c +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file memset.c - * @brief Implementation of safe memset - */ -#include - -void *(*volatile memset_volatile)(void *, int, size_t) = memset; diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.c b/crypto_sign/perk-256-short-5/m4/crypto_memset.c new file mode 120000 index 00000000..e2e1eab2 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/crypto_memset.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.h b/crypto_sign/perk-256-short-5/m4/crypto_memset.h deleted file mode 100644 index 0612f683..00000000 --- a/crypto_sign/perk-256-short-5/m4/crypto_memset.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file memset.h - * @brief Header file for memset.c - */ - -#ifndef PERK_CRYPTO_MEMSET_H -#define PERK_CRYPTO_MEMSET_H - -#include - -/** - * safer call to memset https://github.com/veorq/cryptocoding#problem-4 - */ -extern void *(*volatile memset_volatile)(void *, int, size_t); - -#define memset_zero(ptr, len) memset_volatile((ptr), 0, (len)) - -#endif // PERK_CRYPTO_MEMSET_H diff --git a/crypto_sign/perk-256-short-5/m4/crypto_memset.h b/crypto_sign/perk-256-short-5/m4/crypto_memset.h new file mode 120000 index 00000000..bd8312e1 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/crypto_memset.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./crypto_memset.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/data_structures.h b/crypto_sign/perk-256-short-5/m4/data_structures.h deleted file mode 100644 index b303c778..00000000 --- a/crypto_sign/perk-256-short-5/m4/data_structures.h +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file data_structures.h - * @brief common data structures for the scheme - */ - -#ifndef SIG_PERK_DATA_STRUCTURES_H -#define SIG_PERK_DATA_STRUCTURES_H - -#include -#include "arithmetic.h" -#include "parameters.h" -#include "permutation.h" -#include "symmetric.h" -#include "theta_tree.h" - -/** - * @brief Commitment cmt_t - * - * This structure contains a commitment - */ -typedef uint8_t cmt_t[COMMITMENT_BYTES]; - -/** @struct perk_public_key_t - * @brief This structure contains the public key - * @var perk_public_key_t::seed - * Member 'seed' is an array of bytes used to generate the public key - * @var perk_public_key_t::H - * Member 'H' is a matrix - * @var perk_public_key_t::x - * Member 'x' is a vector of vectors - * @var perk_public_key_t::y - * Member 'y' is a vector of vectors - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - mat_t H; - vect1_t x[PARAM_T]; - vect2_t y[PARAM_T]; -} perk_public_key_t; - -/** @struct perk_private_key_t - * @brief This structure contains the private key - * @var perk_private_key_t::seed - * Member 'seed' is an array of bytes used to generate the private key - * @var perk_private_key_t::pi - * Member 'pi' is a permutation - * @var perk_private_key_t::pk_bytes - * Member 'pk_bytes' is an array of bytes that contain the public key - */ -typedef struct { - uint8_t seed[SEED_BYTES]; - perm_t pi; - uint8_t pk_bytes[PUBLIC_KEY_BYTES]; -} perk_private_key_t; - -/** @struct perk_instance_t - * @brief This structure contains an instance of one round of the scheme - * @var perk_instance_t::theta_tree - * Member 'theta_tree' is a seed tree containing theta and the theta_i - * @var perk_instance_t::pi_i - * Member 'pi_i' is a permutation - * @var perk_instance_t::v_i - * Member 'v_i' is a pointer to the second element of the s_i array. v_i shares the memory with s_i - * @var perk_instance_t::s_i - * Member 's_i' is an array of vectors - * @var perk_instance_t::cmt_1_i - * Member 'cmt_1_i' is an array of commitments. Commitments are stored in reverse order: from element (PARAM_N-1) down - * to element 0. - * @var perk_instance_t::cmt_1 - * Member 'cmt_1' is a commitment - */ -typedef struct { - perk_theta_seeds_tree_t theta_tree; - perm_t pi_i[PARAM_N]; - // v_i shares the same memory with s_i. The pointer must be initialized to s_i + 1; - vect1_t *v_i; - vect1_t s_i[PARAM_N + 1]; - cmt_t cmt_1_i[PARAM_N]; - cmt_t cmt_1; -} perk_instance_t; - -/** - * @brief initialize an array of "perk_instance_t" elements - * - * @param [out,in] instances array of perk_instance_t elements - * @param [in] elements number of elements to be initialized - */ -static inline void perk_instance_t_array_init(perk_instance_t *instances, const int elements) { - for (int i = 0; i < elements; i++) { - instances[i].v_i = &(instances[i].s_i[1]); - } -} - -/** @struct perk_response_t - * @brief This structure contains the response - * @var perk_response_t::z1 - * Member 'z1' is a vector - * @var perk_response_t::z2_pi - * Member 'z2_pi' is a permutation - * @var perk_response_t::z2_theta - * Member 'z2_theta' is an array of theta_t - * @var perk_response_t::cmt_1_alpha - * Member 'cmt_1_alpha' is commitment - */ -typedef struct { - vect1_t z1; - perm_t z2_pi; - theta_t z2_theta[THETA_TREE_LEVELS]; - cmt_t cmt_1_alpha; -} perk_response_t; - -/** @struct perk_signature_t - * @brief This structure contains the signature - * @var perk_signature_t::salt - * Member 'salt' is a salt - * @var perk_signature_t::h1 - * Member 'h1' is a digest - * @var perk_signature_t::h2 - * Member 'h2' is a digest - * @var perk_signature_t::responses - * Member 'responses' is an array of perk_response_t - */ -typedef struct { - salt_t salt; - digest_t h1; - digest_t h2; - perk_response_t responses[PARAM_TAU]; -} perk_signature_t; - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/data_structures.h b/crypto_sign/perk-256-short-5/m4/data_structures.h new file mode 120000 index 00000000..abcad83c --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/data_structures.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./data_structures.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.c b/crypto_sign/perk-256-short-5/m4/djbsort.c deleted file mode 100644 index 62e49c57..00000000 --- a/crypto_sign/perk-256-short-5/m4/djbsort.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "djbsort.h" - -/* can save time by vectorizing xor loops */ -/* can save time by integrating xor loops with int32_sort */ - -void uint32_sort(uint32_t *x,size_t n) -{ - size_t j; - for (j = 0;j < n;++j) x[j] ^= 0x80000000; - int32_sort((int32_t *) x,n); - for (j = 0;j < n;++j) x[j] ^= 0x80000000; -} diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.c b/crypto_sign/perk-256-short-5/m4/djbsort.c new file mode 120000 index 00000000..b9643c8d --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/djbsort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.h b/crypto_sign/perk-256-short-5/m4/djbsort.h deleted file mode 100644 index 92f51643..00000000 --- a/crypto_sign/perk-256-short-5/m4/djbsort.h +++ /dev/null @@ -1,16 +0,0 @@ - -/** - * @file djbsort.h - * @brief Header file for sorting functions - */ - -#ifndef DJB_SORT_H -#define DJB_SORT_H - -#include -#include - -extern void uint32_sort(uint32_t *, size_t) __attribute__((visibility("default"))); -extern void int32_sort(int32_t *, size_t) __attribute__((visibility("default"))); - -#endif diff --git a/crypto_sign/perk-256-short-5/m4/djbsort.h b/crypto_sign/perk-256-short-5/m4/djbsort.h new file mode 120000 index 00000000..2b03be57 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/djbsort.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./djbsort.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/keygen.c b/crypto_sign/perk-256-short-5/m4/keygen.c deleted file mode 100644 index 384e277e..00000000 --- a/crypto_sign/perk-256-short-5/m4/keygen.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file keygen.c - * @brief Implementation of key generation - */ - -#include "keygen.h" -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "parameters.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "verbose.h" - -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk) { - vect1_t tmp; - // sample seeds - randombytes(pk->seed, sizeof(pk->seed)); - randombytes(sk->seed, sizeof(sk->seed)); - - // sample private key - sig_perk_perm_set_random(sk->pi, sk->seed); - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - // compute y - for (int i = 0; i < PARAM_T; i++) { - // compute tmp = pi(x) - sig_perk_perm_vect_permute(tmp, sk->pi, pk->x[i]); - sig_perk_mat_vect_mul(pk->y[i], (const vect1_t *)pk->H, tmp); - } - - sig_perk_public_key_to_bytes(sk->pk_bytes, pk); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk_seed", sk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pi", sk->pi, PARAM_N1); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk_seed", pk->seed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_matrix((const vect1_t *)pk->H); - SIG_PERK_VERBOSE_PRINT_x((const vect1_t *)pk->x); - SIG_PERK_VERBOSE_PRINT_y((const vect2_t *)pk->y); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/keygen.c b/crypto_sign/perk-256-short-5/m4/keygen.c new file mode 120000 index 00000000..72dcf88b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/keygen.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/keygen.h b/crypto_sign/perk-256-short-5/m4/keygen.h deleted file mode 100644 index 7d84ee2f..00000000 --- a/crypto_sign/perk-256-short-5/m4/keygen.h +++ /dev/null @@ -1,21 +0,0 @@ - -/** - * @file keygen.h - * @brief Header file for keygen.c - */ - -#ifndef SIG_PERK_KEYGEN_H -#define SIG_PERK_KEYGEN_H - -#include "data_structures.h" - -/** - * @brief Generate a key pair - * - * @param [out] pk a pointer to public key structure - * @param [out] sk a pointer to private key structure - * @return int 0 if the key generation is successful - */ -uint8_t sig_perk_generate_keypair(perk_public_key_t *pk, perk_private_key_t *sk); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/keygen.h b/crypto_sign/perk-256-short-5/m4/keygen.h new file mode 120000 index 00000000..da9d4863 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/keygen.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./keygen.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing.c b/crypto_sign/perk-256-short-5/m4/parsing.c deleted file mode 100644 index 0d0deda5..00000000 --- a/crypto_sign/perk-256-short-5/m4/parsing.c +++ /dev/null @@ -1,217 +0,0 @@ - -/** - * @file parsing.c - * @brief Implementation of parsing functions - */ - -#include "parsing.h" -#include "parameters.h" -#include "parsing_permutations.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "symmetric.h" - -/** - * @brief store a 10 bit value in a byte array at bit position i*10 - * must be called sequentially with increasing index - * - * @param sb byte array pointer - * @param i position in the byte array - * @param val 10 bit value to store - */ -static inline void store_10bit_in_bytearray(uint8_t* sb, int i, uint16_t val) { - val &= 0x3FF; - int k = (i / 4) * 5; - switch (i % 4) { - case 0: - sb[k + 0] = val; - sb[k + 1] = val >> 8; - break; - case 1: - sb[k + 1] |= val << 2; - sb[k + 2] = val >> 6; - break; - case 2: - sb[k + 2] |= val << 4; - sb[k + 3] = val >> 4; - break; - case 3: - sb[k + 3] |= val << 6; - sb[k + 4] = val >> 2; - break; - default: - break; - } -} - -/** - * @brief load a 10 bit value from a byte array at bit position i*10 - * - * @param sb byte array pointer - * @param i position in the byte array - * @return uint16_t loaded value - */ -static inline uint16_t load_10bit_from_bytearray(const uint8_t* sb, int i) { - int k = (i / 4) * 5; - uint16_t val = 0; - switch (i % 4) { - case 0: - val = sb[k + 0]; - val |= ((uint16_t)sb[k + 1] & 0x3) << 8; - break; - case 1: - val = sb[k + 1] >> 2; - val |= ((uint16_t)sb[k + 2] & 0xF) << 6; - break; - case 2: - val = sb[k + 2] >> 4; - val |= ((uint16_t)sb[k + 3] & 0x3F) << 4; - break; - case 3: - val = sb[k + 3] >> 6; - val |= ((uint16_t)sb[k + 4] & 0xFF) << 2; - break; - default: - break; - } - - return val; -} - -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk) { - memcpy(sk_bytes, sk->seed, SEED_BYTES); - memcpy(sk_bytes + SEED_BYTES, sk->pk_bytes, PUBLIC_KEY_BYTES); -} - -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]) { - memcpy(sk->seed, sk_bytes, SEED_BYTES); - memcpy(sk->pk_bytes, sk_bytes + SEED_BYTES, PUBLIC_KEY_BYTES); - sig_perk_perm_set_random(sk->pi, sk->seed); -} - -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk) { - memcpy(pk_bytes, pk->seed, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - store_10bit_in_bytearray(pk_bytes + SEED_BYTES, i, pk->y[i / PARAM_M][i % PARAM_M]); - } -} - -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]) { - memcpy(pk->seed, pk_bytes, SEED_BYTES); - for (int i = 0; i < PARAM_M * PARAM_T; i++) { - uint16_t y = load_10bit_from_bytearray(pk_bytes + SEED_BYTES, i); - if (y >= PARAM_Q) { - // y out of range - return EXIT_FAILURE; - } - pk->y[i / PARAM_M][i % PARAM_M] = y; - } - - sig_perk_prg_state_t prg; - // initialize prg - sig_perk_prg_init(&prg, PRG1, NULL, pk->seed); - - // Generate H and x - sig_perk_mat_set_random(pk->H, &prg); - sig_perk_vect1_set_random_list(pk->x, &prg); - - return EXIT_SUCCESS; -} - -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2) { - sig_perk_prg_state_t h1_prg_state; - sig_perk_prg_state_t h2_prg_state; - uint16_t tmp_kappa; - uint16_t tmp_alpha; - - // generate first challenge - sig_perk_prg_init(&h1_prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&h1_prg_state, (uint8_t*)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenges[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } - // generate second challenge - sig_perk_prg_init(&h2_prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&h2_prg_state, (uint8_t*)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenges[i].alpha = tmp_alpha; - } -} - -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature) { - memcpy(sb, signature->salt, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(sb, signature->h1, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(sb, signature->h2, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(sb, signature->responses[i].cmt_1_alpha, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(sb, signature->responses[i].z2_theta, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = signature->responses[i / PARAM_N1].z1[i % PARAM_N1]; - store_10bit_in_bytearray(sb, i, z1); - } - sb += (PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8; - - // compress and store permutations - sig_perk_signature_perm_to_bytes(sb, signature); -} - -#define Z1_USED_BITS (uint8_t)((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) % 8 + 1) -static const uint8_t z1_unused_mask = (uint8_t)(((1U << (Z1_USED_BITS)) - 1) ^ 0xFFU); - -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]) { - memcpy(signature->salt, sb, sizeof(salt_t)); - sb += sizeof(salt_t); - memcpy(signature->h1, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - memcpy(signature->h2, sb, sizeof(digest_t)); - sb += sizeof(digest_t); - - for (int i = 0; i < PARAM_TAU; i++) { - memcpy(signature->responses[i].cmt_1_alpha, sb, sizeof(cmt_t)); - sb += sizeof(cmt_t); - memcpy(signature->responses[i].z2_theta, sb, sizeof(theta_t) * THETA_TREE_LEVELS); - sb += sizeof(theta_t) * THETA_TREE_LEVELS; - } - - for (int i = 0; i < PARAM_TAU * PARAM_N1; i++) { - uint16_t z1 = load_10bit_from_bytearray(sb, i); - if (z1 >= PARAM_Q) { - // z1 out of range - return EXIT_FAILURE; - } - signature->responses[i / PARAM_N1].z1[i % PARAM_N1] = z1; - } - sb += ((PARAM_TAU * PARAM_N1 * PARAM_Q_BITS + 7) / 8) - 1; - - // cppcheck-suppress knownConditionTrueFalse - // cppcheck-suppress unmatchedSuppression - if (sb[0] & z1_unused_mask) { - // unused bits after the z1 != 0 - return EXIT_FAILURE; - } - - sb += 1; - - // Load and decompress permutations - return sig_perk_signature_perm_from_bytes(signature, sb); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing.c b/crypto_sign/perk-256-short-5/m4/parsing.c new file mode 120000 index 00000000..b727605b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing.h b/crypto_sign/perk-256-short-5/m4/parsing.h deleted file mode 100644 index 35282479..00000000 --- a/crypto_sign/perk-256-short-5/m4/parsing.h +++ /dev/null @@ -1,75 +0,0 @@ - -/** - * @file parsing.h - * @brief Header file for parsing.c - */ - -#ifndef SIG_PERK_PARSING_H -#define SIG_PERK_PARSING_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Parse a private key into a string - * - * As technicality, the public key is appended to the private key in order to respect NIST API. - * - * @param [out] sk_bytes a string containing the private key - * @param [in] sk a pointer to private key structure - */ -void sig_perk_private_key_to_bytes(uint8_t sk_bytes[PRIVATE_KEY_BYTES], const perk_private_key_t* sk); - -/** - * @brief Parse a private key from a string - * - * @param [out] sk a pointer to private key structure - * @param [in] sk_bytes a string containing the private key - */ -void sig_perk_private_key_from_bytes(perk_private_key_t* sk, const uint8_t sk_bytes[PRIVATE_KEY_BYTES]); - -/** - * @brief Parse a public key into a string - * - * @param [out] pk_bytes a string containing the public key - * @param [in] pk a pointer to public key structure - */ -void sig_perk_public_key_to_bytes(uint8_t pk_bytes[PUBLIC_KEY_BYTES], const perk_public_key_t* pk); - -/** - * @brief Parse a public key from a string - * - * @param [out] pk a pointer to public key structure - * @param [in] pk_bytes a string containing the public key - */ -int sig_perk_public_key_from_bytes(perk_public_key_t* pk, const uint8_t pk_bytes[PUBLIC_KEY_BYTES]); - -/** - * @brief Generate challenges based on Fiat-Shamir transform - * - * @param [out] challenges an array containing the challenges for Pall the rounds - * @param [out] h1 a variable containing the digest h1 - * @param [out] h2 a variable containing the digest h2 - */ -void sig_perk_challenges_from_bytes(challenge_t challenges[PARAM_TAU], const digest_t h1, const digest_t h2); - -/** - * @brief Parse a signature into a string - * - * @param [out] sb a string containing the signature - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_to_bytes(uint8_t sb[SIGNATURE_BYTES], const perk_signature_t* signature); - -/** - * @brief Parse a signature from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb a string containing the signature - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_from_bytes(perk_signature_t* signature, const uint8_t sb[SIGNATURE_BYTES]); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing.h b/crypto_sign/perk-256-short-5/m4/parsing.h new file mode 120000 index 00000000..814acaab --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./parsing.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.c b/crypto_sign/perk-256-short-5/m4/parsing_permutations.c deleted file mode 100644 index 6edb9a7e..00000000 --- a/crypto_sign/perk-256-short-5/m4/parsing_permutations.c +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file parsing_permutations.c - * @brief Implementation of parsing functions - */ - -#include "parsing_permutations.h" -#include "parameters.h" - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "rank_unrank_table.h" -#include "symmetric.h" - -#define PARAM_RANK_UNRANK_LEN_T \ - ((1 << (PARAM_RANK_UNRANK_K + 1)) - 1) /**< Length of list used in rank/unrank compression */ - -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff) { - struct bn mul, code, tmp; - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - bignum_init(&code); - for (int i = 0; i < PARAM_N1; ++i) { - uint8_t ctr = in_p[i]; - uint16_t node = (1 << PARAM_RANK_UNRANK_K) + in_p[i]; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - if (node & 0x1) { - ctr -= T[(node >> 1) << 1]; - } - T[node] += 1; - node = node >> 1; - } - T[node] += 1; - bignum_from_int(&tmp, PARAM_N1 - i); - bignum_mul(&code, &tmp, &mul); - bignum_from_int(&tmp, ctr); - bignum_add(&mul, &tmp, &code); - } - - memset(out_buff, 0, PARAM_PERM_COMPRESSION_BYTES); - memcpy(out_buff, &code, PARAM_PERM_COMPRESSION_BYTES); -} - -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p) { - struct bn code, tmp, tmp2, tmp3; - bignum_init(&code); - - memcpy(&code, in_buff, PARAM_PERM_COMPRESSION_BYTES); - - // validate the permutation encoding to be < n! - if (bignum_cmp(&factorial[PARAM_N1], &code) < 1) { - return EXIT_FAILURE; - } - - bignum_mod(&code, &factorial[PARAM_N1], &tmp); - bignum_assign(&tmp3, &tmp); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - 1], &tmp, &tmp2); - out_p[0] = bignum_to_int(&tmp); - - for (int i = 1; i < PARAM_N1 - 1; ++i) { - bignum_assign(&tmp3, &tmp2); - bignum_divmod(&tmp3, &factorial[PARAM_N1 - i - 1], &tmp, &tmp2); - out_p[i] = bignum_to_int(&tmp); - } - - bignum_div(&tmp2, &factorial[0], &tmp); - out_p[PARAM_N1 - 1] = bignum_to_int(&tmp); - - uint8_t T[PARAM_RANK_UNRANK_LEN_T] = {0}; - for (int i = 0; i <= PARAM_RANK_UNRANK_K; ++i) { - for (int j = 0; j < (1 << i); ++j) { - T[((1 << i)) + j - 1] = 1 << (PARAM_RANK_UNRANK_K - i); - } - } - - for (int i = 0; i < PARAM_N1; ++i) { - int digit = out_p[i]; - uint16_t node = 1; - for (int j = 0; j < PARAM_RANK_UNRANK_K; ++j) { - T[node] -= 1; - node <<= 1; - if (digit >= T[node]) { - digit -= T[node]; - node += 1; - } - } - T[node] = 0; - out_p[i] = node - (1 << PARAM_RANK_UNRANK_K); - } - - return EXIT_SUCCESS; -} - -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature) { - for (int i = 0; i < (PARAM_TAU); i++) { - sig_perk_perm_encode(signature->responses[i].z2_pi, sb); - sb += PARAM_PERM_COMPRESSION_BYTES; - } -} - -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb) { - for (int i = 0; i < PARAM_TAU; i++) { - if (sig_perk_perm_decode(sb, signature->responses[i].z2_pi) != EXIT_SUCCESS) { - return EXIT_FAILURE; - } - sb += PARAM_PERM_COMPRESSION_BYTES; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.c b/crypto_sign/perk-256-short-5/m4/parsing_permutations.c new file mode 120000 index 00000000..4227070c --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing_permutations.c @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.h b/crypto_sign/perk-256-short-5/m4/parsing_permutations.h deleted file mode 100644 index 52c64e70..00000000 --- a/crypto_sign/perk-256-short-5/m4/parsing_permutations.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file parsing_permutations.h - * @brief Header file for parsing_permutations.c - */ - -#ifndef SIG_PERK_PARSING_PERMUTATIONS_H -#define SIG_PERK_PARSING_PERMUTATIONS_H - -#include -#include "data_structures.h" -#include "parameters.h" -#include "signature.h" - -/** - * @brief Permutation rank encoding. Encode a permutation into a bytearray. - * - * @param in_p input permutation - * @param out_buff output buffer byte string - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -void sig_perk_perm_encode(const perm_t in_p, uint8_t* out_buff); - -/** - * @brief Permutation unrank decoding. Decode a bytearray into a permutation. - * - * @param in_buff input buffer byte string - * @param out_p output permutation - * @return EXIT_SUCCESS or EXIT_FAILURE - */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -__attribute__((no_sanitize("memory"))) -#endif -#if __has_feature(address_sanitizer) -__attribute__((no_sanitize("address"))) -#endif -#endif -int sig_perk_perm_decode(const uint8_t* in_buff, perm_t out_p); - -/** - * @brief Parse the permutations into a string - * - * @param [out] sb output string - * @param [in] signature a pointer to signature structure - */ -void sig_perk_signature_perm_to_bytes(uint8_t* sb, const perk_signature_t* signature); - -/** - * @brief Parse the permutations from a string - * - * @param [out] signature a pointer to signature structure - * @param [in] sb input string containing the permutations - * @return int 0 if the parsing is successful and 1 otherwise - */ -int sig_perk_signature_perm_from_bytes(perk_signature_t* signature, const uint8_t* sb); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/parsing_permutations.h b/crypto_sign/perk-256-short-5/m4/parsing_permutations.h new file mode 120000 index 00000000..f78f116d --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/parsing_permutations.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./parsing_permutations.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.c b/crypto_sign/perk-256-short-5/m4/permutation.c deleted file mode 100644 index 09df4c2e..00000000 --- a/crypto_sign/perk-256-short-5/m4/permutation.c +++ /dev/null @@ -1,91 +0,0 @@ - -/** - * @file permutation.c - * @brief Implementation of permutation related functions. - * - * This implementation uses memory table lookup - * and is constant time only for CPU without RAM cache like Arm M4 CPUs - */ - -#include "permutation.h" -#include -#include "crypto_memset.h" -#include "djbsort.h" -#include "symmetric.h" - -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]) { - uint32_t buffer[PARAM_N1]; - // Use 16 bits for randomness - for (int i = 0; i < PARAM_N1; i++) { - buffer[i] = (((uint32_t)rnd_buff[i]) << 16) | i; - } - // sort - uint32_sort(buffer, PARAM_N1); - // check that no double random values were produced - for (int i = 1; i < PARAM_N1; i++) { - if ((buffer[i - 1] >> 16) == (buffer[i] >> 16)) { - return EXIT_FAILURE; - } - } - // extract permutation from buffer - for (int i = 0; i < PARAM_N1; i++) { - p[i] = (uint16_t)(buffer[i]); - } - return EXIT_SUCCESS; -} - -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]) { - uint16_t rnd_buff[PARAM_N1]; - sig_perk_prg_state_t prg; - sig_perk_prg_init(&prg, PRG1, NULL, seed); - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - - while (sig_perk_perm_gen_given_random_input(p, rnd_buff) != EXIT_SUCCESS) { - sig_perk_prg(&prg, (uint8_t *)rnd_buff, sizeof(rnd_buff)); - } - memset(rnd_buff, 0, sizeof(rnd_buff)); -} - -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input) { - vect1_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = input[i]; - } - memcpy(output, buffer, sizeof(vect1_t)); -} - -void sig_perk_perm_inverse(perm_t o, const perm_t p) { - perm_t buffer; - for (int i = 0; i < PARAM_N1; i++) { - buffer[p[i]] = i; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2) { - perm_t buffer = {0}; - for (size_t i = 0; i < PARAM_N1; i++) { - buffer[i] = p1[p2[i]]; - } - memcpy(o, buffer, sizeof(perm_t)); -} - -// compute p1 compose p2^-1 -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2) { - uint32_t buffer[PARAM_N1]; - for (int i = 0; i < PARAM_N1; ++i) { - buffer[i] = (((uint32_t)p2[i]) << 16) | p1[i]; - } - uint32_sort(buffer, PARAM_N1); - for (int i = 0; i < PARAM_N1; ++i) { - o[i] = (uint16_t)(buffer[i]); - } -} - -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi) { - sig_perk_perm_inverse(pi_i[0], pi_i[1]); - for (int i = 2; i < PARAM_N; i++) { - sig_perk_perm_compose_inv(pi_i[0], pi_i[0], pi_i[i]); - } - sig_perk_perm_compose(pi_i[0], pi_i[0], pi); -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.c b/crypto_sign/perk-256-short-5/m4/permutation.c new file mode 120000 index 00000000..a9c11fdc --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/permutation.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.h b/crypto_sign/perk-256-short-5/m4/permutation.h deleted file mode 100644 index 0f8e253b..00000000 --- a/crypto_sign/perk-256-short-5/m4/permutation.h +++ /dev/null @@ -1,111 +0,0 @@ - -/** - * @file permutation.h - * @brief header file for permutation.c - */ - -#ifndef SIG_PERK_PERMUTATION_H -#define SIG_PERK_PERMUTATION_H - -#include -#include "arithmetic.h" -#include "parameters.h" - -/** - * @brief Permutation perm_t - * - * This structure contains an array of integers that is a permutation - */ -typedef uint8_t perm_t[PARAM_N1]; - -/** - * @brief Set permutation to zero - * - * @param [out,in] input_perm a permutation - */ -void sig_perk_perm_set_zero(perm_t input_perm); - -/** - * @brief Generate a random permutation form a seed - * - * @param [out] p a permutation - * @param [in] seed a string containing a seed - */ -void sig_perk_perm_set_random(perm_t p, const uint8_t seed[SEED_BYTES]); - -/** - * @brief Generate a random permutation form random values - * - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input(perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Generate a random permutation form random values and compose - * - * @param [out,in] pi_comp a permutation to be composed - * @param [out] p a permutation - * @param [in] rnd_buff an array containing random values - */ -int sig_perk_perm_gen_given_random_input_and_compose(perm_t pi_comp, perm_t p, const uint16_t rnd_buff[PARAM_N1]); - -/** - * @brief Apply a permutation on a vector - * - * @param [out] output a permuted vector - * @param [in] p a permutation - * @param [in] input a vector - */ -void sig_perk_perm_vect_permute(vect1_t output, const perm_t p, const vect1_t input); - -/** - * @brief Compute the composition on two permutations - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the composition p1 compose p2^-1 - * - * o = p1(p2) - * - * @param [out] o a permutation - * @param [in] p1 a permutation - * @param [in] p2 a permutation - */ -void sig_perk_perm_compose_inv(perm_t o, const perm_t p1, const perm_t p2); - -/** - * @brief Compute the inverse of a permutation - * - * o = p1^(-1) - * - * @param [out] o a permutation - * @param [in] p a permutation - */ -void sig_perk_perm_inverse(perm_t o, const perm_t p); - -/** - * @brief Compute the composition of given permutations - * - * @param [out] o a permutation - * @param [in] pi_i a pointer to permutations - * @param [in] nb_permutations an integer that is the number of permutations to be composed - */ -void sig_perk_perm_compose_set(perm_t o, perm_t *pi_i, const int nb_permutations); - -/** - * @brief Compute the permutation pi_1 - * - * @param [out,in] pi_i a pointer to permutations - * @param [in] pi the secret permutation pi in the scheme - */ -void sig_perk_perm_gen_pi_1(perm_t *pi_i, const perm_t pi); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/permutation.h b/crypto_sign/perk-256-short-5/m4/permutation.h new file mode 120000 index 00000000..84b81467 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/permutation.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./permutation.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h deleted file mode 100644 index c530d04f..00000000 --- a/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file rank_unrank_table.h - * @brief Look-up table used in rank/unrank compression. - * For the GMP version, the encoding is in base-62 - * For tiny-bignum, the setting is for 32 bit architectures - * - * Each i-th value is i! encoded in base-62. - * - */ - -#ifndef SIG_PKP_RANK_UNRANK_TABLE_H -#define SIG_PKP_RANK_UNRANK_TABLE_H - -#include "bn.h" - -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} - -}; - -#endif // SIG_PKP_RANK_UNRANK_TABLE_H diff --git a/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h b/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h new file mode 120000 index 00000000..0466ec6b --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/rank_unrank_table.h @@ -0,0 +1 @@ +../../perk-128-short-3/m4/./rank_unrank_table.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/sign.c b/crypto_sign/perk-256-short-5/m4/sign.c deleted file mode 100644 index d846c73a..00000000 --- a/crypto_sign/perk-256-short-5/m4/sign.c +++ /dev/null @@ -1,119 +0,0 @@ - -/** - * @file sign.c - * @brief Implementation of the NIST api functions - */ - -#include -#include "api.h" -#include "crypto_memset.h" -#include "keygen.h" -#include "parsing.h" -#include "signature.h" -#include "verbose.h" -#include "verify.h" - -/** - * @brief Generate a keypair. - * - * @param [out] pk pointer to public key bytes - * @param [out] sk pointer to public key bytes - * @returns 0 if key generation is successful and -1 otherwise - */ -int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("KEYGEN"); - perk_public_key_t public_key = {0}; - perk_private_key_t private_key = {0}; - - if (sig_perk_generate_keypair(&public_key, &private_key) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - return -1; - } - - sig_perk_public_key_to_bytes(pk, &public_key); - sig_perk_private_key_to_bytes(sk, &private_key); - - memset_zero(&private_key, sizeof(private_key)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("pk", pk, PUBLIC_KEY_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("sk", sk, PRIVATE_KEY_BYTES); - - return 0; -} - -/** - * @brief Generate a signature of a message. - * - * @param [out] sm pointer to output signed message - * (allocated array with CRYPTO_BYTES + mlen bytes), can be equal to m - * @param [out] smlen pointer to output length of signed message - * @param [in] m pointer to message to be signed - * @param [in] mlen length of the message - * @param [in] sk pointer to the secret key bytes - * @returns 0 if signing is successful and -1 otherwise - */ -int crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN"); - perk_private_key_t private_key = {0}; - perk_signature_t signature = {0}; - sig_perk_private_key_from_bytes(&private_key, sk); - - for (size_t i = 0; i < mlen; ++i) sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - - if (sig_perk_sign(&signature, &private_key, sm + CRYPTO_BYTES, (uint64_t)mlen) != EXIT_SUCCESS) { - memset_zero(&private_key, sizeof(private_key)); - memset_zero(&signature, sizeof(signature)); - return -1; - } - - sig_perk_signature_to_bytes(sm, &signature); - memset_zero(&private_key, sizeof(private_key)); - - *smlen = mlen + CRYPTO_BYTES; - - SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, sm); - - return 0; -} - -/** - * @brief Verify a signed message - * - * @param [out] m pointer to output message - * (allocated array with smlen bytes), can be equal to sm - * @param [out] mlen pointer to output length of message - * @param [in] sm pointer to signed message - * @param [in] smlen length of signed message - * @param [in] pk pointer to the public key bytes - * @returns 0 if signed message could be verified correctly and -1 otherwise - */ -int crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { - SIG_PERK_VERBOSE_PRINT_string("SIGN OPEN"); - if (smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - - perk_signature_t signature; - challenge_t challenges[PARAM_TAU] = {0}; - - if (EXIT_SUCCESS != sig_perk_signature_from_bytes(&signature, sm)) { - goto badsig; - } - - sig_perk_challenges_from_bytes(challenges, signature.h1, signature.h2); - - // check the signature - if (EXIT_SUCCESS != sig_perk_verify(&signature, challenges, (uint8_t *)(sm + CRYPTO_BYTES), *mlen, (uint8_t *)pk)) { - goto badsig; - } else { - /* All good, copy msg, return 0 */ - for (size_t i = 0; i < *mlen; ++i) m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - return -1; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/sign.c b/crypto_sign/perk-256-short-5/m4/sign.c new file mode 120000 index 00000000..46365add --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/sign.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sign.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.c b/crypto_sign/perk-256-short-5/m4/signature.c deleted file mode 100644 index f62c4b98..00000000 --- a/crypto_sign/perk-256-short-5/m4/signature.c +++ /dev/null @@ -1,384 +0,0 @@ - -/** - * @file signature.c - * @brief Implementation of sign function - */ - -#include "signature.h" -#include "parameters.h" - -#include -#include -#include "common.h" -#include "crypto_memset.h" -#include "data_structures.h" -#include "parsing.h" -#include "randombytes.h" -#include "symmetric.h" -#include "theta_tree.h" -#include "verbose.h" - -/** - * @brief Generate the commitments TODO: update - * - * @param [out] signature a pointer to a signature structure - * @param [out,in] instances an array of PARAM_TAU instances - * @param [in] pi a variable that containing the permutation pi - * @param [in] H a variable containing the public matrix H - */ -static void sig_perk_gen_commitment(perk_signature_t *signature, sig_perk_hash_state_t *h1_state, - sig_perk_hash_state_t *h2_state, perm_t pi_0[PARAM_TAU], seed_t mseed, - const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, const perm_t pi, - const mat_t H) { - uint8_t rand_bytes[SEED_BYTES + SALT_BYTES] = {0}; - sig_perk_prg_state_t prg_state; - vect1_t v = {0}; - perm_t pi_inv; - - sig_perk_perm_inverse(pi_inv, pi); - - randombytes(rand_bytes, sizeof(rand_bytes)); - memcpy(mseed, rand_bytes, SEED_BYTES); - memcpy(signature->salt, rand_bytes + SEED_BYTES, SALT_BYTES); - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_hash_init(h1_state, signature->salt, NULL, NULL); - sig_perk_hash_update(h1_state, m, mlen); - sig_perk_hash_update(h1_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(h2_state, h1_state, sizeof(sig_perk_hash_state_t)); - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("mseed", mseed, SEED_BYTES); - SIG_PERK_VERBOSE_PRINT_uint8_t_array("salt", signature->salt, SALT_BYTES); - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - perm_t pi_1; - perm_t pi_comp; - cmt_t cmt_1_i; - vect1_t v_i; - perk_theta_seeds_tree_t theta_tree; - - memcpy(pi_1, pi_inv, sizeof(perm_t)); - - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_hash_state_t h_state; - sig_perk_prg_state_t p_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int i = PARAM_N - 1; i > 0; i--) { // i ∈ {N, . . . , 2} - perm_t pi_i; - uint8_t idx = i; - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_pi_i_and_compose(pi_1, pi_i, signature->salt, rnd_buffer_pi_i, &p_state, - theta_tree[THETA_SEEDS_OFFSET + i]); - - if (i == (PARAM_N - 1)) { - memcpy(v, v_i, sizeof(vect1_t)); - memcpy(pi_comp, pi_i, sizeof(perm_t)); - } else { - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - sig_perk_perm_compose(pi_comp, pi_comp, pi_i); - } - } - - sig_perk_perm_inverse(pi_1, pi_1); - /* remove ??? see specification*/ memcpy(pi_0[e], pi_1, sizeof(perm_t)); - - uint8_t idx = 0; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - sig_perk_hash_update(&h_state, pi_1, PARAM_N1); - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + 0], sizeof(theta_t)); - sig_perk_hash_final(&h_state, cmt_1_i, H0); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(v_i, pi_comp, v_i); - sig_perk_vect1_add(v, v, v_i); - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); - - // reuse cmt_1_i for cmt_1 - sig_perk_gen_instance_commitment_cmt_1(cmt_1_i, signature->salt, e, H, v); - sig_perk_hash_update(h1_state, cmt_1_i, sizeof(cmt_t)); - - SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta_tree[0], cmt_1_i, v, e + 1); - } -} - -static void sig_perk_gen_first_challenge_s(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *h1_state, - digest_t h1) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_final(h1_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]) { - sig_perk_hash_state_t hash_state; - sig_perk_prg_state_t prg_state; - uint16_t tmp_kappa; - - sig_perk_hash_init(&hash_state, salt, NULL, NULL); - sig_perk_hash_update(&hash_state, m, mlen); - sig_perk_hash_update(&hash_state, pk_bytes, PUBLIC_KEY_BYTES); - memcpy(saved_state, &hash_state, sizeof(hash_state)); - for (int i = 0; i < PARAM_TAU; ++i) { - // absorb cmt_1_N to cmt_1_1 - // Commitments are stored in reverse order: from element (PARAM_N-1) down to element 0. - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1_i, sizeof(cmt_t) * PARAM_N); - sig_perk_hash_update(&hash_state, (uint8_t *)instances[i].cmt_1, sizeof(cmt_t)); - } - sig_perk_hash_final(&hash_state, h1, H1); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h1); - for (int i = 0; i < PARAM_TAU; ++i) { - uint16_t nonzero_check = 0; - do { - for (int j = 0; j < PARAM_T; ++j) { - do { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_kappa, sizeof(tmp_kappa)); - tmp_kappa = tmp_kappa & PARAM_Q_MASK; - } while (tmp_kappa >= PARAM_Q); // 0 <= tmp_kappa < PARAM_Q - challenge[i].kappa[j] = tmp_kappa; - nonzero_check |= tmp_kappa; - } - } while (!nonzero_check); - } -} - -/** - * @brief Generate the first response - * - * @param [out] instances an array of PARAM_TAU instances - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] x an array of PARAM_T public values x_i - */ -static void sig_perk_gen_first_response(sig_perk_hash_state_t *h2_state, digest_t h1, const perm_t pi_0[PARAM_TAU], - const seed_t mseed, salt_t salt, const challenge_t challenges[PARAM_TAU], - const vect1_t x[PARAM_T]) { - sig_perk_prg_state_t prg_state; - - sig_perk_hash_update(h2_state, h1, sizeof(digest_t)); - - sig_perk_prg_init(&prg_state, PRG1, salt, mseed); - - sig_perk_prg_state_t state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (int e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - - for (int i = 1; i < PARAM_N; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&state, sizeof(sig_perk_prg_state_t)); -} - -static void sig_perk_gen_second_challenge_s(digest_t h2, challenge_t challenge[PARAM_TAU], - sig_perk_hash_state_t *h2_state) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_final(h2_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - uint16_t tmp_alpha; - - sig_perk_hash_update(saved_state, h1, sizeof(digest_t)); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_hash_update(saved_state, (uint8_t *)instances[i].s_i[1], sizeof(vect1_t) * PARAM_N); - } - sig_perk_hash_final(saved_state, h2, H2); - - sig_perk_prg_init(&prg_state, PRG1, NULL, h2); - for (int i = 0; i < PARAM_TAU; ++i) { - sig_perk_prg(&prg_state, (uint8_t *)&tmp_alpha, sizeof(tmp_alpha)); - tmp_alpha = (tmp_alpha & PARAM_N_MASK) + 1; // 0 < tmp_alpha <= PARAM_N - challenge[i].alpha = tmp_alpha; - } -} - -/** - * @brief Generate second response - * - * @param [out] signature a pointer to a signature structure - * @param [in] challenges an array of PARAM_TAU challenges - * @param [in] instances an array of PARAM_TAU instances - */ -static void sig_perk_gen_second_response(perk_signature_t *signature, const seed_t mseed, - const challenge_t challenges[PARAM_TAU], const vect1_t x[PARAM_T], - const perm_t pi_0[PARAM_TAU]) { - sig_perk_prg_state_t prg_state; - - sig_perk_prg_init(&prg_state, PRG1, signature->salt, mseed); - - sig_perk_prg_state_t p_state; - sig_perk_hash_state_t h_state; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - - for (uint8_t e = 0; e < PARAM_TAU; ++e) { - vect1_t tmp; - vect1_t v_i; // TODO: tmp and v_i can share memory?? - vect1_t s_0; - vect1_t s_i; - perk_theta_seeds_tree_t theta_tree; - const uint16_t alpha = challenges[e].alpha; - - // compute s_0 - sig_perk_vect1_mult_scalar_vect(s_0, challenges[e].kappa[0], x[0]); - for (int j = 1; j < PARAM_T; j++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenges[e].kappa[j], x[j]); - sig_perk_vect1_add(s_0, s_0, tmp); - } - - // sample seeds - sig_perk_prg(&prg_state, theta_tree[0], sizeof(theta_t)); - sig_perk_expand_theta_tree(signature->salt, theta_tree); - - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + 0]); - - sig_perk_perm_vect_permute(tmp, pi_0[e], s_0); - sig_perk_vect1_add(s_i, tmp, v_i); - for (int i = 1; i < alpha; ++i) { - perm_t pi_i; - - // sample p_i and v_i - sig_perk_gen_one_pi_i(pi_i, signature->salt, rnd_buffer_pi_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - sig_perk_gen_one_v_i(v_i, signature->salt, rnd_buff_v_i, &p_state, theta_tree[THETA_SEEDS_OFFSET + i]); - - sig_perk_perm_vect_permute(tmp, pi_i, s_i); - sig_perk_vect1_add(s_i, tmp, v_i); - } - memcpy(signature->responses[e].z1, s_i, sizeof(vect1_t)); - - if (alpha != 1) { - memcpy(signature->responses[e].z2_pi, pi_0[e], sizeof(perm_t)); - } else { - for (int j = 0; j < PARAM_N1; j++) { - signature->responses[e].z2_pi[j] = j; - } - } - sig_perk_get_theta_partial_tree_seeds(signature->responses[e].z2_theta, (const theta_t *)theta_tree, alpha - 1); - - uint8_t idx = alpha - 1; - sig_perk_hash_init(&h_state, signature->salt, &e, &idx); - if (alpha == 1) { - sig_perk_hash_update(&h_state, pi_0[e], PARAM_N1); - } - sig_perk_hash_update(&h_state, theta_tree[THETA_SEEDS_OFFSET + idx], sizeof(theta_t)); - sig_perk_hash_final(&h_state, signature->responses[e].cmt_1_alpha, H0); - } - - memset_zero(rnd_buffer_pi_i, sizeof(rnd_buffer_pi_i)); - memset_zero(rnd_buff_v_i, sizeof(rnd_buff_v_i)); - memset_zero(&p_state, sizeof(sig_perk_prg_state_t)); - memset_zero(&h_state, sizeof(sig_perk_hash_state_t)); -} - -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length) { - perk_public_key_t pk; - perm_t pi_0[PARAM_TAU]; - challenge_t challenges[PARAM_TAU] = {0}; - sig_perk_hash_state_t h1_state; - sig_perk_hash_state_t h2_state; // initialized with a copy of h1_state after absorbing salt, m and pk_bytes - seed_t mseed = {0}; - - SIG_PERK_VERBOSE_PRINT_uint8_t_array("message m", message_bytes, message_length); - - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&pk, sk->pk_bytes)) { - return EXIT_FAILURE; - } - - sig_perk_gen_commitment(signature, &h1_state, &h2_state, pi_0, mseed, message_bytes, message_length, sk->pk_bytes, - sk->pi, (const vect1_t *)pk.H); - sig_perk_gen_first_challenge_s(challenges, &h1_state, signature->h1); - sig_perk_gen_first_response(&h2_state, signature->h1, (const perm_t *)pi_0, mseed, signature->salt, challenges, - (const vect1_t *)pk.x); - - sig_perk_gen_second_challenge_s(signature->h2, challenges, &h2_state); - sig_perk_gen_second_response(signature, mseed, challenges, (const vect1_t *)pk.x, (const perm_t *)pi_0); - - SIG_PERK_VERBOSE_PRINT_challenges(challenges); - SIG_PERK_VERBOSE_PRINT_signature(signature); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.c b/crypto_sign/perk-256-short-5/m4/signature.c new file mode 120000 index 00000000..0fe65387 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/signature.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.h b/crypto_sign/perk-256-short-5/m4/signature.h deleted file mode 100644 index 73e69475..00000000 --- a/crypto_sign/perk-256-short-5/m4/signature.h +++ /dev/null @@ -1,64 +0,0 @@ - -/** - * @file signature.h - * @brief Header file for signature.c - */ - -#ifndef SIG_PERK_SIGNATURE_H -#define SIG_PERK_SIGNATURE_H - -#include -#include "data_structures.h" - -/** @struct challenge_t - * @brief This structure contains the challenges of one round of the scheme - * @var challenge_t::kappa - * Member 'kappa' is an array of integers containing challenge kappa[i] with i in 0 .. PARAM_T - 1 - * @var challenge_t::alpha - * Member 'alpha' is an integer containing challenge alpha - */ -typedef struct { - uint16_t kappa[PARAM_T]; - uint16_t alpha; -} challenge_t; - -/** - * @brief Generate challenges kappa for PARAM_TAU rounds - * - * @param [out] challenge an array of PARAM_TAU challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state after absorbing salt, m and pk_bytes - * @param [out] h1 a variable containing the digest h1 - * @param [in] salt a salt - * @param [in] m a pointer to message - * @param [in] mlen length of message - * @param [in] pk_bytes a pointer to the public key bytes - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_first_challenge(challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, digest_t h1, - const salt_t salt, const uint8_t *m, const uint64_t mlen, const uint8_t *pk_bytes, - const perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate h2 and the challenges alpha for tau rounds - * - * @param [out] h2 a variable containing the digest h2 - * @param [out] challenge an array of tau challenge_t struct - * @param [out,in] saved_state a pointer to Keccak state - * @param [out] h1 a variable containing the digest h1 - * @param [in] instances an array of PARAM_TAU instances - */ -void sig_perk_gen_second_challenge(digest_t h2, challenge_t challenge[PARAM_TAU], sig_perk_hash_state_t *saved_state, - const digest_t h1, perk_instance_t instances[PARAM_TAU]); - -/** - * @brief Generate a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] sk a pointer to private key structure - * @param [in] message_bytes a string containing a message - * @param [in] message_length an integer containing the length of the message - */ -uint8_t sig_perk_sign(perk_signature_t *signature, const perk_private_key_t *sk, const uint8_t *message_bytes, - const uint64_t message_length); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/signature.h b/crypto_sign/perk-256-short-5/m4/signature.h new file mode 120000 index 00000000..58d30e08 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/signature.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./signature.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/sort.c b/crypto_sign/perk-256-short-5/m4/sort.c deleted file mode 100644 index 5a335826..00000000 --- a/crypto_sign/perk-256-short-5/m4/sort.c +++ /dev/null @@ -1,128 +0,0 @@ -// crypto_sort aka djbsort. -// copied from supercop-20231107/crypto_sort/int32/portable4 -// Optimized for Cortex-M4 by Décio Luiz Gazzoni Filho (decio.gazzoni@ic.unicamp.br, dgazzoni@uel.br) - -#include - -#include "djbsort.h" - -// -inline assembly using conditional execution -// -reduce instruction count by optimizing loads and stores, reducing temporaries -#define int32_MINMAX_M_M(x, offset1, offset2) \ - do \ - { \ - int32_t a, b; /* temporaries */ \ - asm volatile( \ - "ldr %0, [%4, %5, lsl #2]\n" \ - "ldr %1, [%4, %6, lsl #2]\n" \ - "cmp %0, %1 \n" \ - "itt gt \n" \ - "strgt %1, [%4, %5, lsl #2]\n" \ - "strgt %0, [%4, %6, lsl #2]\n" \ - : "=&r"(a), "=&r"(b), "=m"(x[offset1]), "=m"(x[offset2]) \ - : "r"(x), "r"(offset1), "r"(offset2) \ - : "cc"); \ - } while (0) - -#define int32_MINMAX_V_M(a, x, offset) \ - do \ - { \ - int32_t b; /* temporary */ \ - asm( \ - "ldr %1, [%3, %4, lsl #2]\n" \ - "cmp %0, %1\n" \ - "itt gt \n" \ - "strgt %0, [%3, %4, lsl #2]\n" \ - "movgt %0, %1\n" \ - : "+&r"(a), "=&r"(b), "=m"(x[offset]) \ - : "r"(x), "r"(offset) \ - : "cc"); \ - } while (0) - -// -replace long long by size_t -void int32_sort(int32_t *x, size_t n) -{ - size_t top, p, q, r, i, j; - - if (n < 2) - { - return; - } - top = 1; - while (top < n - top) - { - top += top; - } - - for (p = top; p >= 1; p >>= 1) - { - i = 0; - while (i + 2 * p <= n) - { - for (j = i; j < i + p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - i += 2 * p; - } - for (j = i; j < n - p; ++j) - { - int32_MINMAX_M_M(x, j, j + p); - } - - i = 0; - j = 0; - for (q = top; q > p; q >>= 1) - { - if (j != i) - { - for (;;) - { - if (j == n - q) - { - goto done; - } - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - if (j == i + p) - { - i += 2 * p; - break; - } - } - } - while (i + p <= n - q) - { - for (j = i; j < i + p; ++j) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - } - i += 2 * p; - } - /* now i + p > n - q */ - j = i; - while (j < n - q) - { - int32_t a = x[j + p]; - for (r = q; r > p; r >>= 1) - { - int32_MINMAX_V_M(a, x, j + r); - } - x[j + p] = a; - ++j; - } - - done:; - } - } -} diff --git a/crypto_sign/perk-256-short-5/m4/sort.c b/crypto_sign/perk-256-short-5/m4/sort.c new file mode 120000 index 00000000..c03708c1 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/sort.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./sort.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.c b/crypto_sign/perk-256-short-5/m4/symmetric.c deleted file mode 100644 index 8676221d..00000000 --- a/crypto_sign/perk-256-short-5/m4/symmetric.c +++ /dev/null @@ -1,51 +0,0 @@ - -/** - * @file symmetric.c - * @brief Implementation of the symmetric functions - */ - -#include "symmetric.h" - -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed) { - Keccak_HashInitialize_SHAKE(state); - if (salt != NULL) { - Keccak_HashUpdate_SHAKE(state, salt, sizeof(salt_t)); - } - if (seed != NULL) { - Keccak_HashUpdate_SHAKE(state, seed, sizeof(seed_t)); - } - Keccak_HashUpdate_SHAKE(state, &domain, 1); - Keccak_HashFinal_SHAKE(state); -} - -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen) { - Keccak_HashSqueeze_SHAKE(state, output, outlen); -} - -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n) { - Keccak_HashInitialize_SHA3(state); - Keccak_HashUpdate_SHA3(state, salt, sizeof(salt_t)); - - uint8_t counters[2]; - int j = 0; - if (tau != NULL) { - counters[j] = *tau; - j++; - } - if (n != NULL) { - counters[j] = *n; - j++; - } - if (j != 0) { - Keccak_HashUpdate_SHA3(state, counters, j); - } -} - -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size) { - Keccak_HashUpdate_SHA3(state, message, message_size); -} - -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain) { - Keccak_HashUpdate_SHA3(state, &domain, 1); - Keccak_HashFinal_SHA3(state, digest); -} diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.c b/crypto_sign/perk-256-short-5/m4/symmetric.c new file mode 120000 index 00000000..5642eb3f --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/symmetric.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.h b/crypto_sign/perk-256-short-5/m4/symmetric.h deleted file mode 100644 index 6bbf109a..00000000 --- a/crypto_sign/perk-256-short-5/m4/symmetric.h +++ /dev/null @@ -1,135 +0,0 @@ - -/** - * @file symmetric.h - * @brief Header file for symmetric.c - */ - -#ifndef SIG_PERK_SYMMETRIC_H -#define SIG_PERK_SYMMETRIC_H - -#include -#include "fips202.h" -#include "parameters.h" - -// domains for hash and prg -#define H0 0x00 -#define H1 0x01 -#define H2 0x02 -#define H3 0x03 -#define PRG1 0x04 -#define PRG2 0x05 - -/** - * @brief Salt salt_t - * - * This structure contains the salt - */ -typedef uint8_t salt_t[SALT_BYTES]; - -/** - * @brief Digest digest_t - * - * This structure contains the digest - */ -typedef uint8_t digest_t[HASH_BYTES]; - -/** - * @brief Seed seed_t - * - * This structure defines a string containing SEED_BYTES bytes - */ -typedef uint8_t seed_t[SEED_BYTES]; - -#if (SECURITY_BYTES == 16) -#define PRNG_BLOCK_SIZE 168 // SHAKE128 Block Size -#elif (SECURITY_BYTES == 24) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#elif (SECURITY_BYTES == 32) -#define PRNG_BLOCK_SIZE 136 // SHAKE256 Block Size -#endif - -#if (SECURITY_BYTES == 16) -#define Keccak_HashInitialize_SHAKE(state) shake128_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake128_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake128_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake128_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_256_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_256_inc_finalize(digest, state) - -typedef shake128incctx sig_perk_prg_state_t; -typedef sha3_256incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 24) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_384_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_384_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_384_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_384incctx sig_perk_hash_state_t; -#elif (SECURITY_BYTES == 32) -#define Keccak_HashInitialize_SHAKE(state) shake256_inc_init(state) -#define Keccak_HashUpdate_SHAKE(state, input, inlen) shake256_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHAKE(state) shake256_inc_finalize(state) -#define Keccak_HashSqueeze_SHAKE(state, output, outlen) shake256_inc_squeeze(output, outlen, state) -#define Keccak_HashInitialize_SHA3(state) sha3_512_inc_init(state) -#define Keccak_HashUpdate_SHA3(state, input, inlen) sha3_512_inc_absorb(state, input, inlen) -#define Keccak_HashFinal_SHA3(state, digest) sha3_512_inc_finalize(digest, state) - -typedef shake256incctx sig_perk_prg_state_t; -typedef sha3_512incctx sig_perk_hash_state_t; -#endif - -/** - * @brief Initialize a PRNG - * absorb the salt if not NULL and seed - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [in] domain a byte that is the domain separator. - * @param [in] salt a string containing the salt. If Null no salt is absorbed. - * @param [in] seed a string containing the seed. If Null no seed is absorbed. - */ -void sig_perk_prg_init(sig_perk_prg_state_t *state, const uint8_t domain, const salt_t salt, const seed_t seed); - -/** - * @brief PRNG - * - * @param [out,in] state a pointer to the state of the PRNG - * @param [out] output pinter to the buffer to be filled - * @param [in] outlen size of the output - */ -void sig_perk_prg(sig_perk_prg_state_t *state, uint8_t *output, size_t outlen); - -/** - * @brief initialize the HASH function - * absorb the salt and ctr if != 0 - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] salt a string containing the salt. - * @param [in] tau pointer to uint8_t absorbed after the salt. If NULL tau is not absorbed. - * @param [in] n pointer to uint8_t absorbed after the salt. If NULL n is not absorbed. - */ -void sig_perk_hash_init(sig_perk_hash_state_t *state, const salt_t salt, const uint8_t *tau, const uint8_t *n); - -/** - * @brief HASH update - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [in] message message to be absorbed. - * @param [in] message_size size of the message. - */ -void sig_perk_hash_update(sig_perk_hash_state_t *state, const uint8_t *message, const size_t message_size); - -/** - * @brief output the digest for the chosen hash function (domain) - * - * @param [out,in] state a pointer to the state of the HASH. - * @param [out] digest output digest. - * @param [in] domain domain: H0, H1 or H2. - */ -void sig_perk_hash_final(sig_perk_hash_state_t *state, digest_t digest, const uint8_t domain); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/symmetric.h b/crypto_sign/perk-256-short-5/m4/symmetric.h new file mode 120000 index 00000000..0849c090 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/symmetric.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./symmetric.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.c b/crypto_sign/perk-256-short-5/m4/theta_tree.c deleted file mode 100644 index 2b9a236b..00000000 --- a/crypto_sign/perk-256-short-5/m4/theta_tree.c +++ /dev/null @@ -1,55 +0,0 @@ - -/** - * @file theta_tree.c - * @brief Implementation of tree related functions - */ - -#include "theta_tree.h" -#include -#include "symmetric.h" - -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree) { - sig_perk_hash_state_t state; - - for (unsigned i = 0; i < (PARAM_N - 1); i++) { - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, theta_tree[to], H3); - } -} - -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha) { - sig_perk_hash_state_t state; - for (unsigned i = 0, l = 0, j = 0; i < (PARAM_N - 1); i++, j++) { - unsigned N = (1U << l); - if (j >= N) { // increment level - l++; - j = 0; - } - unsigned from = i; - uint8_t idx = i; - unsigned to = i * 2 + 1; - unsigned missing = (alpha >> (THETA_TREE_LEVELS - l)); // missing node for the level l - unsigned is_right = (~alpha >> (THETA_TREE_LEVELS - 1 - l)) & 1; // position in the level l + 1 - if (j == missing) { - memcpy(partial_theta_tree[to + is_right], partial_tree_seeds[l], sizeof(theta_t)); - } else { - sig_perk_hash_init(&state, salt, &idx, NULL); - sig_perk_hash_update(&state, partial_theta_tree[from], sizeof(theta_t)); - sig_perk_hash_final(&state, partial_theta_tree[to], H3); - } - } -} - -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha) { - for (unsigned i = 0; i < THETA_TREE_LEVELS; i++) { - unsigned level = (1U << (i + 1U)) - 1; - unsigned node = (alpha >> (THETA_TREE_LEVELS - 1U - i)) ^ 1U; - memcpy(partial_tree_seeds[i], theta_tree[level + node], sizeof(theta_t)); - } -} diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.c b/crypto_sign/perk-256-short-5/m4/theta_tree.c new file mode 120000 index 00000000..89d98e69 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/theta_tree.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.h b/crypto_sign/perk-256-short-5/m4/theta_tree.h deleted file mode 100644 index 13b66143..00000000 --- a/crypto_sign/perk-256-short-5/m4/theta_tree.h +++ /dev/null @@ -1,65 +0,0 @@ - -/** - * @file theta_tree.h - * @brief Header file for theta_tree.c - */ - -#ifndef SIG_PERK_THETA_TREE_H -#define SIG_PERK_THETA_TREE_H - -#include -#include "parameters.h" -#include "symmetric.h" - -#define MASTER_THETA_SEED_OFFSET 0 -#define THETA_SEEDS_OFFSET (PARAM_N - 1) - -/** - * @brief Theta theta_t - * - * This structure contains a seed of size SEED_BYTES bytes - */ -typedef uint8_t theta_t[SEED_BYTES]; - -/** - * @brief An array of Theta - * - * This structure contains an array of 2 * PARAM_N - 1 theta_t - */ -typedef theta_t perk_theta_seeds_tree_t[2 * PARAM_N - 1]; - -/** - * @brief expands the tree of thetas (nodes and leaves) from theta master seed and salt - * - * @param[in] salt - * @param[in,out] theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * theta_tree[0] is the master seed - * (theta_tree + THETA_SEEDS_OFFSET) is the array of theta_t - */ -void sig_perk_expand_theta_tree(salt_t salt, perk_theta_seeds_tree_t theta_tree); - -/** - * @brief expands the partial tree of thetas (nodes and leaves missing the alpha related ones) - * from the array of THETA_TREE_LEVELS node seeds, salt and alpha - * - * @param[in] salt - * @param[out] partial_theta_tree a perk_theta_seeds_tree_t to be expanded with nodes and leaves - * from the array of partial_tree_seeds - * @param[in] partial_tree_seeds array of seeds (one for each level) - * @param[in] alpha missing leaf - */ -void sig_perk_expand_theta_partial_tree(salt_t salt, perk_theta_seeds_tree_t partial_theta_tree, - const theta_t partial_tree_seeds[THETA_TREE_LEVELS], const uint16_t alpha); - -/** - * @brief returns the THETA_TREE_LEVELS seeds needed to compute all thetas but the alpha ones - * given perk_theta_seeds_tree_t and alpha - * - * @param[out] partial_tree_seeds array of seeds needed to rebuild the tree with the missing alpha leaf - * @param[in] theta_tree a complete perk_theta_seeds_tree_t - * @param[in] alpha missing leaf - */ -void sig_perk_get_theta_partial_tree_seeds(theta_t partial_tree_seeds[THETA_TREE_LEVELS], - const perk_theta_seeds_tree_t theta_tree, const uint16_t alpha); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/theta_tree.h b/crypto_sign/perk-256-short-5/m4/theta_tree.h new file mode 120000 index 00000000..d8dbb732 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/theta_tree.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./theta_tree.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.c b/crypto_sign/perk-256-short-5/m4/verbose.c deleted file mode 100644 index 777e7f74..00000000 --- a/crypto_sign/perk-256-short-5/m4/verbose.c +++ /dev/null @@ -1,131 +0,0 @@ - -/** - * @file verbose.c - * @brief Implementation of function for printing intermediate values (VERBOSE mode) - */ - -#include "verbose.h" -#include -#include "api.h" -#include "parameters.h" - -void sig_perk_verbose_print_string(const char *var) { - printf("\n\n\n\n### %s ###", var); -} - -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%02x", input[i]); - } -} - -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size) { - printf("\n\n%s: ", var); - for (uint16_t i = 0; i < size; i++) { - printf("%d ", input[i]); - } -} - -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]) { - printf("\n\nx\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" x_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_N1; j++) { - printf("%03d ", x[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]) { - printf("\n\ny\n"); - for (int i = 0; i < PARAM_T; ++i) { - printf(" y_%d: ", i + 1); - for (uint16_t j = 0; j < PARAM_M; j++) { - printf("%03d ", y[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_matrix(const mat_t m_input) { - printf("\n\nH: \n"); - for (int i = 0; i < PARAM_M; i++) { - printf(" "); - for (int j = 0; j < PARAM_N1; j++) { - printf("%03d ", m_input[i][j]); - } - printf("\n"); - } -} - -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number) { - printf("\n\n Round %02d: ", round_number); - printf("\n theta: "); - for (int i = 0; i < SEED_BYTES; ++i) { - printf("%02x", theta[i]); - } - printf("\n cmt_1: "); - for (uint16_t i = 0; i < sizeof(cmt_t); i++) { - printf("%02x", ((uint8_t *)input)[i]); - } - printf("\n v: "); - for (uint16_t i = 0; i < PARAM_N1; i++) { - printf("%d ", v[i]); - } -} - -void sig_perk_verbose_print_challenges(challenge_t *challenges) { - printf("\n\nchallenges: "); - printf("\n\n kappa: "); - for (int i = 0; i < PARAM_TAU; i++) { - printf("\n kappa_i (round %02d): ", i + 1); - for (int j = 0; j < PARAM_T; ++j) { - printf("%03d ", challenges[i].kappa[j]); - } - } - printf("\n\n alpha: "); - for (int i = 0; i < PARAM_TAU; i++) printf("%d ", challenges[i].alpha); -} - -void sig_perk_verbose_print_signature(const perk_signature_t *signature) { - printf("\n\nsignature: "); - sig_perk_verbose_print_uint8_t_array(" h1", signature->h1, sizeof(digest_t)); - sig_perk_verbose_print_uint8_t_array(" h2", signature->h2, sizeof(digest_t)); - printf("\n\n responses"); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n\n response round %d", i + 1); - sig_perk_verbose_print_uint16_t_array(" z1", signature->responses[i].z1, PARAM_N1); - sig_perk_verbose_print_uint8_t_array(" z2_pi", signature->responses[i].z2_pi, PARAM_N1); - printf("\n\n z2_theta"); - for (int j = 0; j < THETA_TREE_LEVELS; ++j) { - printf("\n z2_theta seed # %d: ", j + 1); - for (int k = 0; k < SEED_BYTES; ++k) { - printf("%02x", signature->responses[i].z2_theta[j][k]); - } - } - sig_perk_verbose_print_uint8_t_array(" cmt_1_alpha", signature->responses[i].cmt_1_alpha, COMMITMENT_BYTES); - } -} - -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature) { - sig_perk_verbose_print_uint8_t_array("m", m, mlen); - printf("\n\nsm(CRYPTO_BYTES):"); - for (uint16_t i = 0; i < CRYPTO_BYTES; ++i) { - if (i % 32 == 0) - printf("\n"); - printf("%02x", signature[i]); - } - printf("\n\n"); -} - -void sig_perk_verbose_print_thetas(perk_instance_t *instances) { - printf("\n\nthetas: "); - for (int i = 0; i < PARAM_TAU; ++i) { - printf("\n theta round %02d: ", i + 1); - for (int j = 0; j < SEED_BYTES; ++j) { - printf("%02x", instances[i].theta_tree[0][j]); - } - } -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.c b/crypto_sign/perk-256-short-5/m4/verbose.c new file mode 120000 index 00000000..7de22141 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verbose.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.h b/crypto_sign/perk-256-short-5/m4/verbose.h deleted file mode 100644 index ecd8f8e2..00000000 --- a/crypto_sign/perk-256-short-5/m4/verbose.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file verbose.h - * @brief Header file verbose.c - */ - -#ifndef SIG_PERK_VERBOSE_H -#define SIG_PERK_VERBOSE_H - -#include -#include "arithmetic.h" -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Print a string - * - * @param [in] var a string containing the characters to print - */ -void sig_perk_verbose_print_string(const char *var); - -/** - * @brief Print in hexadecimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint8_t_array(const char *var, const uint8_t *input, uint16_t size); - -/** - * @brief Print in decimal format a given number of bytes - * - * @param [in] var a string containing the name of the variable to be printed - * @param [in] input a string containing the data to be printed - * @param [in] size an integer that is the number of bytes to be printed - */ -void sig_perk_verbose_print_uint16_t_array(const char *var, const uint16_t *input, uint16_t size); - -/** - * @brief Print the public key x_i - * - * @param [in] x an array of vectors vect2_t x_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_x(const vect1_t x[PARAM_T]); - -/** - * @brief Print the public key y_i - * - * @param [in] y an array of vectors vect2_t y_i with i in 0 .. PARAM_T - 1 - */ -void sig_perk_verbose_print_y(const vect2_t y[PARAM_T]); - -/** - * @brief Print the values of the matrix H - * - * @param [in] m_input a matrix - */ -void sig_perk_verbose_print_matrix(const mat_t m_input); - -/** - * @brief Print the root randomness theta, commitment cmt_1 and vector v - * - * @param [in] theta a variable containing the seed theta - * @param [in] input a commitment - * @param [in] v a vector - * @param [in] round_number an integer containing the round number - */ -void sig_perk_verbose_print_theta_cmt_1_and_v(theta_t theta, cmt_t input, vect1_t v, uint16_t round_number); - -/** - * @brief Print the challenges - * - * @param [in] challenges a pointer to the challenges - */ -void sig_perk_verbose_print_challenges(challenge_t *challenges); - -/** - * @brief Print the signature - * - * @param [in] signature a pointer to the signature - */ -void sig_perk_verbose_print_signature(const perk_signature_t *signature); - -/** - * @brief Print the seeds thetas in all rounds - * - * @param [in] instances a pointer to the instances of the signature - */ -void sig_perk_verbose_print_thetas(perk_instance_t *instances); - -/** - * @brief Print a message and a signature - * - * @param [in] m a string containing a message - * @param [in] mlen an integer that is the size of a message - * @param [in] signature a string containing a signature - */ -void sig_perk_verbose_print_signature_raw(const uint8_t *m, uint64_t mlen, const uint8_t *signature); - -#ifdef VERBOSE -#define SIG_PERK_VERBOSE_PRINT_string(var) sig_perk_verbose_print_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) sig_perk_verbose_print_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) sig_perk_verbose_print_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) sig_perk_verbose_print_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) sig_perk_verbose_print_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) sig_perk_verbose_print_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) \ - sig_perk_verbose_print_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) sig_perk_verbose_print_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) sig_perk_verbose_print_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) sig_perk_verbose_print_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) \ - sig_perk_verbose_print_signature_raw(m, mlen, signature) -#else -#define SIG_PERK_VERBOSE_PRINT_string(var) -#define SIG_PERK_VERBOSE_PRINT_uint8_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_uint16_t_array(var, input, size) -#define SIG_PERK_VERBOSE_PRINT_x(x) -#define SIG_PERK_VERBOSE_PRINT_y(y) -#define SIG_PERK_VERBOSE_PRINT_matrix(m_input) -#define SIG_PERK_VERBOSE_PRINT_theta_cmt_1_and_v(theta, input, v, round_number) -#define SIG_PERK_VERBOSE_PRINT_challenges(challenges) -#define SIG_PERK_VERBOSE_PRINT_signature(signature) -#define SIG_PERK_VERBOSE_PRINT_thetas(instances) -#define SIG_PERK_VERBOSE_PRINT_signature_raw(m, mlen, signature) -#endif - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verbose.h b/crypto_sign/perk-256-short-5/m4/verbose.h new file mode 120000 index 00000000..c3393ae7 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verbose.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verbose.h \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.c b/crypto_sign/perk-256-short-5/m4/verify.c deleted file mode 100644 index e25faa0a..00000000 --- a/crypto_sign/perk-256-short-5/m4/verify.c +++ /dev/null @@ -1,160 +0,0 @@ - -/** - * @file verify.c - * @brief Implementation of verify function - */ - -#include "verify.h" -#include -#include "common.h" -#include "parsing.h" - -static void sig_perk_verify_compute_cmt_1_i(sig_perk_hash_state_t *hash_state, const perk_theta_seeds_tree_t theta_tree, - const perk_response_t *response, const challenge_t challenge, - const uint8_t tau, salt_t salt) { - sig_perk_hash_state_t state; - cmt_t cmt_1_i; - - for (int i = PARAM_N - 1; i >= 0; --i) { - uint8_t idx = i; - if (i == 0 && (0 != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, response->z2_pi, sizeof(perm_t)); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i != 0 && (i != (challenge.alpha - 1))) { - sig_perk_hash_init(&state, salt, &tau, &idx); - sig_perk_hash_update(&state, theta_tree[THETA_SEEDS_OFFSET + i], sizeof(theta_t)); - sig_perk_hash_final(&state, cmt_1_i, H0); - - sig_perk_hash_update(hash_state, cmt_1_i, sizeof(cmt_1_i)); - } - if (i == (challenge.alpha - 1)) { - sig_perk_hash_update(hash_state, response->cmt_1_alpha, sizeof(cmt_t)); - } - } -} - -static void sig_perk_verify_compute_s_i_and_h2(sig_perk_hash_state_t *h2_state, const perk_response_t *response, - const perk_theta_seeds_tree_t theta_tree, const challenge_t challenge, - vect1_t s_0, salt_t salt) { - sig_perk_prg_state_t state; - vect1_t v_i; - vect1_t s_i; - perm_t pi_i; - uint16_t rnd_buffer_pi_i[PARAM_N1]; - uint16_t rnd_buff_v_i[PRNG_BLOCK_SIZE / 2]; - for (int i = 0; i < PARAM_N; ++i) { - if (i != (challenge.alpha - 1)) { - if (i != 0) { // skip the generation of pi_1 - sig_perk_gen_one_pi_i(pi_i, salt, rnd_buffer_pi_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - } else { // fetch pi_1 from z_2 - memcpy(pi_i, response->z2_pi, sizeof(perm_t)); - } - sig_perk_gen_one_v_i(v_i, salt, rnd_buff_v_i, &state, theta_tree[THETA_SEEDS_OFFSET + i]); - for (int j = 0; j < PARAM_N1; ++j) { - s_i[pi_i[j]] = s_0[j]; - } - sig_perk_vect1_add(s_i, s_i, v_i); - memcpy(s_0, s_i, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)s_i, sizeof(vect1_t)); - } - if (i == (challenge.alpha - 1)) { - memcpy(s_0, response->z1, sizeof(vect1_t)); - sig_perk_hash_update(h2_state, (uint8_t *)response->z1, sizeof(vect1_t)); - } - } -} - -static void sig_perk_verify_gen_instance_commitment_cmt(cmt_t cmt_1, const perk_public_key_t *public_key, - const vect1_t s_N, const uint16_t kappa[3], const salt_t salt, - const uint8_t tau) { - vect2_t tmp1, tmp2, tmp3; - sig_perk_hash_state_t state; - - sig_perk_mat_vect_mul(tmp1, public_key->H, s_N); - sig_perk_vect2_mult_scalar_vect(tmp2, kappa[0], public_key->y[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect2_mult_scalar_vect(tmp3, kappa[i], public_key->y[i]); - sig_perk_vect2_add(tmp2, tmp2, tmp3); - } - sig_perk_vect2_sub(tmp1, tmp1, tmp2); - - sig_perk_hash_init(&state, salt, &tau, NULL); - sig_perk_hash_update(&state, (uint8_t *)tmp1, sizeof(tmp1)); - sig_perk_hash_final(&state, cmt_1, H0); -} - -static void sig_perk_verify_generic_h(sig_perk_hash_state_t *hash_state, const salt_t salt, - const uint8_t *message_bytes, const uint64_t message_length, - const uint8_t *pk_bytes) { - sig_perk_hash_init(hash_state, salt, NULL, NULL); - sig_perk_hash_update(hash_state, message_bytes, message_length); - sig_perk_hash_update(hash_state, pk_bytes, PUBLIC_KEY_BYTES); -} - -static void sig_perk_streamlined_verify_compute_s_0(vect1_t s_0, const challenge_t challenge, - const vect1_t x[PARAM_T]) { - vect1_t tmp; - sig_perk_vect1_mult_scalar_vect(s_0, challenge.kappa[0], x[0]); - for (int i = 1; i < PARAM_T; i++) { - sig_perk_vect1_mult_scalar_vect(tmp, challenge.kappa[i], x[i]); - sig_perk_vect1_add(s_0, s_0, tmp); - } -} - -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes) { - perk_public_key_t public_key = {0}; - digest_t h1_prime, h2_prime; - sig_perk_hash_state_t h1_state, h2_state; - sig_perk_verify_generic_h(&h1_state, signature->salt, message_bytes, message_length, pk_bytes); - h2_state = h1_state; - sig_perk_hash_update(&h2_state, signature->h1, sizeof(digest_t)); - - for (int i = 0; i < PARAM_TAU; ++i) { - if (challenge[i].alpha == 1) { - for (int j = 0; j < PARAM_N1; j++) { - if (signature->responses[i].z2_pi[j] != j) { - return EXIT_FAILURE; - } - } - } - } - if (EXIT_SUCCESS != sig_perk_public_key_from_bytes(&public_key, pk_bytes)) { - return EXIT_FAILURE; - } - - for (int i = 0; i < PARAM_TAU; ++i) { - perk_theta_seeds_tree_t theta_tree; - vect1_t s_0; - cmt_t cmt_1 = {0}; // fix cppcheck error - - sig_perk_expand_theta_partial_tree(signature->salt, theta_tree, - (const theta_t *)signature->responses[i].z2_theta, challenge[i].alpha - 1); - sig_perk_verify_compute_cmt_1_i(&h1_state, (const theta_t *)theta_tree, &signature->responses[i], challenge[i], - i, signature->salt); - sig_perk_streamlined_verify_compute_s_0(s_0, challenge[i], (const vect1_t *)public_key.x); - // s_N is stored in s_0 - sig_perk_verify_compute_s_i_and_h2(&h2_state, &signature->responses[i], (const theta_t *)theta_tree, - challenge[i], s_0, signature->salt); - sig_perk_verify_gen_instance_commitment_cmt(cmt_1, &public_key, s_0, challenge[i].kappa, signature->salt, i); - sig_perk_hash_update(&h1_state, cmt_1, sizeof(cmt_t)); - } - - sig_perk_hash_final(&h1_state, h1_prime, H1); - sig_perk_hash_final(&h2_state, h2_prime, H2); - - if (memcmp(h1_prime, signature->h1, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - if (memcmp(h2_prime, signature->h2, sizeof(digest_t))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.c b/crypto_sign/perk-256-short-5/m4/verify.c new file mode 120000 index 00000000..bcba1bbf --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verify.c @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.c \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.h b/crypto_sign/perk-256-short-5/m4/verify.h deleted file mode 100644 index e8c8e2c9..00000000 --- a/crypto_sign/perk-256-short-5/m4/verify.h +++ /dev/null @@ -1,26 +0,0 @@ - -/** - * @file verify.h - * @brief Header file for verify.c - */ - -#ifndef SIG_PERK_VERIFY_H -#define SIG_PERK_VERIFY_H - -#include "data_structures.h" -#include "signature.h" - -/** - * @brief Verify a signature - * - * @param [out] signature a pointer to signature structure - * @param [in] challenge an array containing the challenges - * @param [in] message_bytes a pointer to a string containing the message - * @param [in] message_length an integer that is the size of the message - * @param [in] pk_bytes a string containing the public key - * @return int 0 if the verification is successful and 1 otherwise - */ -int sig_perk_verify(perk_signature_t *signature, const challenge_t challenge[PARAM_TAU], const uint8_t *message_bytes, - const uint64_t message_length, const uint8_t *pk_bytes); - -#endif \ No newline at end of file diff --git a/crypto_sign/perk-256-short-5/m4/verify.h b/crypto_sign/perk-256-short-5/m4/verify.h new file mode 120000 index 00000000..3519b356 --- /dev/null +++ b/crypto_sign/perk-256-short-5/m4/verify.h @@ -0,0 +1 @@ +../../perk-128-fast-3/m4/./verify.h \ No newline at end of file From 1fa2eacb39ddd2c3e501dda3301f8e70a58e6469 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Mon, 8 Jan 2024 00:04:19 +0100 Subject: [PATCH 052/107] Add perk to skiplist and update mupq --- mupq | 2 +- skiplist.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 4ba92e08..24aa4d81 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 4ba92e08551453e89df2e870d631475c6b7506bb +Subproject commit 24aa4d8151fdb7492620e9e98ef415d073c49717 diff --git a/skiplist.py b/skiplist.py index ab9c9990..d8fdf45b 100644 --- a/skiplist.py +++ b/skiplist.py @@ -225,4 +225,28 @@ {'scheme': 'cross-sha3-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, {'scheme': 'cross-sha3-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, {'scheme': 'cross-sha3-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'perk-128-fast-3', 'implementation': 'm4', 'estmemory': 33792}, + {'scheme': 'perk-128-fast-3', 'implementation': 'ref', 'estmemory': 323584}, + {'scheme': 'perk-128-fast-5', 'implementation': 'm4', 'estmemory': 34816}, + {'scheme': 'perk-128-fast-5', 'implementation': 'ref', 'estmemory': 315392}, + {'scheme': 'perk-128-short-3', 'implementation': 'm4', 'estmemory': 37888}, + {'scheme': 'perk-128-short-3', 'implementation': 'ref', 'estmemory': 1570816}, + {'scheme': 'perk-128-short-5', 'implementation': 'm4', 'estmemory': 37888}, + {'scheme': 'perk-128-short-5', 'implementation': 'ref', 'estmemory': 1472512}, + {'scheme': 'perk-192-fast-3', 'implementation': 'm4', 'estmemory': 68608}, + {'scheme': 'perk-192-fast-3', 'implementation': 'ref', 'estmemory': 707584}, + {'scheme': 'perk-192-fast-5', 'implementation': 'm4', 'estmemory': 68608}, + {'scheme': 'perk-192-fast-5', 'implementation': 'ref', 'estmemory': 681984}, + {'scheme': 'perk-192-short-3', 'implementation': 'm4', 'estmemory': 69632}, + {'scheme': 'perk-192-short-3', 'implementation': 'ref', 'estmemory': 3487744}, + {'scheme': 'perk-192-short-5', 'implementation': 'm4', 'estmemory': 69632}, + {'scheme': 'perk-192-short-5', 'implementation': 'ref', 'estmemory': 3240960}, + {'scheme': 'perk-256-fast-3', 'implementation': 'm4', 'estmemory': 115712}, + {'scheme': 'perk-256-fast-3', 'implementation': 'ref', 'estmemory': 1226752}, + {'scheme': 'perk-256-fast-5', 'implementation': 'm4', 'estmemory': 114688}, + {'scheme': 'perk-256-fast-5', 'implementation': 'ref', 'estmemory': 1175552}, + {'scheme': 'perk-256-short-3', 'implementation': 'm4', 'estmemory': 111616}, + {'scheme': 'perk-256-short-3', 'implementation': 'ref', 'estmemory': 4222976}, + {'scheme': 'perk-256-short-5', 'implementation': 'm4', 'estmemory': 109568}, + {'scheme': 'perk-256-short-5', 'implementation': 'ref', 'estmemory': 4221952}, ] From 759389b8ceed4709ebbe3b556ae511e8b62e9657 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Mon, 8 Jan 2024 00:21:31 +0100 Subject: [PATCH 053/107] Add HAETAE to skiplist and update mupq --- skiplist.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/skiplist.py b/skiplist.py index d8fdf45b..205e3eb6 100644 --- a/skiplist.py +++ b/skiplist.py @@ -249,4 +249,10 @@ {'scheme': 'perk-256-short-3', 'implementation': 'ref', 'estmemory': 4222976}, {'scheme': 'perk-256-short-5', 'implementation': 'm4', 'estmemory': 109568}, {'scheme': 'perk-256-short-5', 'implementation': 'ref', 'estmemory': 4221952}, + {'scheme': 'haetae2', 'implementation': 'ref', 'estmemory': 59392}, + {'scheme': 'haetae5', 'implementation': 'ref', 'estmemory': 109568}, + {'scheme': 'haetae3', 'implementation': 'ref', 'estmemory': 88064}, + {'scheme': 'haetae2', 'implementation': 'm4f', 'estmemory': 60416}, + {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, + {'scheme': 'haetae3', 'implementation': 'm4f', 'estmemory': 90112}, ] From c3dbd50b7278cf30ac23983d341197c63167fe55 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 11 Jan 2024 11:14:04 +0100 Subject: [PATCH 054/107] add skiplist entries for mqom --- mupq | 2 +- skiplist.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index ae54f549..439dd7b6 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit ae54f5494eb44a1414227f4cccb8802ca74992f5 +Subproject commit 439dd7b65ef6b56a94586fb45d8ecf6d78c59adb diff --git a/skiplist.py b/skiplist.py index 205e3eb6..0f3675dd 100644 --- a/skiplist.py +++ b/skiplist.py @@ -255,4 +255,14 @@ {'scheme': 'haetae2', 'implementation': 'm4f', 'estmemory': 60416}, {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, {'scheme': 'haetae3', 'implementation': 'm4f', 'estmemory': 90112}, + {'scheme': 'mqom_cat5_gf251_short', 'implementation': 'ref', 'estmemory': 4146176}, + {'scheme': 'mqom_cat3_gf251_fast', 'implementation': 'ref', 'estmemory': 1307648}, + {'scheme': 'mqom_cat3_gf31_short', 'implementation': 'ref', 'estmemory': 2688000}, + {'scheme': 'mqom_cat1_gf31_fast', 'implementation': 'ref', 'estmemory': 624640}, + {'scheme': 'mqom_cat1_gf251_fast', 'implementation': 'ref', 'estmemory': 411648}, + {'scheme': 'mqom_cat5_gf251_fast', 'implementation': 'ref', 'estmemory': 3260416}, + {'scheme': 'mqom_cat3_gf31_fast', 'implementation': 'ref', 'estmemory': 2171904}, + {'scheme': 'mqom_cat1_gf31_short', 'implementation': 'ref', 'estmemory': 878592}, + {'scheme': 'mqom_cat1_gf251_short', 'implementation': 'ref', 'estmemory': 675840}, + {'scheme': 'mqom_cat3_gf251_short', 'implementation': 'ref', 'estmemory': 1903616}, ] From fbebf44854ac15bbae18e5a64fafc59cff3da507 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Thu, 11 Jan 2024 19:30:42 +0100 Subject: [PATCH 055/107] Remove old perk entries from skiplist Fixes #321 --- skiplist.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/skiplist.py b/skiplist.py index 0f3675dd..c96b5235 100644 --- a/skiplist.py +++ b/skiplist.py @@ -185,14 +185,6 @@ {'scheme': 'hawk512', 'implementation': 'ref', 'estmemory': 17408}, {'scheme': 'hawk1024', 'implementation': 'ref', 'estmemory': 32768}, {'scheme': 'hawk256', 'implementation': 'ref', 'estmemory': 10240}, - {'scheme': 'perk-192-fast-3', 'implementation': 'ref', 'estmemory': 1036288}, - {'scheme': 'perk-192-fast-5', 'implementation': 'ref', 'estmemory': 1001472}, - {'scheme': 'perk-128-fast-5', 'implementation': 'ref', 'estmemory': 463872}, - {'scheme': 'perk-256-fast-5', 'implementation': 'ref', 'estmemory': 1722368}, - {'scheme': 'perk-128-fast-3', 'implementation': 'ref', 'estmemory': 475136}, - {'scheme': 'perk-128-short-5', 'implementation': 'ref', 'estmemory': 2235392}, - {'scheme': 'perk-256-fast-3', 'implementation': 'ref', 'estmemory': 1797120}, - {'scheme': 'perk-128-short-3', 'implementation': 'ref', 'estmemory': 2377728}, {'scheme': 'ascon-sign-128s-simple', 'implementation': 'ref', 'estmemory': 12288}, {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-192s-simple', 'implementation': 'ref', 'estmemory': 22528}, From a34a481d0cf16f5d42fbf4a46bcaa178cd5e76b6 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 12 Jan 2024 15:46:55 +0100 Subject: [PATCH 056/107] add AIMer --- mupq | 2 +- skiplist.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index d20fa210..87c238d6 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit d20fa210d532bc6b5e4778f7aa525e78d85a4295 +Subproject commit 87c238d6611a359d5b952f4fd689add1de827343 diff --git a/skiplist.py b/skiplist.py index ccdb21fa..cb531127 100644 --- a/skiplist.py +++ b/skiplist.py @@ -275,4 +275,11 @@ {'scheme': 'snova-60-10-16-4-ssk', 'implementation': 'ref', 'estmemory': 1953792}, {'scheme': 'snova-37-8-16-4-esk', 'implementation': 'ref', 'estmemory': 775168}, {'scheme': 'snova-37-8-16-4-ssk', 'implementation': 'ref', 'estmemory': 646144}, + {'scheme': 'aimer-l1-param2', 'implementation': 'ref', 'estmemory': 461824}, + {'scheme': 'aimer-l1-param1', 'implementation': 'ref', 'estmemory': 206848}, + {'scheme': 'aimer-l3-param1', 'implementation': 'ref', 'estmemory': 452608}, + {'scheme': 'aimer-l5-param1', 'implementation': 'ref', 'estmemory': 926720}, + {'scheme': 'aimer-l3-param2', 'implementation': 'ref', 'estmemory': 1091584}, + {'scheme': 'aimer-l5-param2', 'implementation': 'ref', 'estmemory': 2169856}, + {'scheme': 'aimer-l1-param3', 'implementation': 'ref', 'estmemory': 1442816}, ] From 57bb7dccd6bd9e89af0bf0629a19b0fa0317087d Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 15 Jan 2024 14:19:53 +0100 Subject: [PATCH 057/107] update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 5a1c0a1a..255b916b 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 5a1c0a1ab1ebc79fab4924adeb6f11c46fdff950 +Subproject commit 255b916b3493a3429417763b6353d1ff29fe3662 From 1c27aa0803e555d6aee411f7bcefcd7833b12383 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 16 Jan 2024 21:54:18 +0100 Subject: [PATCH 058/107] Add MEDS --- mupq | 2 +- skiplist.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index e8472c0b..1951836e 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit e8472c0b0f740bccc986313fc2b2ab86cd7e627b +Subproject commit 1951836e4df17563783a3a55d1e6d1df89f465c5 diff --git a/skiplist.py b/skiplist.py index edc28711..e22d19df 100644 --- a/skiplist.py +++ b/skiplist.py @@ -294,4 +294,10 @@ {'scheme': 'aimer-l3-param2', 'implementation': 'ref', 'estmemory': 1091584}, {'scheme': 'aimer-l5-param2', 'implementation': 'ref', 'estmemory': 2169856}, {'scheme': 'aimer-l1-param3', 'implementation': 'ref', 'estmemory': 1442816}, + {'scheme': 'meds167717', 'implementation': 'ref', 'estmemory': 927744}, + {'scheme': 'meds41711', 'implementation': 'ref', 'estmemory': 1388544}, + {'scheme': 'meds13220', 'implementation': 'ref', 'estmemory': 210944}, + {'scheme': 'meds134180', 'implementation': 'ref', 'estmemory': 1152000}, + {'scheme': 'meds9923', 'implementation': 'ref', 'estmemory': 1021952}, + {'scheme': 'meds55604', 'implementation': 'ref', 'estmemory': 510976}, ] From b381da5beba2fab7725b7da5a8aca56a49906eba Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 16 Jan 2024 22:06:29 +0100 Subject: [PATCH 059/107] Exclude all non-building schemes for cw308t-stm32f415 --- mk/cw308t-stm32f415.mk | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mk/cw308t-stm32f415.mk b/mk/cw308t-stm32f415.mk index a3891bfe..c148f5c0 100644 --- a/mk/cw308t-stm32f415.mk +++ b/mk/cw308t-stm32f415.mk @@ -2,13 +2,23 @@ DEVICE=stm32f415rgt6 OPENCM3_TARGET=lib/stm32/f4 EXCLUDED_SCHEMES = \ + mupq/pqclean/crypto_kem/mceliece% \ mupq/pqclean/crypto_sign/sphincs-haraka-256f% \ mupq/pqclean/crypto_sign/sphincs-shake256-256f% \ mupq/pqclean/crypto_sign/sphincs-sha256-256f% \ - mupq/pqclean/crypto_kem/mceliece% \ + mupq/crypto_sign/ov-Ip% \ + crypto_sign/ov-Ip% \ mupq/crypto_sign/falcon-1024% \ mupq/crypto_sign/falcon-512% \ crypto_sign/falcon-1024% \ - crypto_sign/falcon-512% + crypto_sign/falcon-512% \ + mupq/crypto_sign/meds167717% \ + mupq/crypto_sign/meds134180% \ + mupq/crypto_sign/snova-60-10-16-4% \ + mupq/crypto_sign/snova-49-11-16-3% \ + mupq/crypto_sign/snova-37-8-16-4% \ + mupq/crypto_sign/snova-66-15-16-3% \ + mupq/crypto_sign/snova-43-25-16-2% \ + mupq/crypto_sign/snova-61-33-16-2% include mk/opencm3.mk From ee2a6ea2616cbd537d2dd5dcffcb388a94ce72c8 Mon Sep 17 00:00:00 2001 From: rpls Date: Thu, 3 Nov 2022 22:55:10 +0100 Subject: [PATCH 060/107] Add a github workflow --- .github/workflows/main.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..440e8f08 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,13 @@ +on: [push] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.5.2 + with: + release: 11.3.Rel1 + - name: Build All + run: make PLATFORM=mps2-an386 From 0a47489e4647ba25fbc9ebe449ebb01229a021bc Mon Sep 17 00:00:00 2001 From: rpls Date: Thu, 3 Nov 2022 23:00:33 +0100 Subject: [PATCH 061/107] Checkout submodules recursively --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 440e8f08..70449389 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,6 +5,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 + with: + submodules: recursive - name: Install Toolchain uses: carlosperate/arm-none-eabi-gcc-action@v1.5.2 with: From dfc968aedb1e887960a0e800434eb8068e06754c Mon Sep 17 00:00:00 2001 From: rpls Date: Fri, 24 Nov 2023 13:21:04 +0100 Subject: [PATCH 062/107] Update workflow dependencies --- .github/workflows/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 70449389..953dfabb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,12 +4,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: recursive - name: Install Toolchain - uses: carlosperate/arm-none-eabi-gcc-action@v1.5.2 + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 with: - release: 11.3.Rel1 + release: 13.2.Rel1 - name: Build All - run: make PLATFORM=mps2-an386 + run: make PLATFORM=mps2-an386 -j2 From d2a880095536f0cd4b133af9116a2df822f43882 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 16 Jan 2024 22:36:40 +0100 Subject: [PATCH 063/107] Properly wrap missing libc functions and shut up linker warning --- mk/mps2-an386.mk | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mk/mps2-an386.mk b/mk/mps2-an386.mk index 7c33809c..ab128df5 100644 --- a/mk/mps2-an386.mk +++ b/mk/mps2-an386.mk @@ -21,6 +21,16 @@ CPPFLAGS += \ LDFLAGS += \ --specs=nosys.specs \ -Wl,--wrap=_sbrk \ + -Wl,--wrap=_open \ + -Wl,--wrap=_close \ + -Wl,--wrap=_isatty \ + -Wl,--wrap=_kill \ + -Wl,--wrap=_lseek \ + -Wl,--wrap=_read \ + -Wl,--wrap=_write \ + -Wl,--wrap=_fstat \ + -Wl,--wrap=_getpid \ + -Wl,--no-warn-rwx-segments \ -ffreestanding \ -T$(LDSCRIPT) \ $(ARCH_FLAGS) From 54d8313e68603d196987f6c19901db0e037de820 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 16 Jan 2024 23:34:10 +0100 Subject: [PATCH 064/107] Run only on push to master, and when PR review requested --- .github/workflows/main.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 953dfabb..5824dfbe 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,9 @@ -on: [push] +on: + push: + branches: + - master + pull_request: + types: [review_requested] jobs: build-all: runs-on: ubuntu-latest From a0dec920dd780fb99eab21de5757abc6ea61fe23 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Thu, 18 Jan 2024 13:20:05 +0100 Subject: [PATCH 065/107] Use updated version of mirith, add embedded optimized version --- mupq | 2 +- skiplist.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 1951836e..375cfb63 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 1951836e4df17563783a3a55d1e6d1df89f465c5 +Subproject commit 375cfb63027f4d88e8f3801bf883a85f989d5cfe diff --git a/skiplist.py b/skiplist.py index 6f765aaa..e915c5f1 100644 --- a/skiplist.py +++ b/skiplist.py @@ -212,9 +212,11 @@ {'scheme': 'mirith_hypercube_IIIb_short', 'implementation': 'ref', 'estmemory': 526336}, {'scheme': 'mirith_hypercube_IIIb_shorter', 'implementation': 'ref', 'estmemory': 3916800}, {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'ref', 'estmemory': 89088}, + {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'opt', 'estmemory': 88064}, {'scheme': 'mirith_hypercube_Ia_short', 'implementation': 'ref', 'estmemory': 227328}, {'scheme': 'mirith_hypercube_Ia_shorter', 'implementation': 'ref', 'estmemory': 1779712}, {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'ref', 'estmemory': 109568}, + {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'opt', 'estmemory': 109568}, {'scheme': 'mirith_hypercube_Ib_short', 'implementation': 'ref', 'estmemory': 247808}, {'scheme': 'mirith_hypercube_Ib_shorter', 'implementation': 'ref', 'estmemory': 1800192}, {'scheme': 'mirith_hypercube_Va_fast', 'implementation': 'ref', 'estmemory': 344064}, From f514356781eeacc24afe7c9bf4ba2d0b11caf30a Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 19 Jan 2024 14:36:36 +0100 Subject: [PATCH 066/107] Add Tuov --- mupq | 2 +- skiplist.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/mupq b/mupq index 375cfb63..d5a9d227 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 375cfb63027f4d88e8f3801bf883a85f989d5cfe +Subproject commit d5a9d2279d9c594c9c188048a4eee8923c096733 diff --git a/skiplist.py b/skiplist.py index e915c5f1..11534aeb 100644 --- a/skiplist.py +++ b/skiplist.py @@ -338,4 +338,16 @@ {'scheme': 'biscuit192s', 'implementation': 'ref', 'estmemory': 2257920}, {'scheme': 'biscuit256f', 'implementation': 'ref', 'estmemory': 505856}, {'scheme': 'biscuit256s', 'implementation': 'ref', 'estmemory': 4004864}, + {'scheme': 'tuov_ip', 'implementation': 'ref', 'estmemory': 3790848}, + {'scheme': 'tuov_ip_pkc', 'implementation': 'ref', 'estmemory': 799744}, + {'scheme': 'tuov_ip_pkc_skc', 'implementation': 'ref', 'estmemory': 865280}, + {'scheme': 'tuov_is', 'implementation': 'ref', 'estmemory': 1111040}, + {'scheme': 'tuov_is_pkc', 'implementation': 'ref', 'estmemory': 1176576}, + {'scheme': 'tuov_is_pkc_skc', 'implementation': 'ref', 'estmemory': 1275904}, + {'scheme': 'tuov_iii', 'implementation': 'ref', 'estmemory': 3280896}, + {'scheme': 'tuov_iii_pkc', 'implementation': 'ref', 'estmemory': 3468288}, + {'scheme': 'tuov_iii_pkc_skc', 'implementation': 'ref', 'estmemory': 3790848}, + {'scheme': 'tuov_v', 'implementation': 'ref', 'estmemory': 8388608}, + {'scheme': 'tuov_v_pkc', 'implementation': 'ref', 'estmemory': 7083008}, + {'scheme': 'tuov_v_pkc_skc', 'implementation': 'ref', 'estmemory': 4639744}, ] From 1ccd61fa77f685dd28eec12e57c5ae4d39be8135 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Fri, 19 Jan 2024 14:42:57 +0100 Subject: [PATCH 067/107] Exclude tuov from builds --- mk/mps2-an386.mk | 3 +++ mk/nucleo-l4r5zi.mk | 1 + mk/stm32f4discovery.mk | 1 + 3 files changed, 5 insertions(+) diff --git a/mk/mps2-an386.mk b/mk/mps2-an386.mk index ab128df5..48914751 100644 --- a/mk/mps2-an386.mk +++ b/mk/mps2-an386.mk @@ -1,3 +1,6 @@ +EXCLUDED_SCHEMES = \ + mupq/crypto_sign/tuov_v/ref% + MPS2_DATA_IN_FLASH = 1 CROSS_PREFIX ?= arm-none-eabi CC := $(CROSS_PREFIX)-gcc diff --git a/mk/nucleo-l4r5zi.mk b/mk/nucleo-l4r5zi.mk index b3b673cd..b0d30fea 100644 --- a/mk/nucleo-l4r5zi.mk +++ b/mk/nucleo-l4r5zi.mk @@ -3,6 +3,7 @@ OPENCM3_TARGET=lib/stm32/l4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ + mupq/crypto_sign/tuov% \ mupq/crypto_sign/falcon-1024-tree% DEVICES_DATA := ldscripts/devices.data diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 267ace05..6c819423 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -3,6 +3,7 @@ OPENCM3_TARGET=lib/stm32/f4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ + mupq/crypto_sign/tuov% \ mupq/crypto_sign/falcon-1024-tree% include mk/opencm3.mk From 4702ce9320e360582d555240974f72564b92b598 Mon Sep 17 00:00:00 2001 From: Marco Palumbi Date: Sat, 20 Jan 2024 09:21:05 +0000 Subject: [PATCH 068/107] improve compression for short levels I and II --- crypto_sign/perk-128-short-3/m4/bn.c | 8 +- crypto_sign/perk-128-short-3/m4/bn.h | 19 +- .../perk-128-short-3/m4/rank_unrank_table.h | 321 +++++++++--------- 3 files changed, 187 insertions(+), 161 deletions(-) diff --git a/crypto_sign/perk-128-short-3/m4/bn.c b/crypto_sign/perk-128-short-3/m4/bn.c index b676feb3..0faba5a0 100644 --- a/crypto_sign/perk-128-short-3/m4/bn.c +++ b/crypto_sign/perk-128-short-3/m4/bn.c @@ -99,11 +99,11 @@ void bignum_add(const struct bn* a, const struct bn* b, struct bn* c) require(b, "b is null"); require(c, "c is null"); - DTYPE_TMP tmp; int carry = 0; int i; for (i = 0; i < BN_ARRAY_SIZE; ++i) { + DTYPE_TMP tmp; tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry; carry = (tmp > MAX_VAL); c->array[i] = (tmp & MAX_VAL); @@ -117,13 +117,13 @@ void bignum_sub(const struct bn* a, const struct bn* b, struct bn* c) require(b, "b is null"); require(c, "c is null"); - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; int borrow = 0; int i; for (i = 0; i < BN_ARRAY_SIZE; ++i) { + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */ tmp2 = (DTYPE_TMP)b->array[i] + borrow; res = (tmp1 - tmp2); diff --git a/crypto_sign/perk-128-short-3/m4/bn.h b/crypto_sign/perk-128-short-3/m4/bn.h index c0debe59..d9253f77 100644 --- a/crypto_sign/perk-128-short-3/m4/bn.h +++ b/crypto_sign/perk-128-short-3/m4/bn.h @@ -20,6 +20,8 @@ There may well be room for performance-optimizations and improvements. */ +#include "parameters.h" + #include #include @@ -30,10 +32,19 @@ There may well be room for performance-optimizations and improvements. #endif /* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (64 / WORD_SIZE) -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE 28 // PERK LEVEL 5 custom WORLD_SIZE - +#if (PARAM_N1 == 79 || PARAM_N1 == 83) +#define BN_ARRAY_SIZE 13 // PERK LEVEL=1, T=3,5 custom WORLD_SIZE +#elif (PARAM_N1 == 112) +#define BN_ARRAY_SIZE 19 // PERK LEVEL=3, T=3 custom WORLD_SIZE +#elif (PARAM_N1 == 116) +#define BN_ARRAY_SIZE 20 // PERK LEVEL=3, T=5 custom WORLD_SIZE +#elif (PARAM_N1 == 146) +#define BN_ARRAY_SIZE 27 // PERK LEVEL=5, T=3 custom WORLD_SIZE +#elif (PARAM_N1 == 150) +#define BN_ARRAY_SIZE 28 // PERK LEVEL=5, T=5 custom WORLD_SIZE +#else +#error Invalid value for parameter PARAM_N1 +#endif /* Here comes the compile-time specialization for how large the underlying array size should be. */ /* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ diff --git a/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h b/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h index c530d04f..dc969d66 100644 --- a/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h +++ b/crypto_sign/perk-128-short-3/m4/rank_unrank_table.h @@ -12,160 +12,175 @@ #define SIG_PKP_RANK_UNRANK_TABLE_H #include "bn.h" +#include "parameters.h" -// clang-format off -static const struct bn factorial[] = {{{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0006,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0018,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0078,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x02d0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x13b0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x9d80,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58980,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x375f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2611500,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x1c8cfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7328cc00,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x4c3b2800,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77775800,0x0130,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x77758000,0x1307,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xeecd8000,0x1437e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xca730000,0x16beec,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x6890000,0x1b02b93,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x82b40000,0x21c3677c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb8c40000,0xc5077d36,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xe0d80000,0xeea4c2b3,0x003c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x33680000,0x70cd7e29,0x0579,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xd1c00000,0x9343d3dc,0x8362,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x7bc00000,0x619fb090,0xcd4a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x91800000,0xea37eeac,0x14d9849,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x58800000,0xb3e62c33,0x232f0fcb,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xae000000,0xad2cd59d,0xd925ba47,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0xb6000000,0x9e1432dc,0x99461a1e,0x006f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x54000000,0x865df5dd,0xf6370f96,0x0d13,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x2c000000,0x4560c5cd,0xd0aae33a,0x1956a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0xac18b9a5,0x155c6748,0x32ad5a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x80000000,0x2f2fee55,0xc0e9505e,0x688589c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x445da75b,0x9efcac82,0xde1bc4d1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x001e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x0445,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xf38fff4,0x6477ada,0x8f68df5,0x9e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x4275fe38,0xee9c3c5e,0x5499125e,0x177401,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x392ac33,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff052540,0x80fde64,0x84c7f27e,0x8eeae81b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x03c1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0xa179,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x1bc0ef,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x4e0ea0c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x0029,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x07b9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x17a88,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x49eebc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0xeba8f91,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x8ab20000,0x2a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x0002,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x009e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x91fc0000,0xc72a98d8,0x66a0711,0x88186c96,0x580cd327,0x77f77e01,0x2172,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x72f97,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x1926933,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x0014,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x04ad,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x118b5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x42e33c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0xd162c005,0xc6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x00ff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x1a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x40c8,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x10b395,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x45f0025,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x0050,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x65dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x15e7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x61356,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x1b57057,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0xea4983b,0x0024,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x35807780,0x5fd0ed48,0x24f4b63c,0x9124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x0a90,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x8cd9620,0x322d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0xf17a60,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfcc94000,0xc910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x0718,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0xbf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x23eb7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x9d7e8000,0xb8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0xab231e0,0x4dff9e1d,0xb816d6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x0013,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0xc70dd91,0x931b466f,0x72d84574,0xa8222a98,0x0680,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x22f38,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x83cc0000,0x42e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x62e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0xbe0c31,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x4e200000,0x6fec0115,0x15ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x0016,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x07fc,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x71376bf,0x3687bb16,0x2d69b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0xaf3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x1051fc7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xd000000,0xefdb9cb3,0x6fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x0022,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x93a7e42,0x0ced,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0x20b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x4d8e3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x1d62e2f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x23b0acf,0x773e059f,0xc976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x0045,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x1b30,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0xaba2b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x4462d40,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x00b2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x495a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x76ae4740,0xd38e0a7d,0x234c1b5,0x6ce9575a,0x60fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x1e5f96,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x7678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0xadb0c97,0x557d15cf,0xcb1f412,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x0247,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0xfad7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0xebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x6cc374,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0xdf3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0xf49048f,0x12b4d256,0x882caf31,0xfee805,0x0015,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x095a,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x433a0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x11510000,0x57bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x1e764f3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x61241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x0066,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x56420000,0x4ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x2fba,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x165f63,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x6f700000,0xebf5e0c,0x6c301cdc,0x25be6d2d,0xa3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0xa931607,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x1b600000,0x732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0xcfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0xa187fb9,0x0005,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0xbdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x3eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x026b,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x12c3d,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x4ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x929a05,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0xf5000000,0x97a4d3d0,0x60ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x5caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x9abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x8b000000,0x3ac514a9,0x4703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x10d0690,0xc3ca6187,0xcbbf8281,0x0023,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x11e5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x767f613,0x8b531aa1,0xebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0xc245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x904d5,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x29c531cb,0x8a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0xa3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x494748b,0x0000,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x0002,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x8e57f90,0x575ed2cd,0x9de4326,0x5bb04be1,0x0135,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x5c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0xddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0xa0b8,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x47eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x5420a5,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0xb128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x0000,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x8f5b2e40,0x31297773,0xd317fe6,0x8c0a1bcd,0x50c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x8f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x854a024,0x9185413b,0x0017,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xb7cbc040,0x4f30ecd7,0xf7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x6e4d985,0xc1d018c3,0xc8bf3a4a,0x5ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0xcbf553d,0x7549b353,0xe04fe897,0x0c9c,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0xeef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x6cc90,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x3b112af,0x0000,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0xa9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x4d6380d,0x0002,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0xa839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x7ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x011c,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x9de6,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x3c0a9bd,0x7befc8de,0x5833a3,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x0000,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x001c,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x1006,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x933e7,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xacee0000,0x2d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x55201f8,0x0000}}, - {{0x0000,0x0000,0x0000,0x0000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x6f9e2f4,0x71ffc59,0x18bb256b,0x0003}}, - {{0x0000,0x0000,0x0000,0x0000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x7bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x01d0}} +#if (PARAM_N1 >= 79) -}; +// clang-format off +static const struct bn factorial[] = {{{0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000002,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000006,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000018,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000078,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x000002d0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x000013b0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00009d80,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00058980,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00375f00,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x02611500,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x1c8cfc00,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x7328cc00,0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x4c3b2800,0x00000014,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x77775800,0x00000130,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x77758000,0x00001307,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xeecd8000,0x0001437e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xca730000,0x0016beec,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x06890000,0x01b02b93,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x82b40000,0x21c3677c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xb8c40000,0xc5077d36,0x00000002,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xe0d80000,0xeea4c2b3,0x0000003c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x33680000,0x70cd7e29,0x00000579,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xd1c00000,0x9343d3dc,0x00008362,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x7bc00000,0x619fb090,0x000cd4a0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x91800000,0xea37eeac,0x014d9849,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x58800000,0xb3e62c33,0x232f0fcb,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xae000000,0xad2cd59d,0xd925ba47,0x00000003,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0xb6000000,0x9e1432dc,0x99461a1e,0x0000006f,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x54000000,0x865df5dd,0xf6370f96,0x00000d13,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x2c000000,0x4560c5cd,0xd0aae33a,0x0001956a,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x80000000,0xac18b9a5,0x155c6748,0x0032ad5a,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x80000000,0x2f2fee55,0xc0e9505e,0x0688589c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x445da75b,0x9efcac82,0xde1bc4d1,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x58cde171,0xbc8b95cf,0x5dcbe8a8,0x0000001e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x7cf3b3e4,0x83a11128,0x30acb7ba,0x00000445,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x0f38fff4,0x06477ada,0x08f68df5,0x00009e00,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x4275fe38,0xee9c3c5e,0x5499125e,0x00177401,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x1ff9ba88,0x59cd325c,0xe351cc76,0x0392ac33,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xff052540,0x080fde64,0x84c7f27e,0x8eeae81b,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xd7d2f740,0x4a8a9e2c,0x4405d62f,0xe39f2c68,0x00000016,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x689c9080,0x3abdf35b,0x28f523c2,0x581d491b,0x000003c1,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x924c4580,0xdde7e05a,0xe12d019f,0xcceb478f,0x0000a179,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x251bf200,0x23da8f91,0xb3bc477a,0x38704cba,0x001bc0ef,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x85e98a00,0x4d6b3c83,0x98189078,0xebbd7cd1,0x04e0ea0c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x0ff6cc00,0xe944dfa2,0x5469f59d,0x5c0c6da9,0xe06a0e52,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xee4f7400,0xd3a50ec0,0x7f7417fd,0xe6482216,0x3378a11e,0x00000029,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xaee5c000,0xaef2c42c,0xe5c47f97,0x2d866437,0xa69e35cb,0x000007b9,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x79f9c000,0x7c778c8d,0xfa9c6c08,0xb6b92eb2,0xe4484be3,0x00017a88,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xd2c78000,0x4f5973a1,0xf28d19a8,0xb02b1ef4,0x961ed279,0x0049eebc,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xfdbe8000,0xced2093c,0x521c1c87,0x18972acc,0xe823ee3e,0x0eba8f91,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x8ab20000,0x02a9e063,0xadb5cb96,0xfeb4b180,0x274c649c,0xfde529a3,0x00000002,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0xb6da0000,0x8d2b749b,0xf6a3260e,0xbb68bfa3,0x22d0d480,0x90719ec7,0x0000009e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x91fc0000,0xc72a98d8,0x066a0711,0x88186c96,0x580cd327,0x77f77e01,0x00002172,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x5d240000,0xca26d687,0x60c784d1,0x3d3f543b,0xeac15d7e,0xc62c1249,0x00072f97,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x5fe00000,0x387eed9c,0x2ba50de4,0x65da6cfd,0x5a4c739d,0x59a4002b,0x01926933,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x58e00000,0x9442e7d1,0xb7c017d0,0xada2445e,0x1b05be0b,0xf58409a7,0x59996c6e,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x22c00000,0x9728856e,0xa1856541,0x56c37d75,0x1f4d0ea5,0x9fea2fdc,0x4cc29123,0x00000014,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x02400000,0xd656c062,0x39be561d,0xff0dea1c,0x36c2601a,0xdaf907bb,0xb0d77335,0x000004ad,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x87000000,0x3c5516f8,0x889c2efe,0xc742de9d,0xd58e8653,0x525dcfe0,0x727f009f,0x000118b5,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x2b000000,0x60467938,0x8d373294,0x7aef0b89,0xe2f601f6,0xa05a8892,0x484325f6,0x0042e33c,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x6a000000,0x51115b9a,0x335e3fef,0xc5e4cb50,0xf79479b1,0xd5ed1392,0x804331ba,0x10330899,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x16000000,0xf3458b00,0xa431bbe4,0xb34e08bc,0xed89f2bf,0xa557d12a,0x90893cfa,0xfc8f1dc6,0x00000003,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x80000000,0xd162c005,0x0c6ef93c,0xd3822f29,0x627cafec,0x55f44abb,0x224f3ea9,0x23c771a4,0x000000ff,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x80000000,0x2a12c165,0x282d4871,0xb40df96c,0x01a8ab21,0xd306f994,0xb61ee8fe,0x15a3daac,0x000040c8,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xd8d5dc2b,0x5bacad2c,0x6b9a4de2,0x6d7c1eb0,0x67cc5828,0xf3f811b2,0x943e6086,0x0010b395,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xbff89f41,0xfe3152bc,0x2962623d,0xa77c082c,0x2a7b1294,0xd9eca1b1,0xcc534351,0x045f0025,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xfe0a4d44,0x8519fa22,0xfe221877,0x7cf22bba,0x48b0ef7c,0xe2daf30f,0x461de1bd,0x293c0a0a,0x00000001,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x78c6d354,0xe0006b6e,0x7f309836,0xad45c966,0x97b08c8d,0x2503831e,0xe60dd82e,0x1d2eb4c4,0x00000050,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x065dc8f8,0x401d6035,0xc7499f01,0x61151206,0x7a466ebd,0x1ef5da5d,0xe7c91c9e,0xfac56dd6,0x000015e7,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xc402bcc8,0xc825aeb4,0x456b1958,0xecd7ffe1,0xe988b685,0x962f8fec,0x48c6efda,0x8cc1769a,0x00061356,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x20c51840,0x4a9922d7,0x861f20f8,0x9cbff75b,0xae7355aa,0x3d607aa1,0x77f3757a,0x96695b64,0x01b57057,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x5833ea40,0x45aaef58,0x3ee066cd,0xb2bd8919,0xbee36da6,0x8082f81a,0x346c7fdb,0xe40b0fa6,0x7cbd08f9,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x7f01b680,0x23692f89,0x2cddb756,0xaac9a14c,0x2dbdb22f,0x25dbb7bb,0x275cf573,0xeb32860b,0x0ea4983b,0x00000024,0x00000000}}, + {{0x00000000,0x00000000,0x35807780,0x5fd0ed48,0x24f4b63c,0x09124151,0x669333f7,0x175ed3d6,0x883be8bc,0xe7cd4544,0x4a38998d,0x00000a90,0x00000000}}, + {{0x00000000,0x00000000,0xe2237a00,0x7206716f,0xf8a619ec,0xb16b6416,0x73b36d56,0xf026e3a6,0x71c917d6,0xd0f09058,0x08cd9620,0x000322d6,0x00000000}}, + {{0x00000000,0x00000000,0x04abb200,0x4bf01ea7,0xc9f5cc1e,0x5d4d1ae8,0xccf7e313,0x3bb27910,0x397c2ba6,0xd85b6a9a,0xa5d627de,0x00f17a60,0x00000000}}, + {{0x00000000,0x00000000,0x6c503c00,0x232956e3,0x88e4313b,0x6d7e32ed,0x73872fe6,0x3060e31e,0x83d54ca6,0xebda7afd,0x874025e5,0x49934972,0x00000000}}, + {{0x00000000,0x00000000,0x6cc28400,0xd9c1d02e,0x3e6b313f,0xc9f1b74d,0xa6b7c81b,0xede61665,0xaed2a748,0xc86bf43b,0xbccbb1f3,0xb473aa57,0x00000016}}, + {{0x00000000,0x00000000,0xfcc94000,0x0c910e81,0x817f63f4,0x1b894823,0x196e88af,0x57e6ffc4,0xa1d446ca,0xa1bc52a6,0xffa79c2e,0x64253b6a,0x00000718}}, + {{0x00000000,0x00000000,0xfbad4000,0xf9e59720,0xf94ea037,0xb66fd33b,0x0bf93f67,0xd016ed0c,0x342a6605,0x2c9626b9,0xe4086ac1,0xafc7ccda,0x00023eb7}}, + {{0x00000000,0x00000000,0x9d7e8000,0x0b8a6890,0xdb2f51ee,0x6fd1a935,0xd5d64f38,0xa757eddb,0xb594addc,0x48186752,0x0ab231e0,0x4dff9e1d,0x00b816d6}}, + {{0x00000000,0x00000000,0x10038000,0xbddfe6e3,0x1057902d,0x40f9dc76,0x547baf4c,0x41821e46,0xdf345e8a,0x5fe97fd0,0x77c62bb7,0x49e0436a,0x3baf677b}} +#if (PARAM_N1 >= 112) + , + {{0x00000000,0x00000000,0x41260000,0x4d77c281,0x5cbb4f02,0x51fc56bd,0xb8958505,0x7eb1ef13,0x3d2f055d,0x789df089,0x4d06582b,0x3d961eef,0x958df474,0x00000013,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xa19e0000,0xb8c394ea,0xca313bc3,0x38c8ccdf,0x49a52ac4,0x1114618c,0x509cc80b,0x0c70dd91,0x931b466f,0x72d84574,0xa8222a98,0x00000680,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x4b140000,0x11b406d2,0xec8a13c0,0x1374d32d,0xbd7c5deb,0xbcd8c520,0x14ab33b7,0x2dea6ed1,0x6b29a94e,0x94a75529,0x7b7a4f36,0x00022f38,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x83cc0000,0x042e5177,0x62ecb646,0x9cb3c49b,0x6543eae3,0x2daafe20,0x062e9371,0x9aaba90e,0x6b288991,0x84ddf113,0xf690eb8c,0x00be0c31,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x4e200000,0x6fec0115,0x015ea811,0xddcb956a,0xcf58be3d,0xb2c75b22,0x2002aee7,0x2b021cd2,0xd5ef4a0d,0xac4adeac,0xc1d0f84d,0x4154312c,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x29200000,0xe90c6068,0x79e86e0f,0x1bc6f1da,0x15da2382,0x274eaf1a,0x20eece8d,0xf3bc050d,0x6030be93,0xe6076a16,0x61a65300,0xb645188f,0x00000016,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x75400000,0xee59e49e,0xdbb6b197,0xc3f106ce,0xaeb07bbd,0xd1a98f2b,0x93f49d9f,0xb019c69d,0xd1230003,0xde9b4bdd,0x54792e50,0x144aa268,0x000007fc,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xadc00000,0xb9f44453,0x19f12101,0xa6ad6b88,0x18bbfc74,0x8745e487,0x97f407cf,0x99299a03,0x5771014f,0x2133f7d9,0x071376bf,0x3687bb16,0x0002d69b,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x71000000,0xd3c88e12,0x52a7dc9e,0xe652a4e9,0xe38eb9eb,0x9d1e208c,0x9bb2ce94,0x0af3594a,0x6c9c789b,0xeead121b,0x8afeacaf,0x98c73bea,0x01051fc7,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x0d000000,0xefdb9cb3,0x06fb25b2,0xac05e8c3,0xaad98ab2,0x13f1d32e,0x8ff50bfd,0xfa67701a,0x74d7d052,0xb4df93f6,0x7e84bbe9,0x8060c434,0x5edc8b82,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xc6000000,0x12a389be,0x9037d7b4,0x2a2b779c,0xbbe0ed9b,0x52cb8b22,0xdbfa66ed,0xf1fb29c0,0xe73e7e77,0x6a18547e,0x74bcffd0,0x23880b46,0xd4fb39eb,0x00000022,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x7a000000,0xeab01dcb,0x84b90bd2,0xa6216319,0xb8782c94,0xb988a1e3,0xa1ec3211,0xcc347e91,0xd030ee82,0x5f075b17,0x5222ee57,0x2f7c2f25,0x093a7e42,0x00000ced,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xc0000000,0x020b2c4d,0xc5646f18,0x4c852991,0x2d10b7be,0x933cb565,0xb892c6a5,0x93af769c,0x1259710c,0xa2c228ee,0xcd1960c3,0xce91adfe,0x75ef58d1,0x0004d8e3,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0xc0000000,0xc63bc975,0xcb0e1818,0xfe74c03b,0x13559f1a,0xca00bb56,0xef9d44bc,0xf57bf161,0xf3e3d5c3,0xab918234,0xb69daa20,0x4532ed8b,0xafb0a77f,0x01d62e2f,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x80000000,0xe2e31f13,0xbb65397b,0x68b196e3,0x66c6e855,0x5447b6f3,0xba345045,0xf972677d,0x5d37d503,0xadb3d845,0xe85b2081,0x7d7eef7b,0x41a01eb8,0xb3fdae41,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x80000000,0xbdd5048a,0x78253ae8,0x7cad5a11,0xbeebd907,0x97bbc020,0x023b0acf,0x773e059f,0x0c976089,0x2c8ca2d3,0xdb3d9226,0x88169cea,0x60ebe158,0x9b1a633c,0x00000045,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x2735c61a,0xee8b02ea,0xb3b72ed2,0x9420c6ec,0x45570cca,0xdf103917,0x943a321c,0xeb21b5b2,0x66ef9a70,0xa40d16e9,0x28d54bbd,0xdc240695,0x964ec395,0x00001b30,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x78372842,0x1cd82661,0xe7457938,0x70ee7b62,0x5b580bec,0x0166862e,0x7af5c564,0xc44caf74,0x9c87ee8c,0xb92a0a15,0x1c26e1d1,0xda3698d9,0x4d132a1f,0x000aba2b,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0xe5fa0a4c,0x7e1f4ad5,0x25ae4c5b,0xff052968,0x6514c034,0x8ed97678,0xfdeca5d8,0x368de868,0x5e290c16,0xc6c0049c,0x377df98f,0xf1c0e681,0xb5a2c8b0,0x04462d40,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x879a2494,0xbe971c0f,0x2920b8cf,0x9b13a8e7,0xab595552,0x797eaa70,0x2a36ba21,0xf318823e,0xe283dcef,0xf741dae9,0x53af68d8,0x449cbdfd,0x147ebf31,0xb83c3509,0x00000001,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x169edc20,0x6d63664f,0xb54b1465,0xfffc9de8,0x9c4aa98e,0x5b753dc5,0x263b9d99,0xc1f4e941,0x0591c17a,0x72c0ef04,0xff429824,0xdfad2ee9,0x537dac03,0xd8758bb0,0x000000b2,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x47284920,0xddc4f670,0x5bcb5d99,0xfe9cc472,0x1a9f8ba6,0x8316560d,0xae73a3e6,0x8d73abb8,0x48c85b59,0x112208a6,0xb25066f3,0xbe083df9,0x3e8b8d96,0xc8364b52,0x0000495a,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x76ae4740,0xd38e0a7d,0x0234c1b5,0x6ce9575a,0x060fd325,0x473fa16d,0x3be1dd72,0x91e51a78,0x22f5d314,0x181794da,0xd54aa0a5,0xaf69a963,0xe5c8a06a,0xe67b300d,0x001e5f96,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x9ad7c7c0,0x6c5e6270,0xec0cf6ff,0x8587829e,0x889d40a4,0xc7987891,0x07678ec3,0xfac21041,0x9cbf3998,0x11db372c,0x26312501,0x5129ccba,0x0adb0c97,0x557d15cf,0x0cb1f412,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x53084500,0xb7d18781,0x957833c1,0x552b1b0b,0xa2574568,0x3452dd65,0x1fb03a98,0xc9dedb6f,0x20ac4c89,0x887b46d2,0x1cbb9c73,0x3da25e88,0x94694fd6,0x10c53358,0x5b12f7bc,0x00000005}}, + {{0x00000000,0x00000000,0x00000000,0x5a856100,0x4436b210,0xa42e097b,0x435a83ee,0x1f288d6c,0x47484446,0x7e08f2ce,0xf3e36e50,0xe95c96aa,0x1c7d2777,0x3be19d31,0x3e223ff4,0x30d6fe38,0x23f6dcb7,0xc7137b13,0x00000247}}, + {{0x00000000,0x00000000,0x00000000,0xe54fae00,0x4f808306,0x8bc812f7,0xf0e4b08a,0x636cc484,0xa10d5621,0x27d854a2,0xcbb96696,0x45c8bd74,0x3dc6f586,0xbaf18b1a,0xb2b77af1,0xfc613c2a,0x7412d6b6,0x8a5ee239,0x0000fad7}}, + {{0x00000000,0x00000000,0x00000000,0x6d8c7200,0x78b8cffd,0x9bc0393b,0x73288c12,0x1c2935a4,0xd4c8587a,0x46ccb283,0x55637b1b,0x420a25a4,0xc9447538,0x0ebb5060,0x7d8e4ed0,0x6e291683,0x542b1957,0xff2416e9,0x006cc374}}, + {{0x00000000,0x00000000,0x00000000,0xed71e000,0xd0dafedf,0x24190a04,0x61bd4824,0x520777f2,0x17a6b56c,0xf98e19ad,0x5b85dbee,0xe47077e5,0x0df3489c,0x71f32a58,0xee427b06,0x31f9d986,0xd2db1640,0x9fca0614,0x2f95832f}} +#if (PARAM_N1 >= 116) + , + {{0x00000000,0x00000000,0x00000000,0xcf43e000,0x30aa80d7,0xef0d6c20,0x248cd7f3,0x354bf1fd,0x709614d0,0x27b95567,0x6616147c,0xd5a4ec3d,0x28630d40,0x4c55b0de,0x2b584dd8,0x0f49048f,0x12b4d256,0x882caf31,0x00fee805,0x00000015}}, + {{0x00000000,0x00000000,0x00000000,0x4c39c000,0xabed601a,0x73fa2655,0x46b82aa0,0xbbd1c2ba,0x22d544b7,0xb0880810,0x75d51f49,0x23713357,0xfc1be6df,0xfe28c2ed,0x4d52aa51,0xce8407c1,0x5485aa52,0xa3e603da,0x71835276,0x0000095a}}, + {{0x00000000,0x00000000,0x00000000,0x3df14000,0x3ba22bd0,0x195f387c,0xc4bb2614,0x5f3a79ad,0xa5cdde89,0x4d1b9f3f,0xeebd0e1a,0xebda1049,0x4088b63c,0x2c4f90e8,0xbc2282d5,0xc54f7bd5,0xf80b8332,0xa053bb13,0xfdfe0b4b,0x000433a0}}, + {{0x00000000,0x00000000,0x00000000,0x11510000,0x057bda5c,0x7f25984b,0x24cd411b,0x267f22bd,0x2148d63f,0xf08428d7,0x2daa63ea,0xdecf6180,0x3df2939a,0x140da93d,0x3fa34898,0x68041cd9,0x65377301,0xa5f0c50c,0x171d1e44,0x01e764f3}} +#if (PARAM_N1 >= 146) + , + {{0x00000000,0x00000000,0x00000000,0xea050000,0x819acc13,0x1c2e9a49,0xd1cec191,0x981ae071,0x3649eadc,0xec66aa52,0xdedfaa5f,0xd4c78f94,0x4fdd75c7,0x2a3e58fd,0x15a02d81,0x89e12f4a,0x42578fa4,0xd70a0eaa,0x904ed55f,0xdec12319,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0xde4e0000,0xbd5a112d,0xfd7b1de1,0xb54d38e2,0x1c637476,0x061241ae,0xf75281e5,0xbb188836,0x13fc2e9e,0xd0144a1c,0x78bd04c2,0xf7d4f989,0x8dcbcc25,0x945c35d7,0x1ea2c27a,0x84565a2d,0xad062dc8,0x00000066,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x56420000,0x04ddfc52,0xd43ae3ef,0x46e57183,0x323b232e,0xd27c87ef,0xf75a6175,0xf867518c,0x4a39abc8,0xb96e730d,0x1fdd368e,0x33fffee7,0xe9bbe5a6,0xf6dd0732,0x3da866fa,0x8423eaf9,0x6ddf4835,0x00002fba,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x6ef00000,0x480e4698,0x7b9ad80a,0x3b8d35cb,0x8bb87db1,0xaa5fb81f,0xf25daf3a,0x706e3a13,0xcb088634,0xebc5ee3a,0xefb192e6,0x5fff7c56,0x9013a5e8,0xb79b5fdd,0xe6f045a3,0xf0d624d4,0x80a9d915,0x00165f63,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x6f700000,0x0ebf5e0c,0x6c301cdc,0x25be6d2d,0x0a3368c5,0x873e06e9,0x8e47d2ba,0x2419736d,0xf7076ec9,0x708d99c9,0x4aee6f25,0x5fc1c517,0x19496ad5,0xc8704fb9,0x2790ea61,0xd53768a1,0xd0479b5e,0x0a931607,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x1b600000,0x0732d1ed,0x8eedc0df,0xfcc007a5,0xdc7fedf3,0x738f4b0e,0xce3a6ce4,0x34210235,0xb98acbdb,0xa37b4a3f,0xb5a0f7d7,0xa257ed19,0x0cfce9af,0x8585fe36,0xdb0fb299,0x9c67dccc,0x42200b31,0x0a187fb9,0x00000005,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x27200000,0x756adcec,0xac3bab28,0x7043ac8b,0xf177543a,0x85d91023,0x161251c3,0x0bdc0fda,0x25aff252,0x8c3cac9e,0x4457149b,0x003eeb5a,0x3d844763,0x276123f8,0x408acfc3,0x25e7166d,0xc56560d6,0xd9c55e02,0x0000026b,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0xf3800000,0xdfc30262,0x6ce6e798,0x60c793a7,0xf5cccc4e,0xd523d168,0xb0df9ab4,0xbe97ada2,0x41395fbd,0xed639c9a,0x1a2dfb57,0x1e79ffb9,0xcc1293f4,0x130d6c3d,0x433ca287,0x5beedceb,0x9d1ae7ba,0x7b998957,0x00012c3d,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0xe5800000,0x42382a50,0x2cbf15a5,0x417318c0,0x04ffc245,0x127d4040,0x5d2e8a4c,0x100fc870,0xd903bfa6,0xe9a37751,0xc873b9ee,0xe191dd61,0xa5123e32,0x4d8dda2c,0xd49b5bf4,0xe3a1dedf,0xb62325fe,0x59f80fc7,0x00929a05,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0xf5000000,0x97a4d3d0,0x060ca756,0x36a62e96,0x75e19e16,0x19a59f82,0xdce81171,0xe7c4a74d,0xcfd853bb,0xfe74ba48,0xa8f58396,0x05caf620,0x3efa9d0b,0x2bd161f9,0xa477423e,0x09abb22a,0xa54cb374,0x4817c44b,0x4827cea2,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x8b000000,0x3ac514a9,0x004703f5,0x1c711c6d,0x7aed6d05,0xb92a21b8,0x9720a71b,0xfa8effa0,0x1c518a37,0x3be86a1f,0xd1cc47e8,0xdfb01a33,0x3e53e877,0xbcdf9aa6,0x9729dcd7,0xcc2d6327,0x010d0690,0xc3ca6187,0xcbbf8281,0x00000023,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x80000000,0x628a54c5,0x2381fa9d,0x388e3680,0x76b6828e,0x9510dc3d,0x90538ddc,0x477fd04b,0x28c51bfd,0xf4350f8e,0xe623f41d,0xd80d19e8,0x29f43bef,0x6fcd531f,0x94ee6bde,0x16b193cb,0x86834866,0xe530c380,0xdfc140e1,0x000011e5,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x80000000,0xa7b4b785,0xe47f494e,0x7fa97691,0xd1f7c9aa,0x1d7efaf8,0xba1a7c27,0x0767f613,0x8b531aa1,0x0ebcd6a2,0xf81e0318,0xde9a0e5b,0x241233db,0x5676e2b4,0x0c245b16,0x6f7b7996,0xc8277b71,0x7d9283c3,0xc061b1d4,0x000904d5,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x29c531cb,0x08a339f1,0xd40e3616,0x9fd46894,0xfa7b725a,0x81730bdc,0xc2caf604,0xc03385c5,0x7be4fe8a,0xff3d9237,0x0a3b4ab3,0x513e55a7,0xe85f1f7a,0x2a764157,0x9cb3be32,0xa40caf9a,0xc466e96b,0xb19c4de7,0x0494748b,0x00000000,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x5fe87ae1,0x6b86a668,0x8345ad46,0xc9b18428,0x2d2b845f,0x3ddf1214,0xaddbe44e,0x5a5d7432,0x662e4100,0x9c81d264,0x3c573a1b,0x92e5d47a,0xe8ad1b97,0xba836ffb,0x2ffa53ab,0xf27ddc1e,0x80a97214,0xe2fbdd99,0x57f7a37b,0x00000002,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x73df5c04,0x716dcdd1,0xafed584f,0xff8824e3,0x4a704163,0xe7055267,0xa561b857,0x982fea21,0xafd9842e,0xb2f07bc4,0x1cf9f63c,0xbe818f07,0xf9423a27,0x2bc5bde3,0xbd13248c,0x08e57f90,0x575ed2cd,0x09de4326,0x5bb04be1,0x00000135,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x330ace14,0xee0bedd1,0x664ee145,0xc1bb2a4a,0xac51f8f3,0x05c3cfa9,0xebc4c5ab,0x10e4a37a,0x5c01ac35,0xf6f04d2f,0x0ddced88,0xf94f4eb2,0x7f6836a5,0xbdbba770,0x3af1fcd2,0x9f3b4632,0x64438485,0x2078e2eb,0xa2976bea,0x0000a0b8,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xb7a7de78,0x9a3e7b80,0x8d49ea9a,0x67f822f1,0x32e84f97,0x047eb2d0,0x68ff7785,0xd7ad9257,0x28e023c6,0x41c866ca,0x41a455b1,0x7f833133,0xb08c9ae0,0x5039a4e2,0xdaaa564f,0x5906be4a,0x7b575df1,0xff46c736,0x1b427c8c,0x005420a5,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xd9865148,0x56f320e0,0x81fab787,0xd3da6d61,0xd881f8d7,0x5ed04bca,0x5eb80725,0xbc882c18,0x8e32dddb,0xb0ae349b,0x9da93079,0x3e2ef207,0x1a25ac63,0x4e65f38b,0x4fd383d3,0xf28e5979,0x0b128a45,0x9e530dbb,0x600fae5a,0x2c5d3711,0x00000000,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x8f5b2e40,0x31297773,0x0d317fe6,0x8c0a1bcd,0x050c32a8,0x5ea843c3,0x51c3cbda,0x28576cf2,0x8b05dcbc,0xdc8bf2a3,0xc1e1c0a5,0x08f0940b,0xe40394b9,0xa62961e5,0x685e0841,0xdb9f8872,0xe1d97528,0x1c1f4b5d,0x0854a024,0x9185413b,0x00000017,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xb7cbc040,0x4f30ecd7,0x0f7d7230,0xf168e0bc,0xb3871c32,0xa80c435d,0xc1c817dc,0x96c94dad,0x662320b1,0x06e4d985,0xc1d018c3,0xc8bf3a4a,0x05ea9705,0xec256407,0xda526b21,0x88600539,0xdd5fb2dd,0x0cbf553d,0x7549b353,0xe04fe897,0x00000c9c,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x13d5a280,0xb05fac49,0x599f8e0a,0x22892560,0xc6d53376,0x969c5082,0x75dcdcf2,0x4883dfaa,0x0eef9fbb,0xb75d41e9,0x7a2d5921,0x37156c4c,0x3075691e,0x4c27ebc9,0xb06dc049,0x83c2d12f,0x55966b6b,0xdf23f359,0x39baaac4,0xeb1361a5,0x0006cc90,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xc4ff3b80,0xc3f28bad,0xa9a21fcd,0xc0774b50,0xf5c2f124,0xc6dfb701,0xfeebf7b7,0x5f9a718d,0x1c1bbab0,0x8fa2c98b,0x569f654e,0xe8a1cd86,0x4fc01367,0x59ad063d,0xcb9767cc,0x8ac794e4,0x78ac5360,0x28852181,0x585ab8e5,0xa38604b6,0x03b112af,0x00000000,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xbb948a00,0x28a46307,0xc4a96487,0x413d301c,0x669be019,0xc2581512,0x690b7880,0x487619a7,0x5f2a1874,0x8d063813,0x5f2b66f6,0x387c6577,0x9d0a9cd3,0x0a9f6987,0x56ccc3c1,0xe5256d1f,0xfe3d98cb,0x28ce52cd,0x519d1d52,0x6d4a93b8,0x04d6380d,0x00000002,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x50d00200,0x628a8b42,0x514c5e71,0xeeb37fd8,0x83da6de8,0x0a839b22,0xdb515eeb,0xe90c2134,0x6a2f780b,0xac6ce2ab,0x6ae7b5cb,0x1c83e2bf,0x7ed86056,0xd9cd1fb1,0xcec7d152,0x359d1a42,0x07ed284d,0x79a39b75,0xf3892640,0x32135c84,0xa9fcdf65,0x0000011c,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xd3611c00,0xa8d93ec8,0x185c62e4,0x6790e9fd,0x2328f734,0xd5000d25,0xa722a65f,0x44ba6b51,0xe654969b,0xa465bb14,0x4c86d6f9,0xd127c62d,0x5c056fc3,0xcfc79474,0xb2d61bf4,0xbd24910e,0x658c5ad3,0x78c03aea,0x161337c3,0xc6bd51bf,0x4a43ea21,0x00009de6,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x133ea400,0x515a122e,0x9b9b3dba,0xd9f2b460,0xa3e21645,0xfb0757be,0x5c5aef87,0x6421f29c,0xa94020bb,0xd4d380ac,0xbf521572,0xd537b34d,0x67096e61,0x107becff,0xe5999dc0,0xa76d0735,0xb966bc46,0x7360e8ee,0x54bc2630,0x03c0a9bd,0x7befc8de,0x005833a3,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xd33c4000,0xc2aa39ea,0x8752b8cd,0x98857657,0x2f2c874a,0x34215b3c,0xf326bc7d,0x531877f3,0x34126968,0xb6f8611f,0x9e2c1097,0xef54dbbb,0xf54e1707,0x45b54fa9,0x2668bc09,0x2d540e51,0x49c9e7be,0xe6830648,0xa9d57b40,0x1c5f7a7f,0xb6e0fce2,0x319d0bf5,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xa5204000,0x426ace01,0xa5daac8b,0x63980793,0xb838a140,0x86e4ad16,0xb8f0c2ea,0x10dbf12c,0x7e6db417,0xa2af02ac,0x96f565ee,0x8f107544,0xf13b0b7e,0x7bb21f43,0xc1528140,0xac9c1bf6,0xcb5c42b7,0x90368ef1,0x31eacfc2,0x1214624f,0x956f3c12,0x19f3c62c,0x0000001c}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x2c648000,0xe0e97cf0,0x96b6676b,0xccb45234,0x104bf6b8,0xee6ab6f5,0x794f29c0,0x9d6f8b81,0x1a90b527,0xc7cf8660,0x17f42218,0x9762e11e,0x93ac8e2d,0x8b95d4bf,0x410db6c6,0x7107f2ba,0xfa9e0cc0,0x3f1d85e5,0x77ea7cf6,0x4fa0112a,0x3970424e,0xcd07056d,0x00001006}} +#if (PARAM_N1 == 150) + , + {{0x00000000,0x00000000,0x00000000,0x00000000,0x7db58000,0x2612bde9,0x8abd62f2,0x8b8b3432,0x5b9eac1d,0xe7470eb8,0xa874f9c8,0x670d1b58,0x411805bf,0xbc2a292f,0xc12f943a,0xedc74447,0xcc15a42d,0x27092a01,0x5adff402,0xe79060f3,0xe8c15280,0x3df3e30e,0xdba5c166,0xb8e9db62,0xfb7612f7,0xbb081db7,0x000933e7,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xacee0000,0x02d5cafc,0x357d33fe,0xac7a2d38,0xf7bb8114,0xb5148294,0x63a06825,0x9393cf41,0xa1e352a7,0xc85fcf51,0xaf81b1f4,0x7733797b,0xfc82ea8d,0x914c4909,0x8979113e,0xdf780cb0,0x8fc3b285,0xd0ff449e,0xfbd3cf1b,0xe732d526,0x6042f736,0x20b12e5d,0x055201f8,0x00000000}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0xa6860000,0xa66f2510,0x21df42d7,0x631c51b7,0x30222108,0x64f000b4,0xfc5c9df2,0xe507a10e,0x394f1b88,0x9fc3aa83,0x267c9378,0x60f5b4fd,0xf8328456,0x916682cf,0x0377096a,0x10df62c0,0xace6e7eb,0xa492f049,0x92478b30,0x90960fb0,0x06f9e2f4,0x071ffc59,0x18bb256b,0x00000003}}, + {{0x00000000,0x00000000,0x00000000,0x00000000,0x92840000,0x851fb7c1,0xd8d12a5b,0x1297e14d,0x33ff5aea,0x24a06994,0xde448c07,0x32785ec7,0x945a2236,0x9ca5e8e3,0x8cfe68ad,0xcff80c54,0x6d998a9c,0x3210a5db,0x07bf8471,0xe2e3dc82,0x4f4be3bb,0x6e18cb2b,0xb5eb8e80,0xb7ed3175,0x166afb4c,0x2cbddc2a,0x7da7ecb6,0x000001d0}} +#endif +#endif +#endif +#endif +#endif + }; #endif // SIG_PKP_RANK_UNRANK_TABLE_H From a39a1723412769eefcf3e16a410db38176c7970c Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Wed, 24 Jan 2024 12:29:33 +0100 Subject: [PATCH 069/107] Use fixed HAETAE reference --- mupq | 2 +- skiplist.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mupq b/mupq index d5a9d227..14f4e132 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit d5a9d2279d9c594c9c188048a4eee8923c096733 +Subproject commit 14f4e13261f792c82caeee90d9d160b4000f9502 diff --git a/skiplist.py b/skiplist.py index 11534aeb..07e9c008 100644 --- a/skiplist.py +++ b/skiplist.py @@ -274,11 +274,11 @@ {'scheme': 'perk-256-short-5', 'implementation': 'm4', 'estmemory': 109568}, {'scheme': 'perk-256-short-5', 'implementation': 'ref', 'estmemory': 4221952}, {'scheme': 'haetae2', 'implementation': 'ref', 'estmemory': 59392}, - {'scheme': 'haetae5', 'implementation': 'ref', 'estmemory': 109568}, {'scheme': 'haetae3', 'implementation': 'ref', 'estmemory': 88064}, + {'scheme': 'haetae5', 'implementation': 'ref', 'estmemory': 109568}, {'scheme': 'haetae2', 'implementation': 'm4f', 'estmemory': 60416}, - {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, {'scheme': 'haetae3', 'implementation': 'm4f', 'estmemory': 90112}, + {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, {'scheme': 'mqom_cat5_gf251_short', 'implementation': 'ref', 'estmemory': 4146176}, {'scheme': 'mqom_cat3_gf251_fast', 'implementation': 'ref', 'estmemory': 1307648}, {'scheme': 'mqom_cat3_gf31_short', 'implementation': 'ref', 'estmemory': 2688000}, From c8394987d8f1def399346c21d500e91f3543f5ad Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 10:55:57 +0800 Subject: [PATCH 070/107] update PQClean --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 14f4e132..dbe94161 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 14f4e13261f792c82caeee90d9d160b4000f9502 +Subproject commit dbe9416182ce4f4d9cdb9a42da31dbf5ba5e6e4c From 5087fd85011b9b9fa5772634e496c0820f13e938 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 10:56:33 +0800 Subject: [PATCH 071/107] remove Kyber-90s; won't be standardized --- crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/api.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/cbd.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/cbd.h | 1 - .../kyber1024-90s/m4fspeed/fastaddsub.S | 1 - .../kyber1024-90s/m4fspeed/fastbasemul.S | 1 - .../kyber1024-90s/m4fspeed/fastinvntt.S | 1 - crypto_kem/kyber1024-90s/m4fspeed/fastntt.S | 1 - crypto_kem/kyber1024-90s/m4fspeed/indcpa.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/indcpa.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/kem.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/macros.i | 1 - crypto_kem/kyber1024-90s/m4fspeed/matacc.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/matacc.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/matacc.i | 1 - .../kyber1024-90s/m4fspeed/matacc_asm.S | 1 - crypto_kem/kyber1024-90s/m4fspeed/ntt.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/ntt.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/params.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/poly.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/poly.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/poly_asm.S | 1 - crypto_kem/kyber1024-90s/m4fspeed/polyvec.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/polyvec.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/reduce.S | 1 - crypto_kem/kyber1024-90s/m4fspeed/symmetric.h | 1 - crypto_kem/kyber1024-90s/m4fspeed/verify.c | 1 - crypto_kem/kyber1024-90s/m4fspeed/verify.h | 1 - crypto_kem/kyber1024-90s/m4fstack/aes256ctr.c | 1 - crypto_kem/kyber1024-90s/m4fstack/aes256ctr.h | 1 - crypto_kem/kyber1024-90s/m4fstack/api.h | 1 - crypto_kem/kyber1024-90s/m4fstack/cbd.c | 1 - crypto_kem/kyber1024-90s/m4fstack/cbd.h | 1 - .../kyber1024-90s/m4fstack/fastaddsub.S | 1 - .../kyber1024-90s/m4fstack/fastbasemul.S | 1 - .../kyber1024-90s/m4fstack/fastinvntt.S | 1 - crypto_kem/kyber1024-90s/m4fstack/fastntt.S | 1 - crypto_kem/kyber1024-90s/m4fstack/indcpa.c | 1 - crypto_kem/kyber1024-90s/m4fstack/indcpa.h | 1 - crypto_kem/kyber1024-90s/m4fstack/kem.c | 1 - crypto_kem/kyber1024-90s/m4fstack/macros.i | 1 - crypto_kem/kyber1024-90s/m4fstack/matacc.c | 1 - crypto_kem/kyber1024-90s/m4fstack/matacc.h | 1 - crypto_kem/kyber1024-90s/m4fstack/matacc.i | 1 - .../kyber1024-90s/m4fstack/matacc_asm.S | 1 - crypto_kem/kyber1024-90s/m4fstack/ntt.c | 1 - crypto_kem/kyber1024-90s/m4fstack/ntt.h | 1 - crypto_kem/kyber1024-90s/m4fstack/params.h | 1 - crypto_kem/kyber1024-90s/m4fstack/poly.c | 1 - crypto_kem/kyber1024-90s/m4fstack/poly.h | 1 - crypto_kem/kyber1024-90s/m4fstack/poly_asm.S | 1 - crypto_kem/kyber1024-90s/m4fstack/polyvec.c | 1 - crypto_kem/kyber1024-90s/m4fstack/polyvec.h | 1 - crypto_kem/kyber1024-90s/m4fstack/reduce.S | 1 - crypto_kem/kyber1024-90s/m4fstack/symmetric.h | 1 - crypto_kem/kyber1024-90s/m4fstack/verify.c | 1 - crypto_kem/kyber1024-90s/m4fstack/verify.h | 1 - crypto_kem/kyber512-90s/m4fspeed/aes256ctr.c | 1 - crypto_kem/kyber512-90s/m4fspeed/aes256ctr.h | 1 - crypto_kem/kyber512-90s/m4fspeed/api.h | 1 - crypto_kem/kyber512-90s/m4fspeed/cbd.c | 1 - crypto_kem/kyber512-90s/m4fspeed/cbd.h | 1 - crypto_kem/kyber512-90s/m4fspeed/fastaddsub.S | 1 - .../kyber512-90s/m4fspeed/fastbasemul.S | 1 - crypto_kem/kyber512-90s/m4fspeed/fastinvntt.S | 1 - crypto_kem/kyber512-90s/m4fspeed/fastntt.S | 1 - crypto_kem/kyber512-90s/m4fspeed/indcpa.c | 1 - crypto_kem/kyber512-90s/m4fspeed/indcpa.h | 1 - crypto_kem/kyber512-90s/m4fspeed/kem.c | 1 - crypto_kem/kyber512-90s/m4fspeed/macros.i | 1 - crypto_kem/kyber512-90s/m4fspeed/matacc.c | 1 - crypto_kem/kyber512-90s/m4fspeed/matacc.h | 1 - crypto_kem/kyber512-90s/m4fspeed/matacc.i | 1 - crypto_kem/kyber512-90s/m4fspeed/matacc_asm.S | 1 - crypto_kem/kyber512-90s/m4fspeed/ntt.c | 1 - crypto_kem/kyber512-90s/m4fspeed/ntt.h | 1 - crypto_kem/kyber512-90s/m4fspeed/params.h | 1 - crypto_kem/kyber512-90s/m4fspeed/poly.c | 1 - crypto_kem/kyber512-90s/m4fspeed/poly.h | 1 - crypto_kem/kyber512-90s/m4fspeed/poly_asm.S | 1 - crypto_kem/kyber512-90s/m4fspeed/polyvec.c | 1 - crypto_kem/kyber512-90s/m4fspeed/polyvec.h | 1 - crypto_kem/kyber512-90s/m4fspeed/reduce.S | 1 - crypto_kem/kyber512-90s/m4fspeed/symmetric.h | 1 - crypto_kem/kyber512-90s/m4fspeed/verify.c | 1 - crypto_kem/kyber512-90s/m4fspeed/verify.h | 1 - crypto_kem/kyber512-90s/m4fstack/aes256ctr.c | 1 - crypto_kem/kyber512-90s/m4fstack/aes256ctr.h | 1 - crypto_kem/kyber512-90s/m4fstack/api.h | 1 - crypto_kem/kyber512-90s/m4fstack/cbd.c | 1 - crypto_kem/kyber512-90s/m4fstack/cbd.h | 1 - crypto_kem/kyber512-90s/m4fstack/fastaddsub.S | 1 - .../kyber512-90s/m4fstack/fastbasemul.S | 1 - crypto_kem/kyber512-90s/m4fstack/fastinvntt.S | 1 - crypto_kem/kyber512-90s/m4fstack/fastntt.S | 1 - crypto_kem/kyber512-90s/m4fstack/indcpa.c | 1 - crypto_kem/kyber512-90s/m4fstack/indcpa.h | 1 - crypto_kem/kyber512-90s/m4fstack/kem.c | 1 - crypto_kem/kyber512-90s/m4fstack/macros.i | 1 - crypto_kem/kyber512-90s/m4fstack/matacc.c | 1 - crypto_kem/kyber512-90s/m4fstack/matacc.h | 1 - crypto_kem/kyber512-90s/m4fstack/matacc.i | 1 - crypto_kem/kyber512-90s/m4fstack/matacc_asm.S | 1 - crypto_kem/kyber512-90s/m4fstack/ntt.c | 1 - crypto_kem/kyber512-90s/m4fstack/ntt.h | 1 - crypto_kem/kyber512-90s/m4fstack/params.h | 1 - crypto_kem/kyber512-90s/m4fstack/poly.c | 1 - crypto_kem/kyber512-90s/m4fstack/poly.h | 1 - crypto_kem/kyber512-90s/m4fstack/poly_asm.S | 1 - crypto_kem/kyber512-90s/m4fstack/polyvec.c | 1 - crypto_kem/kyber512-90s/m4fstack/polyvec.h | 1 - crypto_kem/kyber512-90s/m4fstack/reduce.S | 1 - crypto_kem/kyber512-90s/m4fstack/symmetric.h | 1 - crypto_kem/kyber512-90s/m4fstack/verify.c | 1 - crypto_kem/kyber512-90s/m4fstack/verify.h | 1 - crypto_kem/kyber768-90s/m4fspeed/aes256ctr.c | 96 ----- crypto_kem/kyber768-90s/m4fspeed/aes256ctr.h | 19 - crypto_kem/kyber768-90s/m4fspeed/api.h | 1 - crypto_kem/kyber768-90s/m4fspeed/cbd.c | 1 - crypto_kem/kyber768-90s/m4fspeed/cbd.h | 1 - crypto_kem/kyber768-90s/m4fspeed/fastaddsub.S | 1 - .../kyber768-90s/m4fspeed/fastbasemul.S | 1 - crypto_kem/kyber768-90s/m4fspeed/fastinvntt.S | 1 - crypto_kem/kyber768-90s/m4fspeed/fastntt.S | 1 - crypto_kem/kyber768-90s/m4fspeed/indcpa.c | 1 - crypto_kem/kyber768-90s/m4fspeed/indcpa.h | 1 - crypto_kem/kyber768-90s/m4fspeed/kem.c | 1 - crypto_kem/kyber768-90s/m4fspeed/macros.i | 1 - crypto_kem/kyber768-90s/m4fspeed/matacc.c | 92 ---- crypto_kem/kyber768-90s/m4fspeed/matacc.h | 63 --- crypto_kem/kyber768-90s/m4fspeed/matacc.i | 1 - crypto_kem/kyber768-90s/m4fspeed/matacc_asm.S | 403 ------------------ crypto_kem/kyber768-90s/m4fspeed/ntt.c | 1 - crypto_kem/kyber768-90s/m4fspeed/ntt.h | 1 - crypto_kem/kyber768-90s/m4fspeed/params.h | 1 - crypto_kem/kyber768-90s/m4fspeed/poly.c | 1 - crypto_kem/kyber768-90s/m4fspeed/poly.h | 1 - crypto_kem/kyber768-90s/m4fspeed/poly_asm.S | 1 - crypto_kem/kyber768-90s/m4fspeed/polyvec.c | 1 - crypto_kem/kyber768-90s/m4fspeed/polyvec.h | 1 - crypto_kem/kyber768-90s/m4fspeed/reduce.S | 1 - crypto_kem/kyber768-90s/m4fspeed/symmetric.h | 25 -- crypto_kem/kyber768-90s/m4fspeed/verify.c | 1 - crypto_kem/kyber768-90s/m4fspeed/verify.h | 1 - crypto_kem/kyber768-90s/m4fstack/aes256ctr.c | 1 - crypto_kem/kyber768-90s/m4fstack/aes256ctr.h | 1 - crypto_kem/kyber768-90s/m4fstack/api.h | 1 - crypto_kem/kyber768-90s/m4fstack/cbd.c | 1 - crypto_kem/kyber768-90s/m4fstack/cbd.h | 1 - crypto_kem/kyber768-90s/m4fstack/fastaddsub.S | 1 - .../kyber768-90s/m4fstack/fastbasemul.S | 1 - crypto_kem/kyber768-90s/m4fstack/fastinvntt.S | 1 - crypto_kem/kyber768-90s/m4fstack/fastntt.S | 1 - crypto_kem/kyber768-90s/m4fstack/indcpa.c | 1 - crypto_kem/kyber768-90s/m4fstack/indcpa.h | 1 - crypto_kem/kyber768-90s/m4fstack/kem.c | 1 - crypto_kem/kyber768-90s/m4fstack/macros.i | 1 - crypto_kem/kyber768-90s/m4fstack/matacc.c | 45 -- crypto_kem/kyber768-90s/m4fstack/matacc.h | 26 -- crypto_kem/kyber768-90s/m4fstack/matacc.i | 1 - crypto_kem/kyber768-90s/m4fstack/matacc_asm.S | 159 ------- crypto_kem/kyber768-90s/m4fstack/ntt.c | 1 - crypto_kem/kyber768-90s/m4fstack/ntt.h | 1 - crypto_kem/kyber768-90s/m4fstack/params.h | 1 - crypto_kem/kyber768-90s/m4fstack/poly.c | 1 - crypto_kem/kyber768-90s/m4fstack/poly.h | 1 - crypto_kem/kyber768-90s/m4fstack/poly_asm.S | 1 - crypto_kem/kyber768-90s/m4fstack/polyvec.c | 1 - crypto_kem/kyber768-90s/m4fstack/polyvec.h | 1 - crypto_kem/kyber768-90s/m4fstack/reduce.S | 1 - crypto_kem/kyber768-90s/m4fstack/symmetric.h | 1 - crypto_kem/kyber768-90s/m4fstack/verify.c | 1 - crypto_kem/kyber768-90s/m4fstack/verify.h | 1 - 174 files changed, 1093 deletions(-) delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/api.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/cbd.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/cbd.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/fastaddsub.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/fastbasemul.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/fastinvntt.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/fastntt.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/indcpa.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/indcpa.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/kem.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/macros.i delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/matacc.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/matacc.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/matacc.i delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/matacc_asm.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/ntt.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/ntt.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/params.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/poly.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/poly.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/poly_asm.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/polyvec.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/polyvec.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/reduce.S delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/symmetric.h delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/verify.c delete mode 120000 crypto_kem/kyber1024-90s/m4fspeed/verify.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/aes256ctr.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/aes256ctr.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/api.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/cbd.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/cbd.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/fastaddsub.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/fastbasemul.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/fastinvntt.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/fastntt.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/indcpa.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/indcpa.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/kem.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/macros.i delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/matacc.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/matacc.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/matacc.i delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/matacc_asm.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/ntt.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/ntt.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/params.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/poly.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/poly.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/poly_asm.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/polyvec.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/polyvec.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/reduce.S delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/symmetric.h delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/verify.c delete mode 120000 crypto_kem/kyber1024-90s/m4fstack/verify.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/aes256ctr.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/aes256ctr.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/api.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/cbd.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/cbd.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/fastaddsub.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/fastbasemul.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/fastinvntt.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/fastntt.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/indcpa.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/indcpa.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/kem.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/macros.i delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/matacc.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/matacc.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/matacc.i delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/matacc_asm.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/ntt.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/ntt.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/params.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/poly.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/poly.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/poly_asm.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/polyvec.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/polyvec.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/reduce.S delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/symmetric.h delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/verify.c delete mode 120000 crypto_kem/kyber512-90s/m4fspeed/verify.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/aes256ctr.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/aes256ctr.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/api.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/cbd.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/cbd.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/fastaddsub.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/fastbasemul.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/fastinvntt.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/fastntt.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/indcpa.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/indcpa.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/kem.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/macros.i delete mode 120000 crypto_kem/kyber512-90s/m4fstack/matacc.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/matacc.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/matacc.i delete mode 120000 crypto_kem/kyber512-90s/m4fstack/matacc_asm.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/ntt.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/ntt.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/params.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/poly.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/poly.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/poly_asm.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/polyvec.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/polyvec.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/reduce.S delete mode 120000 crypto_kem/kyber512-90s/m4fstack/symmetric.h delete mode 120000 crypto_kem/kyber512-90s/m4fstack/verify.c delete mode 120000 crypto_kem/kyber512-90s/m4fstack/verify.h delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/aes256ctr.c delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/aes256ctr.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/api.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/cbd.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/cbd.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/fastaddsub.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/fastbasemul.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/fastinvntt.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/fastntt.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/indcpa.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/indcpa.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/kem.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/macros.i delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/matacc.c delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/matacc.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/matacc.i delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/matacc_asm.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/ntt.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/ntt.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/params.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/poly.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/poly.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/poly_asm.S delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/polyvec.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/polyvec.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/reduce.S delete mode 100644 crypto_kem/kyber768-90s/m4fspeed/symmetric.h delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/verify.c delete mode 120000 crypto_kem/kyber768-90s/m4fspeed/verify.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/aes256ctr.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/aes256ctr.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/api.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/cbd.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/cbd.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/fastaddsub.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/fastbasemul.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/fastinvntt.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/fastntt.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/indcpa.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/indcpa.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/kem.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/macros.i delete mode 100644 crypto_kem/kyber768-90s/m4fstack/matacc.c delete mode 100644 crypto_kem/kyber768-90s/m4fstack/matacc.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/matacc.i delete mode 100644 crypto_kem/kyber768-90s/m4fstack/matacc_asm.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/ntt.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/ntt.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/params.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/poly.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/poly.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/poly_asm.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/polyvec.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/polyvec.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/reduce.S delete mode 120000 crypto_kem/kyber768-90s/m4fstack/symmetric.h delete mode 120000 crypto_kem/kyber768-90s/m4fstack/verify.c delete mode 120000 crypto_kem/kyber768-90s/m4fstack/verify.h diff --git a/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.c b/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.c deleted file mode 120000 index d7413cfa..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.h b/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.h deleted file mode 120000 index 4b8193b8..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/aes256ctr.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/api.h b/crypto_kem/kyber1024-90s/m4fspeed/api.h deleted file mode 120000 index 35f9f710..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber1024/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/cbd.c b/crypto_kem/kyber1024-90s/m4fspeed/cbd.c deleted file mode 120000 index 37d243ad..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/cbd.h b/crypto_kem/kyber1024-90s/m4fspeed/cbd.h deleted file mode 120000 index c00c0559..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/fastaddsub.S b/crypto_kem/kyber1024-90s/m4fspeed/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/fastbasemul.S b/crypto_kem/kyber1024-90s/m4fspeed/fastbasemul.S deleted file mode 120000 index 7156a2a8..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/fastinvntt.S b/crypto_kem/kyber1024-90s/m4fspeed/fastinvntt.S deleted file mode 120000 index 38ea2e36..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/fastntt.S b/crypto_kem/kyber1024-90s/m4fspeed/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/indcpa.c b/crypto_kem/kyber1024-90s/m4fspeed/indcpa.c deleted file mode 120000 index 04181f8d..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/indcpa.h b/crypto_kem/kyber1024-90s/m4fspeed/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/kem.c b/crypto_kem/kyber1024-90s/m4fspeed/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/macros.i b/crypto_kem/kyber1024-90s/m4fspeed/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/matacc.c b/crypto_kem/kyber1024-90s/m4fspeed/matacc.c deleted file mode 120000 index 84bf5550..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/matacc.h b/crypto_kem/kyber1024-90s/m4fspeed/matacc.h deleted file mode 120000 index 6cd6abe5..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/matacc.i b/crypto_kem/kyber1024-90s/m4fspeed/matacc.i deleted file mode 120000 index e388a0ad..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/matacc_asm.S b/crypto_kem/kyber1024-90s/m4fspeed/matacc_asm.S deleted file mode 120000 index 8e6ccb39..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/ntt.c b/crypto_kem/kyber1024-90s/m4fspeed/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/ntt.h b/crypto_kem/kyber1024-90s/m4fspeed/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/params.h b/crypto_kem/kyber1024-90s/m4fspeed/params.h deleted file mode 120000 index 5d6db01e..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber1024/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/poly.c b/crypto_kem/kyber1024-90s/m4fspeed/poly.c deleted file mode 120000 index ed549db6..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/poly.h b/crypto_kem/kyber1024-90s/m4fspeed/poly.h deleted file mode 120000 index 6f495407..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/poly_asm.S b/crypto_kem/kyber1024-90s/m4fspeed/poly_asm.S deleted file mode 120000 index 4424e11a..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/polyvec.c b/crypto_kem/kyber1024-90s/m4fspeed/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/polyvec.h b/crypto_kem/kyber1024-90s/m4fspeed/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/reduce.S b/crypto_kem/kyber1024-90s/m4fspeed/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/symmetric.h b/crypto_kem/kyber1024-90s/m4fspeed/symmetric.h deleted file mode 120000 index 1c2c04a2..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/verify.c b/crypto_kem/kyber1024-90s/m4fspeed/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fspeed/verify.h b/crypto_kem/kyber1024-90s/m4fspeed/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber1024-90s/m4fspeed/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.c b/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.c deleted file mode 120000 index d7413cfa..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.h b/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.h deleted file mode 120000 index 4b8193b8..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/aes256ctr.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/api.h b/crypto_kem/kyber1024-90s/m4fstack/api.h deleted file mode 120000 index 35f9f710..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber1024/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/cbd.c b/crypto_kem/kyber1024-90s/m4fstack/cbd.c deleted file mode 120000 index 37d243ad..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/cbd.h b/crypto_kem/kyber1024-90s/m4fstack/cbd.h deleted file mode 120000 index c00c0559..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/fastaddsub.S b/crypto_kem/kyber1024-90s/m4fstack/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/fastbasemul.S b/crypto_kem/kyber1024-90s/m4fstack/fastbasemul.S deleted file mode 120000 index 7ba7f7e4..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/fastinvntt.S b/crypto_kem/kyber1024-90s/m4fstack/fastinvntt.S deleted file mode 120000 index 8d3a7e52..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber1024/m4fstack/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/fastntt.S b/crypto_kem/kyber1024-90s/m4fstack/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/indcpa.c b/crypto_kem/kyber1024-90s/m4fstack/indcpa.c deleted file mode 120000 index 7d86b771..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/indcpa.h b/crypto_kem/kyber1024-90s/m4fstack/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/kem.c b/crypto_kem/kyber1024-90s/m4fstack/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/macros.i b/crypto_kem/kyber1024-90s/m4fstack/macros.i deleted file mode 120000 index 6e838919..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/macros.i +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/matacc.c b/crypto_kem/kyber1024-90s/m4fstack/matacc.c deleted file mode 120000 index b1cfe3c1..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/matacc.h b/crypto_kem/kyber1024-90s/m4fstack/matacc.h deleted file mode 120000 index f4274b16..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/matacc.i b/crypto_kem/kyber1024-90s/m4fstack/matacc.i deleted file mode 120000 index 3804c85d..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/matacc_asm.S b/crypto_kem/kyber1024-90s/m4fstack/matacc_asm.S deleted file mode 120000 index c3f105c1..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/ntt.c b/crypto_kem/kyber1024-90s/m4fstack/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/ntt.h b/crypto_kem/kyber1024-90s/m4fstack/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/params.h b/crypto_kem/kyber1024-90s/m4fstack/params.h deleted file mode 120000 index 5d6db01e..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber1024/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/poly.c b/crypto_kem/kyber1024-90s/m4fstack/poly.c deleted file mode 120000 index 209dba88..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/poly.h b/crypto_kem/kyber1024-90s/m4fstack/poly.h deleted file mode 120000 index e02915ca..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/poly_asm.S b/crypto_kem/kyber1024-90s/m4fstack/poly_asm.S deleted file mode 120000 index 9b529775..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/polyvec.c b/crypto_kem/kyber1024-90s/m4fstack/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/polyvec.h b/crypto_kem/kyber1024-90s/m4fstack/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/reduce.S b/crypto_kem/kyber1024-90s/m4fstack/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/symmetric.h b/crypto_kem/kyber1024-90s/m4fstack/symmetric.h deleted file mode 120000 index 1c2c04a2..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/verify.c b/crypto_kem/kyber1024-90s/m4fstack/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber1024-90s/m4fstack/verify.h b/crypto_kem/kyber1024-90s/m4fstack/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber1024-90s/m4fstack/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.c b/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.c deleted file mode 120000 index d7413cfa..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.h b/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.h deleted file mode 120000 index 4b8193b8..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/aes256ctr.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/api.h b/crypto_kem/kyber512-90s/m4fspeed/api.h deleted file mode 120000 index b5cb28ed..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/cbd.c b/crypto_kem/kyber512-90s/m4fspeed/cbd.c deleted file mode 120000 index e47a1c19..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/cbd.h b/crypto_kem/kyber512-90s/m4fspeed/cbd.h deleted file mode 120000 index c817e33a..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/fastaddsub.S b/crypto_kem/kyber512-90s/m4fspeed/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/fastbasemul.S b/crypto_kem/kyber512-90s/m4fspeed/fastbasemul.S deleted file mode 120000 index 7156a2a8..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/fastinvntt.S b/crypto_kem/kyber512-90s/m4fspeed/fastinvntt.S deleted file mode 120000 index 38ea2e36..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/fastntt.S b/crypto_kem/kyber512-90s/m4fspeed/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/indcpa.c b/crypto_kem/kyber512-90s/m4fspeed/indcpa.c deleted file mode 120000 index 024ac9eb..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/indcpa.h b/crypto_kem/kyber512-90s/m4fspeed/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/kem.c b/crypto_kem/kyber512-90s/m4fspeed/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/macros.i b/crypto_kem/kyber512-90s/m4fspeed/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/matacc.c b/crypto_kem/kyber512-90s/m4fspeed/matacc.c deleted file mode 120000 index 84bf5550..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/matacc.h b/crypto_kem/kyber512-90s/m4fspeed/matacc.h deleted file mode 120000 index 6cd6abe5..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/matacc.i b/crypto_kem/kyber512-90s/m4fspeed/matacc.i deleted file mode 120000 index e388a0ad..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/matacc_asm.S b/crypto_kem/kyber512-90s/m4fspeed/matacc_asm.S deleted file mode 120000 index 8e6ccb39..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/ntt.c b/crypto_kem/kyber512-90s/m4fspeed/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/ntt.h b/crypto_kem/kyber512-90s/m4fspeed/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/params.h b/crypto_kem/kyber512-90s/m4fspeed/params.h deleted file mode 120000 index fa4f5338..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/poly.c b/crypto_kem/kyber512-90s/m4fspeed/poly.c deleted file mode 120000 index de46a5b5..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/poly.h b/crypto_kem/kyber512-90s/m4fspeed/poly.h deleted file mode 120000 index f4a411b6..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/poly_asm.S b/crypto_kem/kyber512-90s/m4fspeed/poly_asm.S deleted file mode 120000 index e0377ff5..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/polyvec.c b/crypto_kem/kyber512-90s/m4fspeed/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/polyvec.h b/crypto_kem/kyber512-90s/m4fspeed/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/reduce.S b/crypto_kem/kyber512-90s/m4fspeed/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/symmetric.h b/crypto_kem/kyber512-90s/m4fspeed/symmetric.h deleted file mode 120000 index 1c2c04a2..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/verify.c b/crypto_kem/kyber512-90s/m4fspeed/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fspeed/verify.h b/crypto_kem/kyber512-90s/m4fspeed/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber512-90s/m4fspeed/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/aes256ctr.c b/crypto_kem/kyber512-90s/m4fstack/aes256ctr.c deleted file mode 120000 index d7413cfa..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/aes256ctr.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/aes256ctr.h b/crypto_kem/kyber512-90s/m4fstack/aes256ctr.h deleted file mode 120000 index 4b8193b8..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/aes256ctr.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/aes256ctr.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/api.h b/crypto_kem/kyber512-90s/m4fstack/api.h deleted file mode 120000 index b5cb28ed..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/cbd.c b/crypto_kem/kyber512-90s/m4fstack/cbd.c deleted file mode 120000 index e47a1c19..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/cbd.h b/crypto_kem/kyber512-90s/m4fstack/cbd.h deleted file mode 120000 index c817e33a..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/fastaddsub.S b/crypto_kem/kyber512-90s/m4fstack/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/fastbasemul.S b/crypto_kem/kyber512-90s/m4fstack/fastbasemul.S deleted file mode 120000 index 7ba7f7e4..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/fastinvntt.S b/crypto_kem/kyber512-90s/m4fstack/fastinvntt.S deleted file mode 120000 index 0ebaf18e..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fstack/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/fastntt.S b/crypto_kem/kyber512-90s/m4fstack/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/indcpa.c b/crypto_kem/kyber512-90s/m4fstack/indcpa.c deleted file mode 120000 index 87420787..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fstack/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/indcpa.h b/crypto_kem/kyber512-90s/m4fstack/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/kem.c b/crypto_kem/kyber512-90s/m4fstack/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/macros.i b/crypto_kem/kyber512-90s/m4fstack/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/matacc.c b/crypto_kem/kyber512-90s/m4fstack/matacc.c deleted file mode 120000 index b1cfe3c1..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/matacc.h b/crypto_kem/kyber512-90s/m4fstack/matacc.h deleted file mode 120000 index f4274b16..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/matacc.i b/crypto_kem/kyber512-90s/m4fstack/matacc.i deleted file mode 120000 index fb867f14..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/matacc_asm.S b/crypto_kem/kyber512-90s/m4fstack/matacc_asm.S deleted file mode 120000 index c3f105c1..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/ntt.c b/crypto_kem/kyber512-90s/m4fstack/ntt.c deleted file mode 120000 index 812f843b..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/ntt.h b/crypto_kem/kyber512-90s/m4fstack/ntt.h deleted file mode 120000 index 67b48eb7..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/params.h b/crypto_kem/kyber512-90s/m4fstack/params.h deleted file mode 120000 index fa4f5338..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/poly.c b/crypto_kem/kyber512-90s/m4fstack/poly.c deleted file mode 120000 index 645f8c91..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fstack/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/poly.h b/crypto_kem/kyber512-90s/m4fstack/poly.h deleted file mode 120000 index db24efb8..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber512/m4fstack/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/poly_asm.S b/crypto_kem/kyber512-90s/m4fstack/poly_asm.S deleted file mode 120000 index 3e764454..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/polyvec.c b/crypto_kem/kyber512-90s/m4fstack/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/polyvec.h b/crypto_kem/kyber512-90s/m4fstack/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/reduce.S b/crypto_kem/kyber512-90s/m4fstack/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/symmetric.h b/crypto_kem/kyber512-90s/m4fstack/symmetric.h deleted file mode 120000 index 1c2c04a2..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768-90s/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/verify.c b/crypto_kem/kyber512-90s/m4fstack/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber512-90s/m4fstack/verify.h b/crypto_kem/kyber512-90s/m4fstack/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber512-90s/m4fstack/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.c b/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.c deleted file mode 100644 index 35e5be84..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "aes256ctr.h" -#include "aes.h" -#include "aes-publicinputs.h" -#include -#include -#include - -static inline void br_enc32be(unsigned char *dst, uint32_t x) { - dst[3] = (unsigned char)x; - dst[2] = (unsigned char)(x >> 8); - dst[1] = (unsigned char)(x >> 16); - dst[0] = (unsigned char)(x >> 24); -} - -static void aes256_ctr_xof(unsigned char *out, size_t outlen, const unsigned char *iv, uint32_t ctr, const aes256ctx_publicinputs *ctx) { - uint8_t ivw[16]; - uint8_t buf[AES_BLOCKBYTES]; - size_t i; - - memcpy(ivw, iv, AESCTR_NONCEBYTES); - br_enc32be(ivw + AESCTR_NONCEBYTES, ctr); - - while (outlen > AES_BLOCKBYTES) { - aes256_ecb_publicinputs(out, ivw, 1, ctx); - br_enc32be(ivw + AESCTR_NONCEBYTES, ++ctr); - out += AES_BLOCKBYTES; - outlen -= AES_BLOCKBYTES; - } - if (outlen > 0) { - aes256_ecb_publicinputs(buf, ivw, 1, ctx); - for (i = 0; i < outlen; i++) { - out[i] = buf[i]; - } - } -} - -/************************************************* -* Name: aes256_prf -* -* Description: AES256 stream generation in CTR mode using 32-bit counter, -* nonce is zero-padded to 12 bytes, counter starts at zero -* -* Arguments: - uint8_t *output: pointer to output -* - size_t outlen: length of requested output in bytes -* - const uint8_t *key: pointer to 32-byte key -* - uint8_t nonce: 1-byte nonce (will be zero-padded to 12 bytes) -**************************************************/ -void aes256_prf(uint8_t *output, size_t outlen, const uint8_t *key, uint8_t nonce) { - uint8_t iv[12]; - for (int i = 1; i < 12; i++) { - iv[i] = 0; - } - iv[0] = nonce; - - aes256ctx ctx; - aes256_ctr_keyexp(&ctx, key); - aes256_ctr(output, outlen, iv, &ctx); - aes256_ctx_release(&ctx); -} - -/************************************************* -* Name: aes256xof_absorb -* -* Description: AES256 CTR used as a replacement for a XOF; this function -* "absorbs" a 32-byte key and two additional bytes that are zero-padded -* to a 12-byte nonce -* -* Arguments: - aes256xof_ctx *s: pointer to state to "absorb" key and IV into -* - const uint8_t *key: pointer to 32-byte key -* - uint8_t x: first additional byte to "absorb" -* - uint8_t y: second additional byte to "absorb" -**************************************************/ -void aes256xof_absorb(aes256xof_ctx *s, const uint8_t *key, uint8_t x, uint8_t y) { - aes256_ctr_keyexp_publicinputs(&s->sk_exp, key); - for (int i = 2; i < 12; i++) { - s->iv[i] = 0; - } - s->iv[0] = x; - s->iv[1] = y; - s->ctr = 0; -} - -/************************************************* -* Name: aes256xof_squeezeblocks -* -* Description: AES256 CTR used as a replacement for a XOF; this function -* generates 4 blocks out AES256-CTR output -* -* Arguments: - uint8_t *out: pointer to output -* - size_t nblocks: number of reqested 64-byte output blocks -* - aes256xof_ctx *s: AES "state", i.e. expanded key and IV -**************************************************/ -void aes256xof_squeezeblocks(uint8_t *out, size_t nblocks, aes256xof_ctx *s) { - aes256_ctr_xof(out, nblocks * 64, s->iv, s->ctr, &s->sk_exp); - s->ctr += 4 * nblocks; -} diff --git a/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.h b/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.h deleted file mode 100644 index 6f596197..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/aes256ctr.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef AES256CTR_H -#define AES256CTR_H - -#include "aes-publicinputs.h" - -#include -#include - -typedef struct { - aes256ctx_publicinputs sk_exp; - uint8_t iv[12]; - uint32_t ctr; -} aes256xof_ctx; - -void aes256_prf(uint8_t *output, size_t outlen, const uint8_t *key, uint8_t nonce); -void aes256xof_absorb(aes256xof_ctx *s, const uint8_t *key, uint8_t x, uint8_t y); -void aes256xof_squeezeblocks(uint8_t *out, size_t nblocks, aes256xof_ctx *s); - -#endif diff --git a/crypto_kem/kyber768-90s/m4fspeed/api.h b/crypto_kem/kyber768-90s/m4fspeed/api.h deleted file mode 120000 index eb61c624..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/cbd.c b/crypto_kem/kyber768-90s/m4fspeed/cbd.c deleted file mode 120000 index 37d243ad..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/cbd.h b/crypto_kem/kyber768-90s/m4fspeed/cbd.h deleted file mode 120000 index c00c0559..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/fastaddsub.S b/crypto_kem/kyber768-90s/m4fspeed/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/fastbasemul.S b/crypto_kem/kyber768-90s/m4fspeed/fastbasemul.S deleted file mode 120000 index 7156a2a8..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/fastinvntt.S b/crypto_kem/kyber768-90s/m4fspeed/fastinvntt.S deleted file mode 120000 index 38ea2e36..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/fastntt.S b/crypto_kem/kyber768-90s/m4fspeed/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/indcpa.c b/crypto_kem/kyber768-90s/m4fspeed/indcpa.c deleted file mode 120000 index 04181f8d..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/indcpa.h b/crypto_kem/kyber768-90s/m4fspeed/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/kem.c b/crypto_kem/kyber768-90s/m4fspeed/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/macros.i b/crypto_kem/kyber768-90s/m4fspeed/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/matacc.c b/crypto_kem/kyber768-90s/m4fspeed/matacc.c deleted file mode 100644 index 0e265874..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/matacc.c +++ /dev/null @@ -1,92 +0,0 @@ -#include "ntt.h" -#include "poly.h" -#include "polyvec.h" -#include "symmetric.h" -#include "matacc.h" - -void matacc_cache32(poly* r, const polyvec *b, polyvec *b_prime, unsigned char i, const unsigned char *seed, int transposed) { - unsigned char buf[XOF_BLOCKBYTES+2]; - xof_state state; - int16_t c[4]; - int32_t r_tmp[KYBER_N]; // stores intermediate accumulated values to save reductions - int j = 0; - unsigned int buflen; - - // 16-32 - buflen = XOF_BLOCKBYTES; - if (transposed) - xof_absorb(&state, seed, i, j); - else - xof_absorb(&state, seed, j, i); - - xof_squeezeblocks(buf, 1, &state); - - matacc_asm_cache_16_32(r_tmp, b->vec[j].coeffs, c, buf, zetas, &state, b_prime->vec[j].coeffs, &buflen); - - // 32-32 KYBER_K - 2 times - for(j=1;jvec[j].coeffs, c, buf, zetas, &state, b_prime->vec[j].coeffs, &buflen); - } - - // 32-16 - buflen = XOF_BLOCKBYTES; - if (transposed) - xof_absorb(&state, seed, i, j); - else - xof_absorb(&state, seed, j, i); - - xof_squeezeblocks(buf, 1, &state); - - matacc_asm_cache_32_16(r->coeffs, b->vec[j].coeffs, c, buf, zetas, &state, b_prime->vec[j].coeffs, r_tmp, &buflen); -} - -void matacc_opt32(poly* r, const polyvec *b, const polyvec *b_prime, unsigned char i, const unsigned char *seed, int transposed) { - unsigned char buf[XOF_BLOCKBYTES+2]; - xof_state state; - int16_t c[4]; - int32_t r_tmp[KYBER_N]; // stores intermediate accumulated values to save reductions - int j = 0; - unsigned int buflen; - // 16-32 - buflen = XOF_BLOCKBYTES; - if (transposed) - xof_absorb(&state, seed, i, j); - else - xof_absorb(&state, seed, j, i); - - xof_squeezeblocks(buf, 1, &state); - - matacc_asm_opt_16_32(r_tmp, b->vec[j].coeffs, c, buf, &state, b_prime->vec[j].coeffs, &buflen); - - // 32-32 KYBER_K - 2 times - for(j=1;jvec[j].coeffs, c, buf, &state, b_prime->vec[j].coeffs, &buflen); - } - - // 32-16 - buflen = XOF_BLOCKBYTES; - if (transposed) - xof_absorb(&state, seed, i, j); - else - xof_absorb(&state, seed, j, i); - - xof_squeezeblocks(buf, 1, &state); - - matacc_asm_opt_32_16(r->coeffs, b->vec[j].coeffs, c, buf, &state, b_prime->vec[j].coeffs, r_tmp, &buflen); -} diff --git a/crypto_kem/kyber768-90s/m4fspeed/matacc.h b/crypto_kem/kyber768-90s/m4fspeed/matacc.h deleted file mode 100644 index 6d7127af..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/matacc.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef MATACC_H -#define MATACC_H -#include "poly.h" -#include "polyvec.h" -#include "symmetric.h" - -extern void matacc_asm_cache_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen); -static inline void _matacc_asm_cache_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t _zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_cache_16_32(r_tmp, b, c, buf, _zetas, state, aprimeptr, buflen); -} -#define matacc_asm_cache_16_32 _matacc_asm_cache_16_32 - -extern void matacc_asm_cache_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen); -static inline void _matacc_asm_cache_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t _zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_cache_32_32(r_tmp, b, c, buf, _zetas, state, aprimeptr, buflen); -} -#define matacc_asm_cache_32_32 _matacc_asm_cache_32_32 - -extern void matacc_asm_cache_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t zetas[64], xof_state *state, int16_t *aprimeptr, int32_t *r_tmp, unsigned int *buflen); -static inline void _matacc_asm_cache_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t _zetas[64], xof_state *state, int16_t *aprimeptr, int32_t *r_tmp, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_cache_32_16(r, b, c, buf, _zetas, state, aprimeptr, r_tmp, buflen); -} -#define matacc_asm_cache_32_16 _matacc_asm_cache_32_16 - -extern void matacc_asm_opt_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen); -static inline void _matacc_asm_opt_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_opt_16_32(r_tmp, b, c, buf, state, aprimeptr, buflen); -} -#define matacc_asm_opt_16_32 _matacc_asm_opt_16_32 - -extern void matacc_asm_opt_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen); -static inline void _matacc_asm_opt_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_opt_32_32(r_tmp, b, c, buf, state, aprimeptr, buflen); -} -#define matacc_asm_opt_32_32 _matacc_asm_opt_32_32 - -extern void matacc_asm_opt_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, int32_t *r_tmp, unsigned int *buflen); -static inline void _matacc_asm_opt_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, int32_t *r_tmp, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27", "s28", "s29"); - matacc_asm_opt_32_16(r, b, c, buf, state, aprimeptr, r_tmp, buflen); -} -#define matacc_asm_opt_32_16 _matacc_asm_opt_32_16 - -void matacc_opt32(poly* r, const polyvec *b, const polyvec *b_prime, unsigned char i, const unsigned char *seed, int transposed); -void matacc_cache32(poly* r, const polyvec *b, polyvec *b_prime, unsigned char i, const unsigned char *seed, int transposed); -#endif \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/matacc.i b/crypto_kem/kyber768-90s/m4fspeed/matacc.i deleted file mode 120000 index e388a0ad..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/matacc_asm.S b/crypto_kem/kyber768-90s/m4fspeed/matacc_asm.S deleted file mode 100644 index a4fe78d6..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/matacc_asm.S +++ /dev/null @@ -1,403 +0,0 @@ -#include "matacc.i" -.extern aes256xof_squeezeblocks - -.syntax unified -.cpu cortex-m4 -.thumb - -// aes256xof_squeezeblocks into buffer if (almost) all bytes have been used -.macro update_buf_loop_finish tmp, tmp2, tmp3, val0, val1, bufptr, ctr, buflenval - // if (pos + 3 > buflen - vmov s23, \tmp3 - vmov \tmp2, \buflenval // get buflen value - vmov \tmp, s17 - sub \tmp3, \bufptr, \tmp // compute pos - add \tmp3, #3 // pos + 3 - cmp.w \tmp3, \tmp2 - ble.w 3f - // && ctr < KYBER_N/4) - cmp.w \ctr, #256/4 - bge.w 3f - // tmp = buffer start - // tmp2 = buffer end - add.w \tmp2, \tmp, \tmp2 // buffer start + buf len = last address of xof output byte - - // copy remaining bytes to start of buffer - ldr.w \tmp3, [\bufptr] - str.w \tmp3, [\tmp] - sub \tmp3, \tmp2, \bufptr - add.w \tmp, \tmp, \tmp3 - - // compute buflen - vmov \val0, s17 // get buf addr - sub \val0, tmp, \val0 - add.w \val0, #64 // XOF_BLOCKBYTES=64 - vmov \buflenval, \val0 - - vmov s18, r0 - vmov s19, r1 - vmov s20, r2 - vmov s21, r12 - vmov s22, lr - - mov.w r0, \tmp // buf + off implicitly after copying loop - mov r1, #1 - vmov r2, s26 // get state ptr - bl aes256xof_squeezeblocks - - vmov r0, s18 - vmov r1, s19 - vmov r2, s20 - vmov r12, s21 - vmov lr, s22 - // pos = 0; - vmov \bufptr, s17 // reset buffer pointer to start -> only after squeezeblocks - 3: - vmov \tmp3, s23 - cmp \ctr, #256/4 - blt.w 1b -.endm - -// void matacc_asm_cache_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int16_t zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen) -.global matacc_asm_cache_16_32 -.type matacc_asm_cache_16_32, %function -.align 2 -matacc_asm_cache_16_32: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - zetaptr .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w zetaptr, [sp, #13*4] // load zetaptr from stack - ldr.w tmp, [sp, #14*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #15*4] // load aprimeptr from stack - vmov s27, tmp - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s29, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_cache_16_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_cache_16_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s29 - - pop {r0-r11, pc} -.size matacc_asm_cache_16_32, . - matacc_asm_cache_16_32 - -// void matacc_asm_cache_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int16_t zetas[64], xof_state *state, int16_t *aprimeptr, unsigned int *buflen) -.global matacc_asm_cache_32_32 -.type matacc_asm_cache_32_32, %function -.align 2 -matacc_asm_cache_32_32: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - zetaptr .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w zetaptr, [sp, #13*4] // load zetaptr from stack - ldr.w tmp, [sp, #14*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #15*4] // load aprimeptr from stack - vmov s27, tmp - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s29, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_acc_cache_32_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_acc_cache_32_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s29 - - pop {r0-r11, pc} -.size matacc_asm_cache_32_32, . - matacc_asm_cache_32_32 - -// void matacc_asm_cache_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int16_t zetas[64], xof_state *state, int16_t *aprimeptr, const int32_t *r_tmp, unsigned int *buflen) -.global matacc_asm_cache_32_16 -.type matacc_asm_cache_32_16, %function -.align 2 -matacc_asm_cache_32_16: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - zetaptr .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w zetaptr, [sp, #13*4] // load zetaptr from stack - - ldr.w tmp, [sp, #14*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #15*4] // load aprimeptr from stack - vmov s27, tmp - - vmov s28, rptr // store "real" destinaton in FP - vmov s29, rptr // backup - ldr.w rptr, [sp, #16*4] - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s16, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_acc_cache_32_16, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_acc_cache_32_16, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s16 - - vmov rptr, s29 - - pop {r0-r11, pc} -.size matacc_asm_cache_32_16, . - matacc_asm_cache_32_16 - -.unreq zetaptr - -// void matacc_asm_opt_16_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen) -.global matacc_asm_opt_16_32 -.type matacc_asm_opt_16_32, %function -.align 2 -matacc_asm_opt_16_32: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - tmp3 .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w tmp, [sp, #13*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #14*4] // load aprimeptr from stack - vmov s27, tmp - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s29, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_opt_16_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_opt_16_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s29 - - pop {r0-r11, pc} -.size matacc_asm_opt_16_32, . - matacc_asm_opt_16_32 - -.unreq ctr -.unreq tmp -.unreq tmp2 - -// void matacc_asm_opt_32_32(int32_t *r_tmp, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, unsigned int *buflen) -.global matacc_asm_opt_32_32 -.type matacc_asm_opt_32_32, %function -.align 2 -matacc_asm_opt_32_32: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - tmp3 .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w tmp, [sp, #13*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #14*4] // load aprimeptr from stack - vmov s27, tmp - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s29, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_acc_opt_32_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_acc_opt_32_32, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s29 - - pop {r0-r11, pc} -.size matacc_asm_opt_32_32, . - matacc_asm_opt_32_32 - -.unreq ctr -.unreq tmp -.unreq tmp2 - -// void matacc_asm_opt_32_16(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], xof_state *state, const int16_t *aprimeptr, const int32_t *r_tmp, unsigned int *buflen) -.global matacc_asm_opt_32_16 -.type matacc_asm_opt_32_16, %function -.align 2 -matacc_asm_opt_32_16: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - tmp3 .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - ldr.w tmp, [sp, #13*4] // load state from stack - vmov s26, tmp - - ldr.w tmp, [sp, #14*4] // load aprimeptr from stack - vmov s27, tmp - - vmov s28, rptr // store "real" destinaton in FP - vmov s29, rptr // backup - ldr.w rptr, [sp, #15*4] - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s16, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_acc_opt_32_16, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_acc_opt_32_16, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, tmp3, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s16 - - vmov rptr, s29 - - pop {r0-r11, pc} -.size matacc_asm_opt_32_16, . - matacc_asm_opt_32_16 \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/ntt.c b/crypto_kem/kyber768-90s/m4fspeed/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/ntt.h b/crypto_kem/kyber768-90s/m4fspeed/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/params.h b/crypto_kem/kyber768-90s/m4fspeed/params.h deleted file mode 120000 index 1b04f0d7..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/poly.c b/crypto_kem/kyber768-90s/m4fspeed/poly.c deleted file mode 120000 index ed549db6..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/poly.h b/crypto_kem/kyber768-90s/m4fspeed/poly.h deleted file mode 120000 index 6f495407..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/poly_asm.S b/crypto_kem/kyber768-90s/m4fspeed/poly_asm.S deleted file mode 120000 index 4424e11a..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/polyvec.c b/crypto_kem/kyber768-90s/m4fspeed/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/polyvec.h b/crypto_kem/kyber768-90s/m4fspeed/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/reduce.S b/crypto_kem/kyber768-90s/m4fspeed/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/symmetric.h b/crypto_kem/kyber768-90s/m4fspeed/symmetric.h deleted file mode 100644 index 76a1b448..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/symmetric.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include "params.h" - - -#include "aes256ctr.h" -#include "sha2.h" - -#if (KYBER_SSBYTES != 32) -#error "90s variant of Kyber can only generate keys of length 256 bits" -#endif - -#define hash_h(OUT, IN, INBYTES) sha256(OUT, IN, INBYTES) -#define hash_g(OUT, IN, INBYTES) sha512(OUT, IN, INBYTES) -#define xof_absorb(STATE, IN, X, Y) aes256xof_absorb(STATE, IN, X, Y) -#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) aes256xof_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define prf(OUT, OUTBYTES, KEY, NONCE) aes256_prf(OUT, OUTBYTES, KEY, NONCE) -#define kdf(OUT, IN, INBYTES) sha256(OUT, IN, INBYTES) - -#define XOF_BLOCKBYTES 64 - -typedef aes256xof_ctx xof_state; - -#endif /* SYMMETRIC_H */ diff --git a/crypto_kem/kyber768-90s/m4fspeed/verify.c b/crypto_kem/kyber768-90s/m4fspeed/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fspeed/verify.h b/crypto_kem/kyber768-90s/m4fspeed/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber768-90s/m4fspeed/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/aes256ctr.c b/crypto_kem/kyber768-90s/m4fstack/aes256ctr.c deleted file mode 120000 index 38c1834b..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/aes256ctr.c +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/aes256ctr.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/aes256ctr.h b/crypto_kem/kyber768-90s/m4fstack/aes256ctr.h deleted file mode 120000 index d9d79ac8..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/aes256ctr.h +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/aes256ctr.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/api.h b/crypto_kem/kyber768-90s/m4fstack/api.h deleted file mode 120000 index eb61c624..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/api.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/api.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/cbd.c b/crypto_kem/kyber768-90s/m4fstack/cbd.c deleted file mode 120000 index 37d243ad..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/cbd.h b/crypto_kem/kyber768-90s/m4fstack/cbd.h deleted file mode 120000 index c00c0559..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/fastaddsub.S b/crypto_kem/kyber768-90s/m4fstack/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/fastbasemul.S b/crypto_kem/kyber768-90s/m4fstack/fastbasemul.S deleted file mode 120000 index 7ba7f7e4..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/fastinvntt.S b/crypto_kem/kyber768-90s/m4fstack/fastinvntt.S deleted file mode 120000 index 8b242d6c..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/fastntt.S b/crypto_kem/kyber768-90s/m4fstack/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/indcpa.c b/crypto_kem/kyber768-90s/m4fstack/indcpa.c deleted file mode 120000 index 7d86b771..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/indcpa.h b/crypto_kem/kyber768-90s/m4fstack/indcpa.h deleted file mode 120000 index 5893b12b..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/kem.c b/crypto_kem/kyber768-90s/m4fstack/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/macros.i b/crypto_kem/kyber768-90s/m4fstack/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/matacc.c b/crypto_kem/kyber768-90s/m4fstack/matacc.c deleted file mode 100644 index be644379..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/matacc.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "ntt.h" -#include "poly.h" -#include "polyvec.h" -#include "symmetric.h" -#include "matacc.h" - -/************************************************* -* Name: matacc -* -* Description: Multiplies a row of A or A^T, generated on-the-fly, -* with a vector of polynomials and accumulates into the result. -* -* Arguments: - poly *r: pointer to output polynomial to accumulate in -* - polyvec *b: pointer to input vector of polynomials to multiply with -* - unsigned char i: byte to indicate the index < KYBER_K of the row of A or A^T -* - const unsigned char *seed: pointer to the public seed used to generate A -* - int transposed: boolean indicatin whether A or A^T is generated -**************************************************/ -void matacc(poly* r, const polyvec *b, unsigned char i, const unsigned char *seed, int transposed) { - unsigned char buf[XOF_BLOCKBYTES+2]; - xof_state state; - int16_t c[4]; - int j = 0; - unsigned int buflen; - - buflen = XOF_BLOCKBYTES; - if (transposed) - xof_absorb(&state, seed, i, j); - else - xof_absorb(&state, seed, j, i); - - xof_squeezeblocks(buf, 1, &state); - matacc_asm(r->coeffs, b->vec[j].coeffs, c, buf, zetas, &state, &buflen); - for(j=1;jcoeffs, b->vec[j].coeffs, c, buf, zetas, &state, &buflen); - } -} \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/matacc.h b/crypto_kem/kyber768-90s/m4fstack/matacc.h deleted file mode 100644 index bac8633e..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/matacc.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef MATACC_H -#define MATACC_H -#include "poly.h" -#include "polyvec.h" -#include "symmetric.h" - -extern void matacc_asm(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES + 2], const int32_t zetas[64], xof_state *state, unsigned int *buflen); -static inline void _matacc_asm(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES + 2], const int32_t _zetas[64], xof_state *state, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27"); - matacc_asm(r, b, c, buf, _zetas, state, buflen); -} -#define matacc_asm _matacc_asm - -extern void matacc_asm_acc(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES + 2], const int32_t zetas[64], xof_state *state, unsigned int *buflen); -static inline void _matacc_asm_acc(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES + 2], const int32_t _zetas[64], xof_state *state, unsigned int *buflen) -{ - // floating point registers clobbered by assembly function - asm volatile("" : : : "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s26", "s27"); - matacc_asm_acc(r, b, c, buf, _zetas, state, buflen); -} -#define matacc_asm_acc _matacc_asm_acc - -void matacc(poly *r, const polyvec *b, unsigned char i, const unsigned char *seed, int transposed); -#endif \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/matacc.i b/crypto_kem/kyber768-90s/m4fstack/matacc.i deleted file mode 120000 index 3804c85d..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/matacc_asm.S b/crypto_kem/kyber768-90s/m4fstack/matacc_asm.S deleted file mode 100644 index c4baa40b..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/matacc_asm.S +++ /dev/null @@ -1,159 +0,0 @@ -#include "matacc.i" -.extern aes256xof_squeezeblocks - -.syntax unified -.cpu cortex-m4 -.thumb - -.macro update_buf_loop_finish tmp, tmp2, tmp3, val0, val1, bufptr, ctr, buflenval - // if (pos + 3 > buflen - vmov s23, \tmp3 - vmov \tmp2, \buflenval // get buflen value - vmov \tmp, s17 - sub \tmp3, \bufptr, \tmp // compute pos - add \tmp3, #3 // pos + 3 - cmp.w \tmp3, \tmp2 - ble.w 3f - // && ctr < KYBER_N/4) { - cmp.w \ctr, #256/4 - bge.w 3f - // tmp = buffer start - // tmp2 = buffer end - add \tmp2, \tmp, \tmp2 // buffer start + buf len = last address of xof output byte - - // copy remaining bytes to start of buffer - ldr.w \tmp3, [\bufptr] - str.w \tmp3, [\tmp] - sub \tmp3, \tmp2, \bufptr - add \tmp, \tmp, \tmp3 - - // compute buflen - vmov \val0, s17 // get buf addr - sub \val0, tmp, \val0 - add.w \val0, #64 // XOF_BLOCKBYTES=64 - vmov \buflenval, \val0 - - vmov s18, r0 - vmov s19, r1 - vmov s20, r2 - vmov s21, r12 - vmov s22, lr - - mov r0, \tmp // buf + off implicitly after copying loop - mov r1, #1 - vmov r2, s26 // get state ptr - bl aes256xof_squeezeblocks - - vmov r0, s18 - vmov r1, s19 - vmov r2, s20 - vmov r12, s21 - vmov lr, s22 - // pos = 0; - vmov \bufptr, s17 // reset buffer pointer to start -> only after squeezeblocks - 3: - vmov \tmp3, s23 - cmp \ctr, #256/4 - blt.w 1b -.endm - -// void matacc_asm(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t zetas[64], xof_state *state) -.global matacc_asm -.type matacc_asm, %function -.align 2 -matacc_asm: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - zetaptr .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - ldr.w zetaptr, [sp, #13*4] // load zetaptr from stack - ldr.w tmp, [sp, #14*4] // load state from stack - vmov s26, tmp - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s27, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - second_if doublebasemul_asm, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s27 - - pop {r0-r11, pc} -.size matacc_asm, . - matacc_asm - -// void matacc_asm(int16_t *r, const int16_t *b, int16_t c[4], unsigned char buf[XOF_BLOCKBYTES+2], const int32_t zetas[64], xof_state *state) -.global matacc_asm_acc -.type matacc_asm_acc, %function -.align 2 -matacc_asm_acc: - push {r0-r11, r14} - rptr .req r0 - bptr .req r1 - cptr .req r2 - bufptr .req r3 - zetaptr .req r4 - val0 .req r5 - val1 .req r6 - tmp .req r7 - tmp2 .req r8 - k .req r9 - q .req r10 - qa .req r11 - qinv .req r12 - ctr .req r14 - - ldr.w zetaptr, [sp, #13*4] // load zetaptr from stack - ldr.w tmp, [sp, #14*4] // load state from stack - vmov s26, tmp - - movw qa, #26632 - movw q, #3329 - ### qinv=0x6ba8f301 - movw qinv, #62209 - movt qinv, #27560 - movw k, #0 - - movw tmp2, #64 // XOF_BLOCKBYTES - vmov s27, tmp2 - - // outer while loop - movw ctr, #0 - vmov s17, bufptr // save bufptr to check later - 1: - - load_vals val0, val1, bufptr, tmp - - first_if doublebasemul_asm_acc, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - second_if doublebasemul_asm_acc, tmp, tmp2, val0, val1, rptr, bptr, cptr, bufptr, zetaptr, k, q, qa, qinv, ctr - - update_buf_loop_finish tmp, tmp2, k, val0, val1, bufptr, ctr, s27 - pop {r0-r11, pc} -.size matacc_asm_acc, . - matacc_asm_acc diff --git a/crypto_kem/kyber768-90s/m4fstack/ntt.c b/crypto_kem/kyber768-90s/m4fstack/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/ntt.h b/crypto_kem/kyber768-90s/m4fstack/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/params.h b/crypto_kem/kyber768-90s/m4fstack/params.h deleted file mode 120000 index 1b04f0d7..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/params.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/params.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/poly.c b/crypto_kem/kyber768-90s/m4fstack/poly.c deleted file mode 120000 index 209dba88..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/poly.h b/crypto_kem/kyber768-90s/m4fstack/poly.h deleted file mode 120000 index e02915ca..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/poly_asm.S b/crypto_kem/kyber768-90s/m4fstack/poly_asm.S deleted file mode 120000 index 9b529775..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/polyvec.c b/crypto_kem/kyber768-90s/m4fstack/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/polyvec.h b/crypto_kem/kyber768-90s/m4fstack/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/reduce.S b/crypto_kem/kyber768-90s/m4fstack/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/symmetric.h b/crypto_kem/kyber768-90s/m4fstack/symmetric.h deleted file mode 120000 index 28c6facf..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/verify.c b/crypto_kem/kyber768-90s/m4fstack/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber768-90s/m4fstack/verify.h b/crypto_kem/kyber768-90s/m4fstack/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber768-90s/m4fstack/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file From f418bf6b8af69f2998daccaf761c11b612e767ab Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 10:56:55 +0800 Subject: [PATCH 072/107] update M4 Kyber to be compatible with NIST Draft --- crypto_kem/kyber512/m4fspeed/indcpa.c | 18 ++- crypto_kem/kyber512/m4fstack/indcpa.c | 7 +- crypto_kem/kyber768/m4fspeed/indcpa.c | 18 ++- crypto_kem/kyber768/m4fspeed/indcpa.h | 5 +- crypto_kem/kyber768/m4fspeed/kem.c | 129 +++++++++++++----- crypto_kem/kyber768/m4fspeed/matacc_asm.S | 6 +- .../kyber768/m4fspeed/symmetric-fips202.c | 85 ++++++------ crypto_kem/kyber768/m4fspeed/symmetric.h | 30 ++-- crypto_kem/kyber768/m4fstack/indcpa.c | 7 +- crypto_kem/kyber768/m4fstack/matacc.i | 2 +- crypto_kem/kyber768/m4fstack/matacc_asm.S | 2 +- 11 files changed, 199 insertions(+), 110 deletions(-) diff --git a/crypto_kem/kyber512/m4fspeed/indcpa.c b/crypto_kem/kyber512/m4fspeed/indcpa.c index 8f83c7e0..5e7fd5ca 100644 --- a/crypto_kem/kyber512/m4fspeed/indcpa.c +++ b/crypto_kem/kyber512/m4fspeed/indcpa.c @@ -9,16 +9,23 @@ #include #include + /************************************************* -* Name: indcpa_keypair +* Name: indcpa_keypair_derand * * Description: Generates public and private key for the CPA-secure * public-key encryption scheme underlying Kyber * -* Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) -* - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes) +* Arguments: - uint8_t *pk: pointer to output public key +* (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key +* (of length KYBER_INDCPA_SECRETKEYBYTES bytes) +* - const uint8_t *coins: pointer to input randomness +* (of length KYBER_SYMBYTES bytes) **************************************************/ -void indcpa_keypair(unsigned char *pk, unsigned char *sk) { +void indcpa_keypair_derand(unsigned char *pk, + unsigned char *sk, + const unsigned char *coins){ polyvec skpv, skpv_prime; poly pkp; unsigned char buf[2 * KYBER_SYMBYTES]; @@ -27,8 +34,7 @@ void indcpa_keypair(unsigned char *pk, unsigned char *sk) { int i; unsigned char nonce = 0; - randombytes(buf, KYBER_SYMBYTES); - hash_g(buf, buf, KYBER_SYMBYTES); + hash_g(buf, coins, KYBER_SYMBYTES); for (i = 0; i < KYBER_K; i++) poly_getnoise_eta1(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber512/m4fstack/indcpa.c b/crypto_kem/kyber512/m4fstack/indcpa.c index 02973e7c..764d494d 100644 --- a/crypto_kem/kyber512/m4fstack/indcpa.c +++ b/crypto_kem/kyber512/m4fstack/indcpa.c @@ -18,7 +18,9 @@ * Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) * - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes) **************************************************/ -void indcpa_keypair(unsigned char *pk, unsigned char *sk) { +void indcpa_keypair_derand(unsigned char *pk, + unsigned char *sk, + const unsigned char *coins){ polyvec skpv; poly pkp; unsigned char buf[2 * KYBER_SYMBYTES]; @@ -27,8 +29,7 @@ void indcpa_keypair(unsigned char *pk, unsigned char *sk) { int i; unsigned char nonce = 0; - randombytes(buf, KYBER_SYMBYTES); - hash_g(buf, buf, KYBER_SYMBYTES); + hash_g(buf, coins, KYBER_SYMBYTES); for (i = 0; i < KYBER_K; i++) poly_getnoise_eta1(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber768/m4fspeed/indcpa.c b/crypto_kem/kyber768/m4fspeed/indcpa.c index 3bf815ad..6e9d5b06 100644 --- a/crypto_kem/kyber768/m4fspeed/indcpa.c +++ b/crypto_kem/kyber768/m4fspeed/indcpa.c @@ -8,17 +8,22 @@ #include #include - /************************************************* -* Name: indcpa_keypair +* Name: indcpa_keypair_derand * * Description: Generates public and private key for the CPA-secure * public-key encryption scheme underlying Kyber * -* Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) -* - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes) +* Arguments: - uint8_t *pk: pointer to output public key +* (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key +* (of length KYBER_INDCPA_SECRETKEYBYTES bytes) +* - const uint8_t *coins: pointer to input randomness +* (of length KYBER_SYMBYTES bytes) **************************************************/ -void indcpa_keypair(unsigned char *pk, unsigned char *sk) { +void indcpa_keypair_derand(unsigned char *pk, + unsigned char *sk, + const unsigned char *coins){ polyvec skpv, skpv_prime; poly pkp; unsigned char buf[2 * KYBER_SYMBYTES]; @@ -27,8 +32,7 @@ void indcpa_keypair(unsigned char *pk, unsigned char *sk) { int i; unsigned char nonce = 0; - randombytes(buf, KYBER_SYMBYTES); - hash_g(buf, buf, KYBER_SYMBYTES); + hash_g(buf, coins, KYBER_SYMBYTES); for (i = 0; i < KYBER_K; i++) poly_getnoise(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber768/m4fspeed/indcpa.h b/crypto_kem/kyber768/m4fspeed/indcpa.h index fcf6aa0d..6d5588a7 100644 --- a/crypto_kem/kyber768/m4fspeed/indcpa.h +++ b/crypto_kem/kyber768/m4fspeed/indcpa.h @@ -1,8 +1,9 @@ #ifndef INDCPA_H #define INDCPA_H -void indcpa_keypair(unsigned char *pk, - unsigned char *sk); +void indcpa_keypair_derand(unsigned char *pk, + unsigned char *sk, + const unsigned char *coins); void indcpa_enc(unsigned char *c, const unsigned char *m, diff --git a/crypto_kem/kyber768/m4fspeed/kem.c b/crypto_kem/kyber768/m4fspeed/kem.c index 31f16e3f..7e6474e2 100644 --- a/crypto_kem/kyber768/m4fspeed/kem.c +++ b/crypto_kem/kyber768/m4fspeed/kem.c @@ -9,6 +9,35 @@ #include +#include + + +/************************************************* +* Name: crypto_kem_keypair_derand +* +* Description: Generates public and private key +* for CCA-secure Kyber key encapsulation mechanism +* +* Arguments: - uint8_t *pk: pointer to output public key +* (an already allocated array of KYBER_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key +* (an already allocated array of KYBER_SECRETKEYBYTES bytes) +* - uint8_t *coins: pointer to input randomness +* (an already allocated array filled with 2*KYBER_SYMBYTES random bytes) +** +* Returns 0 (success) +**************************************************/ +static int crypto_kem_keypair_derand(uint8_t *pk, + uint8_t *sk, + const uint8_t *coins) { + indcpa_keypair_derand(pk, sk, coins); + memcpy(sk + KYBER_INDCPA_SECRETKEYBYTES, pk, KYBER_PUBLICKEYBYTES); + hash_h(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); + /* Value z for pseudo-random output on reject */ + memcpy(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, coins + KYBER_SYMBYTES, KYBER_SYMBYTES); + return 0; +} + /************************************************* * Name: crypto_kem_keypair * @@ -21,42 +50,72 @@ * Returns 0 (success) **************************************************/ int crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { - size_t i; - indcpa_keypair(pk, sk); - for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) { - sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i]; - } - hash_h(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); - randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */ + uint8_t coins[2 * KYBER_SYMBYTES]; + randombytes(coins, 2 * KYBER_SYMBYTES); + crypto_kem_keypair_derand(pk, sk, coins); return 0; } + /************************************************* -* Name: crypto_kem_enc +* Name: crypto_kem_enc_derand * * Description: Generates cipher text and shared * secret for given public key * -* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) -* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) -* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) -* +* Arguments: - uint8_t *ct: pointer to output cipher text +* (an already allocated array of KYBER_CIPHERTEXTBYTES bytes) +* - uint8_t *ss: pointer to output shared secret +* (an already allocated array of KYBER_SSBYTES bytes) +* - const uint8_t *pk: pointer to input public key +* (an already allocated array of KYBER_PUBLICKEYBYTES bytes) +* - const uint8_t *coins: pointer to input randomness +* (an already allocated array filled with KYBER_SYMBYTES random bytes) +** * Returns 0 (success) **************************************************/ -int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { - unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ - unsigned char buf[2 * KYBER_SYMBYTES]; +static int crypto_kem_enc_derand(uint8_t *ct, + uint8_t *ss, + const uint8_t *pk, + const uint8_t *coins) { + uint8_t buf[2 * KYBER_SYMBYTES]; + /* Will contain key, coins */ + uint8_t kr[2 * KYBER_SYMBYTES]; - randombytes(buf, KYBER_SYMBYTES); - hash_h(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */ + memcpy(buf, coins, KYBER_SYMBYTES); - hash_h(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ + /* Multitarget countermeasure for coins + contributory KEM */ + hash_h(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); hash_g(kr, buf, 2 * KYBER_SYMBYTES); - indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ + /* coins are in kr+KYBER_SYMBYTES */ + indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); - hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ - kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ + memcpy(ss, kr, KYBER_SYMBYTES); + return 0; +} + +/************************************************* +* Name: crypto_kem_enc +* +* Description: Generates cipher text and shared +* secret for given public key +* +* Arguments: - uint8_t *ct: pointer to output cipher text +* (an already allocated array of KYBER_CIPHERTEXTBYTES bytes) +* - uint8_t *ss: pointer to output shared secret +* (an already allocated array of KYBER_SSBYTES bytes) +* - const uint8_t *pk: pointer to input public key +* (an already allocated array of KYBER_PUBLICKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int crypto_kem_enc(uint8_t *ct, + uint8_t *ss, + const uint8_t *pk) { + uint8_t coins[KYBER_SYMBYTES]; + randombytes(coins, KYBER_SYMBYTES); + crypto_kem_enc_derand(ct, ss, pk, coins); return 0; } @@ -75,25 +134,29 @@ int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk * On failure, ss will contain a pseudo-random value. **************************************************/ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { - size_t i; - unsigned char fail; - unsigned char buf[2 * KYBER_SYMBYTES]; - unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ - const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES; + int fail; + uint8_t buf[2 * KYBER_SYMBYTES]; + /* Will contain key, coins */ + uint8_t kr[2 * KYBER_SYMBYTES]; + uint8_t cmp[KYBER_CIPHERTEXTBYTES + KYBER_SYMBYTES]; + const uint8_t *pk = sk + KYBER_INDCPA_SECRETKEYBYTES; indcpa_dec(buf, ct, sk); - for (i = 0; i < KYBER_SYMBYTES; i++) { /* Multitarget countermeasure for coins + contributory KEM */ - buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + i]; /* Save hash by storing H(pk) in sk */ - } + /* Multitarget countermeasure for coins + contributory KEM */ + memcpy(buf + KYBER_SYMBYTES, sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, KYBER_SYMBYTES); hash_g(kr, buf, 2 * KYBER_SYMBYTES); - fail = indcpa_enc_cmp(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ + /* coins are in kr+KYBER_SYMBYTES */ + indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); + + fail = verify(ct, cmp, KYBER_CIPHERTEXTBYTES); - hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */ + /* Compute rejection key */ + rkprf(ss, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, ct); - cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */ + /* Copy true key to return buffer if fail is false */ + cmov(ss, kr, KYBER_SYMBYTES, (uint8_t) (1 - fail)); - kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */ return 0; } diff --git a/crypto_kem/kyber768/m4fspeed/matacc_asm.S b/crypto_kem/kyber768/m4fspeed/matacc_asm.S index c4c4e855..f77ae605 100644 --- a/crypto_kem/kyber768/m4fspeed/matacc_asm.S +++ b/crypto_kem/kyber768/m4fspeed/matacc_asm.S @@ -1,11 +1,11 @@ #include "matacc.i" -.extern kyber_shake128_squeezeblocks +.extern shake128_squeezeblocks .syntax unified .cpu cortex-m4 .thumb -// kyber_shake128_squeezeblocks into buffer if all bytes have been used +// shake128_squeezeblocks into buffer if all bytes have been used .macro third_if tmp, tmp2, rptr, bptr, cptr, bufptr, ctr // if (pos + 3 > buflen && ctr < KYBER_N/4) vmov \tmp, s17 @@ -27,7 +27,7 @@ movw \bptr, #1 vmov \cptr, s26 // load state - bl kyber_shake128_squeezeblocks + bl shake128_squeezeblocks vmov r12, s16 vmov \rptr, s18 diff --git a/crypto_kem/kyber768/m4fspeed/symmetric-fips202.c b/crypto_kem/kyber768/m4fspeed/symmetric-fips202.c index 311d33f0..4ee07233 100644 --- a/crypto_kem/kyber768/m4fspeed/symmetric-fips202.c +++ b/crypto_kem/kyber768/m4fspeed/symmetric-fips202.c @@ -1,64 +1,71 @@ #include "fips202.h" +#include "params.h" #include "symmetric.h" - -#include +#include +#include +#include /************************************************* * Name: kyber_shake128_absorb * * Description: Absorb step of the SHAKE128 specialized for the Kyber context. * -* Arguments: - shake128ctx *s: pointer to (uninitialized) output Keccak state -* - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s -* - unsigned char i additional byte of input -* - unsigned char j additional byte of input +* Arguments: - xof_state *state: pointer to (uninitialized) output Keccak state +* - const uint8_t *seed: pointer to KYBER_SYMBYTES input to be absorbed into state +* - uint8_t i: additional byte of input +* - uint8_t j: additional byte of input **************************************************/ -void kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y) { - unsigned char extseed[KYBER_SYMBYTES + 2]; - int i; +void kyber_shake128_absorb(xof_state *state, + const uint8_t seed[KYBER_SYMBYTES], + uint8_t x, + uint8_t y) { + uint8_t extseed[KYBER_SYMBYTES + 2]; + + memcpy(extseed, seed, KYBER_SYMBYTES); + extseed[KYBER_SYMBYTES + 0] = x; + extseed[KYBER_SYMBYTES + 1] = y; - for (i = 0; i < KYBER_SYMBYTES; i++) { - extseed[i] = input[i]; - } - extseed[i++] = x; - extseed[i] = y; - shake128_absorb(s, extseed, KYBER_SYMBYTES + 2); + shake128_absorb(state, extseed, sizeof(extseed)); } /************************************************* -* Name: kyber_shake128_squeezeblocks +* Name: kyber_shake256_prf * -* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each. -* Modifies the state. Can be called multiple times to keep squeezing, -* i.e., is incremental. +* Description: Usage of SHAKE256 as a PRF, concatenates secret and public input +* and then generates outlen bytes of SHAKE256 output * -* Arguments: - unsigned char *output: pointer to output blocks -* - size_t nblocks: number of blocks to be squeezed (written to output) -* - shake128ctx *s: pointer to in/output Keccak state +* Arguments: - uint8_t *out: pointer to output +* - size_t outlen: number of requested output bytes +* - const uint8_t *key: pointer to the key (of length KYBER_SYMBYTES) +* - uint8_t nonce: single-byte nonce (public PRF input) **************************************************/ -void kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s) { - shake128_squeezeblocks(output, nblocks, s); +void kyber_shake256_prf(uint8_t *out, size_t outlen, const uint8_t key[KYBER_SYMBYTES], uint8_t nonce) { + uint8_t extkey[KYBER_SYMBYTES + 1]; + + memcpy(extkey, key, KYBER_SYMBYTES); + extkey[KYBER_SYMBYTES] = nonce; + + shake256(out, outlen, extkey, sizeof(extkey)); } /************************************************* -* Name: shake256_prf +* Name: kyber_shake256_prf * * Description: Usage of SHAKE256 as a PRF, concatenates secret and public input * and then generates outlen bytes of SHAKE256 output * -* Arguments: - unsigned char *output: pointer to output -* - size_t outlen: number of requested output bytes -* - const unsigned char * key: pointer to the key (of length KYBER_SYMBYTES) -* - const unsigned char nonce: single-byte nonce (public PRF input) +* Arguments: - uint8_t *out: pointer to output +* - size_t outlen: number of requested output bytes +* - const uint8_t *key: pointer to the key (of length KYBER_SYMBYTES) +* - uint8_t nonce: single-byte nonce (public PRF input) **************************************************/ -void shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce) { - unsigned char extkey[KYBER_SYMBYTES + 1]; - size_t i; +void kyber_shake256_rkprf(uint8_t out[KYBER_SSBYTES], const uint8_t key[KYBER_SYMBYTES], const uint8_t input[KYBER_CIPHERTEXTBYTES]) { + shake256incctx s; - for (i = 0; i < KYBER_SYMBYTES; i++) { - extkey[i] = key[i]; - } - extkey[i] = nonce; - - shake256(output, outlen, extkey, KYBER_SYMBYTES + 1); -} + shake256_inc_init(&s); + shake256_inc_absorb(&s, key, KYBER_SYMBYTES); + shake256_inc_absorb(&s, input, KYBER_CIPHERTEXTBYTES); + shake256_inc_finalize(&s); + shake256_inc_squeeze(out, KYBER_SSBYTES, &s); + shake256_inc_ctx_release(&s); +} \ No newline at end of file diff --git a/crypto_kem/kyber768/m4fspeed/symmetric.h b/crypto_kem/kyber768/m4fspeed/symmetric.h index d396466d..8441c837 100644 --- a/crypto_kem/kyber768/m4fspeed/symmetric.h +++ b/crypto_kem/kyber768/m4fspeed/symmetric.h @@ -1,23 +1,29 @@ #ifndef SYMMETRIC_H #define SYMMETRIC_H - #include "fips202.h" #include "params.h" #include +#include -void kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y); -void kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s); -void shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce); +typedef shake128ctx xof_state; -#define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES) -#define hash_g(OUT, IN, INBYTES) sha3_512(OUT, IN, INBYTES) -#define xof_absorb(STATE, IN, X, Y) kyber_shake128_absorb(STATE, IN, X, Y) -#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) kyber_shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define prf(OUT, OUTBYTES, KEY, NONCE) shake256_prf(OUT, OUTBYTES, KEY, NONCE) -#define kdf(OUT, IN, INBYTES) shake256(OUT, KYBER_SSBYTES, IN, INBYTES) +void kyber_shake128_absorb(xof_state *s, + const uint8_t seed[KYBER_SYMBYTES], + uint8_t x, + uint8_t y); -#define XOF_BLOCKBYTES 168 +void kyber_shake256_prf(uint8_t *out, size_t outlen, const uint8_t key[KYBER_SYMBYTES], uint8_t nonce); -typedef shake128ctx xof_state; +void kyber_shake256_rkprf(uint8_t out[KYBER_SSBYTES], const uint8_t key[KYBER_SYMBYTES], const uint8_t input[KYBER_CIPHERTEXTBYTES]); + +#define XOF_BLOCKBYTES SHAKE128_RATE + +#define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES) +#define hash_g(OUT, IN, INBYTES) sha3_512(OUT, IN, INBYTES) +#define xof_absorb(STATE, SEED, X, Y) kyber_shake128_absorb(STATE, SEED, X, Y) +#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) shake128_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define xof_ctx_release(STATE) shake128_ctx_release(STATE) +#define prf(OUT, OUTBYTES, KEY, NONCE) kyber_shake256_prf(OUT, OUTBYTES, KEY, NONCE) +#define rkprf(OUT, KEY, INPUT) kyber_shake256_rkprf(OUT, KEY, INPUT) #endif /* SYMMETRIC_H */ diff --git a/crypto_kem/kyber768/m4fstack/indcpa.c b/crypto_kem/kyber768/m4fstack/indcpa.c index d558df08..bb0ce408 100644 --- a/crypto_kem/kyber768/m4fstack/indcpa.c +++ b/crypto_kem/kyber768/m4fstack/indcpa.c @@ -18,7 +18,9 @@ * Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes) * - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes) **************************************************/ -void indcpa_keypair(unsigned char *pk, unsigned char *sk) { +void indcpa_keypair_derand(unsigned char *pk, + unsigned char *sk, + const unsigned char *coins){ polyvec skpv; poly pkp; unsigned char buf[2 * KYBER_SYMBYTES]; @@ -27,8 +29,7 @@ void indcpa_keypair(unsigned char *pk, unsigned char *sk) { int i; unsigned char nonce = 0; - randombytes(buf, KYBER_SYMBYTES); - hash_g(buf, buf, KYBER_SYMBYTES); + hash_g(buf, coins, KYBER_SYMBYTES); for (i = 0; i < KYBER_K; i++) poly_getnoise(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber768/m4fstack/matacc.i b/crypto_kem/kyber768/m4fstack/matacc.i index bb080277..237ee469 100644 --- a/crypto_kem/kyber768/m4fstack/matacc.i +++ b/crypto_kem/kyber768/m4fstack/matacc.i @@ -98,7 +98,7 @@ movw \bptr, #1 vmov \cptr, s26 // load state #ifndef nohash - bl kyber_shake128_squeezeblocks + bl shake128_squeezeblocks #endif vmov r12, s16 diff --git a/crypto_kem/kyber768/m4fstack/matacc_asm.S b/crypto_kem/kyber768/m4fstack/matacc_asm.S index b5610180..2a5a3074 100644 --- a/crypto_kem/kyber768/m4fstack/matacc_asm.S +++ b/crypto_kem/kyber768/m4fstack/matacc_asm.S @@ -1,5 +1,5 @@ #include "matacc.i" -.extern kyber_shake128_squeezeblocks +.extern shake128_squeezeblocks .syntax unified .cpu cortex-m4 From edcf6f6af44c680c435c6d9c258e93aa285f28f2 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 11:11:58 +0800 Subject: [PATCH 073/107] eliminate / KYBER_Q that may result in variable time division This applies the patches from upstream to poly_compress and polyvec_compress See https://github.com/pq-crystals/kyber/commit/272125f6acc8e8b6850fd68ceb901a660ff48196 https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/ldX0ThYJuBo/m/ovODsdY7AwAJ --- crypto_kem/kyber512/m4fspeed/poly.c | 154 ++++++++++++++++++------- crypto_kem/kyber512/m4fspeed/poly.h | 2 +- crypto_kem/kyber512/m4fstack/poly.c | 154 ++++++++++++++++++------- crypto_kem/kyber512/m4fstack/poly.h | 2 +- crypto_kem/kyber768/m4fspeed/poly.c | 150 ++++++++++++++++++------ crypto_kem/kyber768/m4fspeed/poly.h | 2 +- crypto_kem/kyber768/m4fspeed/polyvec.c | 82 +++++++------ crypto_kem/kyber768/m4fspeed/polyvec.h | 2 +- crypto_kem/kyber768/m4fstack/poly.c | 150 ++++++++++++++++++------ crypto_kem/kyber768/m4fstack/poly.h | 2 +- 10 files changed, 510 insertions(+), 190 deletions(-) diff --git a/crypto_kem/kyber512/m4fspeed/poly.c b/crypto_kem/kyber512/m4fspeed/poly.c index 1b74c0c9..f9d408b8 100644 --- a/crypto_kem/kyber512/m4fspeed/poly.c +++ b/crypto_kem/kyber512/m4fspeed/poly.c @@ -16,38 +16,56 @@ * Arguments: - unsigned char *r: pointer to output byte array (of length KYBER_POLYCOMPRESSEDBYTES) * - const poly *a: pointer to input polynomial to be serialized *************************************************/ -void poly_compress(unsigned char *r, poly *a) +void poly_compress(unsigned char *r, const poly *a) { + unsigned int i,j; + int16_t u; + uint32_t d0; uint8_t t[8]; - int i,j,k=0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for(i=0;icoeffs[i+j] << 4) + KYBER_Q/2) / KYBER_Q) & 15; - - r[k] = t[0] | (t[1] << 4); - r[k+1] = t[2] | (t[3] << 4); - r[k+2] = t[4] | (t[5] << 4); - r[k+3] = t[6] | (t[7] << 4); - k += 4; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } + + r[0] = t[0] | (t[1] << 4); + r[1] = t[2] | (t[3] << 4); + r[2] = t[4] | (t[5] << 4); + r[3] = t[6] | (t[7] << 4); + r += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; - - r[k] = t[0] | (t[1] << 5); - r[k+1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); - r[k+2] = (t[3] >> 1) | (t[4] << 4); - r[k+3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); - r[k+4] = (t[6] >> 2) | (t[7] << 3); - k += 5; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + + r[0] = (t[0] >> 0) | (t[1] << 5); + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); + r[2] = (t[3] >> 1) | (t[4] << 4); + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); + r[4] = (t[6] >> 2) | (t[7] << 3); + r += 5; } #else -#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {96, 128, 160}" +#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" #endif } @@ -107,13 +125,24 @@ void poly_decompress(poly *r, const unsigned char *a) **************************************************/ void poly_packcompress(unsigned char *r, poly *a, int i) { int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -131,9 +160,17 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; - + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } r[320*i+5*j+0] = t[0] & 0xff; r[320*i+5*j+1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2); r[320*i+5*j+2] = ((t[1] >> 6) | ((t[2] & 0x0f) << 4)) & 0xff; @@ -194,14 +231,24 @@ void poly_unpackdecompress(poly *r, const unsigned char *a, int i) { **************************************************/ int cmp_poly_compress(const unsigned char *r, poly *a) { unsigned char rc = 0; + int16_t u; + uint32_t d0; uint8_t t[8]; int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) for (i = 0; i < KYBER_N; i += 8) { - for (j = 0; j < 8; j++) - t[j] = ((((uint32_t)a->coeffs[i + j] << 4) + KYBER_Q / 2) / KYBER_Q) & 15; - + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } rc |= r[k] ^ (t[0] | (t[1] << 4)); rc |= r[k + 1] ^ (t[2] | (t[3] << 4)); rc |= r[k + 2] ^ (t[4] | (t[5] << 4)); @@ -211,8 +258,18 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { #elif (KYBER_POLYCOMPRESSEDBYTES == 160) for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + rc |= r[k] ^ (t[0] | (t[1] << 5)); rc |= r[k+1] ^ ((t[1] >> 3) | (t[2] << 2) | (t[3] << 7)); @@ -222,7 +279,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 5; } #else -#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {96, 128, 160}" +#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" #endif return rc; } @@ -241,13 +298,23 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { unsigned char rc = 0; int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } rc |= r[352*i+11*j+ 0] ^ (t[0] & 0xff); rc |= r[352*i+11*j+ 1] ^ ((t[0] >> 8) | ((t[1] & 0x1f) << 3)); @@ -264,8 +331,17 @@ int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { #elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 320)) uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } rc |= r[320*i+5*j+0] ^ (t[0] & 0xff); rc |= r[320*i+5*j+1] ^ ((t[0] >> 8) | ((t[1] & 0x3f) << 2)); diff --git a/crypto_kem/kyber512/m4fspeed/poly.h b/crypto_kem/kyber512/m4fspeed/poly.h index d4d6b29f..4994d871 100644 --- a/crypto_kem/kyber512/m4fspeed/poly.h +++ b/crypto_kem/kyber512/m4fspeed/poly.h @@ -18,7 +18,7 @@ typedef struct { int16_t coeffs[KYBER_N]; } poly; -void poly_compress(unsigned char *r, poly *a); +void poly_compress(unsigned char *r, const poly *a); void poly_decompress(poly *r, const unsigned char *a); void poly_packcompress(unsigned char *r, poly *a, int i); diff --git a/crypto_kem/kyber512/m4fstack/poly.c b/crypto_kem/kyber512/m4fstack/poly.c index 0c449a46..f42154ff 100644 --- a/crypto_kem/kyber512/m4fstack/poly.c +++ b/crypto_kem/kyber512/m4fstack/poly.c @@ -16,38 +16,56 @@ * Arguments: - unsigned char *r: pointer to output byte array (of length KYBER_POLYCOMPRESSEDBYTES) * - const poly *a: pointer to input polynomial to be serialized *************************************************/ -void poly_compress(unsigned char *r, poly *a) +void poly_compress(unsigned char *r, const poly *a) { + unsigned int i,j; + int16_t u; + uint32_t d0; uint8_t t[8]; - int i,j,k=0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for(i=0;icoeffs[i+j] << 4) + KYBER_Q/2) / KYBER_Q) & 15; - - r[k] = t[0] | (t[1] << 4); - r[k+1] = t[2] | (t[3] << 4); - r[k+2] = t[4] | (t[5] << 4); - r[k+3] = t[6] | (t[7] << 4); - k += 4; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } + + r[0] = t[0] | (t[1] << 4); + r[1] = t[2] | (t[3] << 4); + r[2] = t[4] | (t[5] << 4); + r[3] = t[6] | (t[7] << 4); + r += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; - - r[k] = t[0] | (t[1] << 5); - r[k+1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); - r[k+2] = (t[3] >> 1) | (t[4] << 4); - r[k+3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); - r[k+4] = (t[6] >> 2) | (t[7] << 3); - k += 5; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + + r[0] = (t[0] >> 0) | (t[1] << 5); + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); + r[2] = (t[3] >> 1) | (t[4] << 4); + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); + r[4] = (t[6] >> 2) | (t[7] << 3); + r += 5; } #else -#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {96, 128, 160}" +#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" #endif } @@ -107,13 +125,24 @@ void poly_decompress(poly *r, const unsigned char *a) **************************************************/ void poly_packcompress(unsigned char *r, poly *a, int i) { int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -131,9 +160,17 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; - + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } r[320*i+5*j+0] = t[0] & 0xff; r[320*i+5*j+1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2); r[320*i+5*j+2] = ((t[1] >> 6) | ((t[2] & 0x0f) << 4)) & 0xff; @@ -194,14 +231,24 @@ void poly_unpackdecompress(poly *r, const unsigned char *a, int i) { **************************************************/ int cmp_poly_compress(const unsigned char *r, poly *a) { unsigned char rc = 0; + int16_t u; + uint32_t d0; uint8_t t[8]; int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) for (i = 0; i < KYBER_N; i += 8) { - for (j = 0; j < 8; j++) - t[j] = ((((uint32_t)a->coeffs[i + j] << 4) + KYBER_Q / 2) / KYBER_Q) & 15; - + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } rc |= r[k] ^ (t[0] | (t[1] << 4)); rc |= r[k + 1] ^ (t[2] | (t[3] << 4)); rc |= r[k + 2] ^ (t[4] | (t[5] << 4)); @@ -211,8 +258,18 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { #elif (KYBER_POLYCOMPRESSEDBYTES == 160) for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + rc |= r[k] ^ (t[0] | (t[1] << 5)); rc |= r[k+1] ^ ((t[1] >> 3) | (t[2] << 2) | (t[3] << 7)); @@ -222,7 +279,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 5; } #else -#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {96, 128, 160}" +#error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" #endif return rc; } @@ -241,13 +298,23 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { unsigned char rc = 0; int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } rc |= r[352*i+11*j+ 0] ^ (t[0] & 0xff); rc |= r[352*i+11*j+ 1] ^ ((t[0] >> 8) | ((t[1] & 0x1f) << 3)); @@ -264,8 +331,17 @@ int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { #elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 320)) uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } rc |= r[320*i+5*j+0] ^ (t[0] & 0xff); rc |= r[320*i+5*j+1] ^ ((t[0] >> 8) | ((t[1] & 0x3f) << 2)); diff --git a/crypto_kem/kyber512/m4fstack/poly.h b/crypto_kem/kyber512/m4fstack/poly.h index 2a58b678..d62e9661 100644 --- a/crypto_kem/kyber512/m4fstack/poly.h +++ b/crypto_kem/kyber512/m4fstack/poly.h @@ -18,7 +18,7 @@ typedef struct { int16_t coeffs[KYBER_N]; } poly; -void poly_compress(unsigned char *r, poly *a); +void poly_compress(unsigned char *r, const poly *a); void poly_decompress(poly *r, const unsigned char *a); void poly_packcompress(unsigned char *r, poly *a, int i); diff --git a/crypto_kem/kyber768/m4fspeed/poly.c b/crypto_kem/kyber768/m4fspeed/poly.c index d7c63bc6..9864534a 100644 --- a/crypto_kem/kyber768/m4fspeed/poly.c +++ b/crypto_kem/kyber768/m4fspeed/poly.c @@ -16,35 +16,53 @@ * Arguments: - unsigned char *r: pointer to output byte array (of length KYBER_POLYCOMPRESSEDBYTES) * - const poly *a: pointer to input polynomial to be serialized *************************************************/ -void poly_compress(unsigned char *r, poly *a) +void poly_compress(unsigned char *r, const poly *a) { + unsigned int i,j; + int16_t u; + uint32_t d0; uint8_t t[8]; - int i,j,k=0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for(i=0;icoeffs[i+j] << 4) + KYBER_Q/2) / KYBER_Q) & 15; - - r[k] = t[0] | (t[1] << 4); - r[k+1] = t[2] | (t[3] << 4); - r[k+2] = t[4] | (t[5] << 4); - r[k+3] = t[6] | (t[7] << 4); - k += 4; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } + + r[0] = t[0] | (t[1] << 4); + r[1] = t[2] | (t[3] << 4); + r[2] = t[4] | (t[5] << 4); + r[3] = t[6] | (t[7] << 4); + r += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; - - r[k] = t[0] | (t[1] << 5); - r[k+1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); - r[k+2] = (t[3] >> 1) | (t[4] << 4); - r[k+3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); - r[k+4] = (t[6] >> 2) | (t[7] << 3); - k += 5; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + + r[0] = (t[0] >> 0) | (t[1] << 5); + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); + r[2] = (t[3] >> 1) | (t[4] << 4); + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); + r[4] = (t[6] >> 2) | (t[7] << 3); + r += 5; } #else #error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" @@ -107,13 +125,24 @@ void poly_decompress(poly *r, const unsigned char *a) **************************************************/ void poly_packcompress(unsigned char *r, poly *a, int i) { int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -131,9 +160,17 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; - + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } r[320*i+5*j+0] = t[0] & 0xff; r[320*i+5*j+1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2); r[320*i+5*j+2] = ((t[1] >> 6) | ((t[2] & 0x0f) << 4)) & 0xff; @@ -194,14 +231,24 @@ void poly_unpackdecompress(poly *r, const unsigned char *a, int i) { **************************************************/ int cmp_poly_compress(const unsigned char *r, poly *a) { unsigned char rc = 0; + int16_t u; + uint32_t d0; uint8_t t[8]; int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) for (i = 0; i < KYBER_N; i += 8) { - for (j = 0; j < 8; j++) - t[j] = ((((uint32_t)a->coeffs[i + j] << 4) + KYBER_Q / 2) / KYBER_Q) & 15; - + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } rc |= r[k] ^ (t[0] | (t[1] << 4)); rc |= r[k + 1] ^ (t[2] | (t[3] << 4)); rc |= r[k + 2] ^ (t[4] | (t[5] << 4)); @@ -211,8 +258,18 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { #elif (KYBER_POLYCOMPRESSEDBYTES == 160) for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + rc |= r[k] ^ (t[0] | (t[1] << 5)); rc |= r[k+1] ^ ((t[1] >> 3) | (t[2] << 2) | (t[3] << 7)); @@ -241,13 +298,23 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { unsigned char rc = 0; int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } rc |= r[352*i+11*j+ 0] ^ (t[0] & 0xff); rc |= r[352*i+11*j+ 1] ^ ((t[0] >> 8) | ((t[1] & 0x1f) << 3)); @@ -264,8 +331,17 @@ int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { #elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 320)) uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } rc |= r[320*i+5*j+0] ^ (t[0] & 0xff); rc |= r[320*i+5*j+1] ^ ((t[0] >> 8) | ((t[1] & 0x3f) << 2)); diff --git a/crypto_kem/kyber768/m4fspeed/poly.h b/crypto_kem/kyber768/m4fspeed/poly.h index 4c7b1e47..fc61dd51 100644 --- a/crypto_kem/kyber768/m4fspeed/poly.h +++ b/crypto_kem/kyber768/m4fspeed/poly.h @@ -16,7 +16,7 @@ typedef struct { int16_t coeffs[KYBER_N]; } poly; -void poly_compress(unsigned char *r, poly *a); +void poly_compress(unsigned char *r, const poly *a); void poly_decompress(poly *r, const unsigned char *a); void poly_packcompress(unsigned char *r, poly *a, int i); diff --git a/crypto_kem/kyber768/m4fspeed/polyvec.c b/crypto_kem/kyber768/m4fspeed/polyvec.c index b1e387a2..a405e919 100644 --- a/crypto_kem/kyber768/m4fspeed/polyvec.c +++ b/crypto_kem/kyber768/m4fspeed/polyvec.c @@ -7,52 +7,68 @@ * * Description: Compress and serialize vector of polynomials * -* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES) +* Arguments: - uint8_t *r: pointer to output byte array +* (needs space for KYBER_POLYVECCOMPRESSEDBYTES) * - const polyvec *a: pointer to input vector of polynomials **************************************************/ -void polyvec_compress(unsigned char *r, polyvec *a) +void polyvec_compress(unsigned char *r, const polyvec *a) { - int i,j,k; + unsigned int i,j,k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; - for(i=0;ivec[i].coeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(i=0;ivec[i].coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } - r[11*j+ 0] = t[0] & 0xff; - r[11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); - r[11*j+ 2] = (t[1] >> 5) | ((t[2] & 0x03) << 6); - r[11*j+ 3] = (t[2] >> 2) & 0xff; - r[11*j+ 4] = (t[2] >> 10) | ((t[3] & 0x7f) << 1); - r[11*j+ 5] = (t[3] >> 7) | ((t[4] & 0x0f) << 4); - r[11*j+ 6] = (t[4] >> 4) | ((t[5] & 0x01) << 7); - r[11*j+ 7] = (t[5] >> 1) & 0xff; - r[11*j+ 8] = (t[5] >> 9) | ((t[6] & 0x3f) << 2); - r[11*j+ 9] = (t[6] >> 6) | ((t[7] & 0x07) << 5); - r[11*j+10] = (t[7] >> 3); + r[ 0] = (t[0] >> 0); + r[ 1] = (t[0] >> 8) | (t[1] << 3); + r[ 2] = (t[1] >> 5) | (t[2] << 6); + r[ 3] = (t[2] >> 2); + r[ 4] = (t[2] >> 10) | (t[3] << 1); + r[ 5] = (t[3] >> 7) | (t[4] << 4); + r[ 6] = (t[4] >> 4) | (t[5] << 7); + r[ 7] = (t[5] >> 1); + r[ 8] = (t[5] >> 9) | (t[6] << 2); + r[ 9] = (t[6] >> 6) | (t[7] << 5); + r[10] = (t[7] >> 3); + r += 11; } - r += 352; } #elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 320)) uint16_t t[4]; - for(i=0;ivec[i].coeffs[4*j+k] << 10) + KYBER_Q/2) / KYBER_Q) & 0x3ff; + for(i=0;ivec[i].coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } - r[5*j+ 0] = t[0] & 0xff; - r[5*j+ 1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2); - r[5*j+ 2] = (t[1] >> 6) | ((t[2] & 0x0f) << 4); - r[5*j+ 3] = (t[2] >> 4) | ((t[3] & 0x03) << 6); - r[5*j+ 4] = (t[3] >> 2); + r[0] = (t[0] >> 0); + r[1] = (t[0] >> 8) | (t[1] << 2); + r[2] = (t[1] >> 6) | (t[2] << 4); + r[3] = (t[2] >> 4) | (t[3] << 6); + r[4] = (t[3] >> 2); + r += 5; } - r += 320; } #else #error "KYBER_POLYVECCOMPRESSEDBYTES needs to be in {320*KYBER_K, 352*KYBER_K}" diff --git a/crypto_kem/kyber768/m4fspeed/polyvec.h b/crypto_kem/kyber768/m4fspeed/polyvec.h index 22713053..0be7873f 100644 --- a/crypto_kem/kyber768/m4fspeed/polyvec.h +++ b/crypto_kem/kyber768/m4fspeed/polyvec.h @@ -8,7 +8,7 @@ typedef struct { poly vec[KYBER_K]; } polyvec; -void polyvec_compress(unsigned char *r, polyvec *a); +void polyvec_compress(unsigned char *r, const polyvec *a); void polyvec_decompress(polyvec *r, const unsigned char *a); void polyvec_tobytes(unsigned char *r, polyvec *a); diff --git a/crypto_kem/kyber768/m4fstack/poly.c b/crypto_kem/kyber768/m4fstack/poly.c index 84b1deb8..91fab840 100644 --- a/crypto_kem/kyber768/m4fstack/poly.c +++ b/crypto_kem/kyber768/m4fstack/poly.c @@ -16,35 +16,53 @@ * Arguments: - unsigned char *r: pointer to output byte array (of length KYBER_POLYCOMPRESSEDBYTES) * - const poly *a: pointer to input polynomial to be serialized *************************************************/ -void poly_compress(unsigned char *r, poly *a) +void poly_compress(unsigned char *r, const poly *a) { + unsigned int i,j; + int16_t u; + uint32_t d0; uint8_t t[8]; - int i,j,k=0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for(i=0;icoeffs[i+j] << 4) + KYBER_Q/2) / KYBER_Q) & 15; - - r[k] = t[0] | (t[1] << 4); - r[k+1] = t[2] | (t[3] << 4); - r[k+2] = t[4] | (t[5] << 4); - r[k+3] = t[6] | (t[7] << 4); - k += 4; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } + + r[0] = t[0] | (t[1] << 4); + r[1] = t[2] | (t[3] << 4); + r[2] = t[4] | (t[5] << 4); + r[3] = t[6] | (t[7] << 4); + r += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; - - r[k] = t[0] | (t[1] << 5); - r[k+1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); - r[k+2] = (t[3] >> 1) | (t[4] << 4); - r[k+3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); - r[k+4] = (t[6] >> 2) | (t[7] << 3); - k += 5; + for(i=0;icoeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + + r[0] = (t[0] >> 0) | (t[1] << 5); + r[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); + r[2] = (t[3] >> 1) | (t[4] << 4); + r[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); + r[4] = (t[6] >> 2) | (t[7] << 3); + r += 5; } #else #error "KYBER_POLYCOMPRESSEDBYTES needs to be in {128, 160}" @@ -107,13 +125,24 @@ void poly_decompress(poly *r, const unsigned char *a) **************************************************/ void poly_packcompress(unsigned char *r, poly *a, int i) { int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -131,9 +160,17 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; - + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } r[320*i+5*j+0] = t[0] & 0xff; r[320*i+5*j+1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2); r[320*i+5*j+2] = ((t[1] >> 6) | ((t[2] & 0x0f) << 4)) & 0xff; @@ -194,14 +231,24 @@ void poly_unpackdecompress(poly *r, const unsigned char *a, int i) { **************************************************/ int cmp_poly_compress(const unsigned char *r, poly *a) { unsigned char rc = 0; + int16_t u; + uint32_t d0; uint8_t t[8]; int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) for (i = 0; i < KYBER_N; i += 8) { - for (j = 0; j < 8; j++) - t[j] = ((((uint32_t)a->coeffs[i + j] << 4) + KYBER_Q / 2) / KYBER_Q) & 15; - + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint16_t)u << 4) + KYBER_Q/2)/KYBER_Q) & 15; */ + d0 = u << 4; + d0 += 1665; + d0 *= 80635; + d0 >>= 28; + t[j] = d0 & 0xf; + } rc |= r[k] ^ (t[0] | (t[1] << 4)); rc |= r[k + 1] ^ (t[2] | (t[3] << 4)); rc |= r[k + 2] ^ (t[4] | (t[5] << 4)); @@ -211,8 +258,18 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { #elif (KYBER_POLYCOMPRESSEDBYTES == 160) for(i=0;icoeffs[i+j] << 5) + KYBER_Q/2) / KYBER_Q) & 31; + for(j=0;j<8;j++) { + // map to positive standard representatives + u = a->coeffs[8*i+j]; + u += (u >> 15) & KYBER_Q; +/* t[j] = ((((uint32_t)u << 5) + KYBER_Q/2)/KYBER_Q) & 31; */ + d0 = u << 5; + d0 += 1664; + d0 *= 40318; + d0 >>= 27; + t[j] = d0 & 0x1f; + } + rc |= r[k] ^ (t[0] | (t[1] << 5)); rc |= r[k+1] ^ ((t[1] >> 3) | (t[2] << 2) | (t[3] << 7)); @@ -241,13 +298,23 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { unsigned char rc = 0; int j, k; + uint64_t d0; #if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 352)) uint16_t t[8]; for(j=0;jcoeffs[8*j+k] << 11) + KYBER_Q/2) / KYBER_Q) & 0x7ff; + for(k=0;k<8;k++) { + t[k] = a->coeffs[8*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; +/* t[k] = ((((uint32_t)t[k] << 11) + KYBER_Q/2)/KYBER_Q) & 0x7ff; */ + d0 = t[k]; + d0 <<= 11; + d0 += 1664; + d0 *= 645084; + d0 >>= 31; + t[k] = d0 & 0x7ff; + } rc |= r[352*i+11*j+ 0] ^ (t[0] & 0xff); rc |= r[352*i+11*j+ 1] ^ ((t[0] >> 8) | ((t[1] & 0x1f) << 3)); @@ -264,8 +331,17 @@ int cmp_poly_packcompress(const unsigned char *r, poly *a, int i) { #elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_K * 320)) uint16_t t[4]; for (j = 0; j < KYBER_N / 4; j++) { - for (k = 0; k < 4; k++) - t[k] = ((((uint32_t)a->coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff; + for(k=0;k<4;k++) { + t[k] = a->coeffs[4*j+k]; + t[k] += ((int16_t)t[k] >> 15) & KYBER_Q; + /* t[k] = ((((uint32_t)t[k] << 10) + KYBER_Q/2)/ KYBER_Q) & 0x3ff; */ + d0 = t[k]; + d0 <<= 10; + d0 += 1665; + d0 *= 1290167; + d0 >>= 32; + t[k] = d0 & 0x3ff; + } rc |= r[320*i+5*j+0] ^ (t[0] & 0xff); rc |= r[320*i+5*j+1] ^ ((t[0] >> 8) | ((t[1] & 0x3f) << 2)); diff --git a/crypto_kem/kyber768/m4fstack/poly.h b/crypto_kem/kyber768/m4fstack/poly.h index 3aef4c45..635abe9f 100644 --- a/crypto_kem/kyber768/m4fstack/poly.h +++ b/crypto_kem/kyber768/m4fstack/poly.h @@ -16,7 +16,7 @@ typedef struct { int16_t coeffs[KYBER_N]; } poly; -void poly_compress(unsigned char *r, poly *a); +void poly_compress(unsigned char *r, const poly *a); void poly_decompress(poly *r, const unsigned char *a); void poly_packcompress(unsigned char *r, poly *a, int i); From 0fa8f561d410d9032b9c27052840d89ffb4a33c4 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 13:14:13 +0800 Subject: [PATCH 074/107] Dilithium compatibility with NIST draft --- crypto_sign/dilithium2/m4f/packing.c | 39 +++++++++++++------------- crypto_sign/dilithium2/m4f/packing.h | 10 +++---- crypto_sign/dilithium2/m4f/params.h | 15 ++++++---- crypto_sign/dilithium2/m4f/poly.c | 6 ++-- crypto_sign/dilithium2/m4f/polyvec.c | 3 +- crypto_sign/dilithium2/m4f/sign.c | 41 ++++++++++++++-------------- 6 files changed, 59 insertions(+), 55 deletions(-) diff --git a/crypto_sign/dilithium2/m4f/packing.c b/crypto_sign/dilithium2/m4f/packing.c index 869822c4..8aaff2a3 100644 --- a/crypto_sign/dilithium2/m4f/packing.c +++ b/crypto_sign/dilithium2/m4f/packing.c @@ -64,7 +64,7 @@ void unpack_pk(uint8_t rho[SEEDBYTES], **************************************************/ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t rho[SEEDBYTES], - const uint8_t tr[SEEDBYTES], + const uint8_t tr[TRBYTES], const uint8_t key[SEEDBYTES], const polyveck *t0, const polyvecl *s1, @@ -80,9 +80,9 @@ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], sk[i] = key[i]; sk += SEEDBYTES; - for(i = 0; i < SEEDBYTES; ++i) + for(i = 0; i < TRBYTES; ++i) sk[i] = tr[i]; - sk += SEEDBYTES; + sk += TRBYTES; for(i = 0; i < L; ++i) polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s1->vec[i]); @@ -110,7 +110,7 @@ void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], * - uint8_t sk[]: byte array containing bit-packed sk **************************************************/ void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[SEEDBYTES], + uint8_t tr[TRBYTES], uint8_t key[SEEDBYTES], polyveck *t0, smallpoly s1[L], @@ -127,9 +127,9 @@ void unpack_sk(uint8_t rho[SEEDBYTES], key[i] = sk[i]; sk += SEEDBYTES; - for(i = 0; i < SEEDBYTES; ++i) + for(i = 0; i < TRBYTES; ++i) tr[i] = sk[i]; - sk += SEEDBYTES; + sk += TRBYTES; for(i=0; i < L; ++i) small_polyeta_unpack(&s1[i], sk + i*POLYETA_PACKEDBYTES); @@ -143,6 +143,7 @@ void unpack_sk(uint8_t rho[SEEDBYTES], polyt0_unpack(&t0->vec[i], sk + i*POLYT0_PACKEDBYTES); } + /************************************************* * Name: pack_sig * @@ -154,15 +155,15 @@ void unpack_sk(uint8_t rho[SEEDBYTES], * - const polyveck *h: pointer to hint vector h **************************************************/ void pack_sig(uint8_t sig[CRYPTO_BYTES], - const uint8_t c[SEEDBYTES], + const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h) { unsigned int i, j, k; - for(i=0; i < SEEDBYTES; ++i) + for(i=0; i < CTILDEBYTES; ++i) sig[i] = c[i]; - sig += SEEDBYTES; + sig += CTILDEBYTES; for(i = 0; i < L; ++i) polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); @@ -183,20 +184,20 @@ void pack_sig(uint8_t sig[CRYPTO_BYTES], } void pack_sig_c(uint8_t sig[CRYPTO_BYTES], - const uint8_t c[SEEDBYTES]) + const uint8_t c[CTILDEBYTES]) { unsigned int i; - for(i=0; i < SEEDBYTES; ++i) + for(i=0; i < CTILDEBYTES; ++i) sig[i] = c[i]; - sig += SEEDBYTES; + sig += CTILDEBYTES; } void pack_sig_z(uint8_t sig[CRYPTO_BYTES], const polyvecl *z) { unsigned int i; - sig += SEEDBYTES; + sig += CTILDEBYTES; for(i = 0; i < L; ++i) polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); } @@ -207,7 +208,7 @@ void pack_sig_h(unsigned char sig[CRYPTO_BYTES], const unsigned int idx, unsigned int *hints_written) { - sig += SEEDBYTES; + sig += CTILDEBYTES; sig += L*POLYZ_PACKEDBYTES; // Encode h @@ -222,7 +223,7 @@ void pack_sig_h(unsigned char sig[CRYPTO_BYTES], void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], unsigned int *hints_written) { - sig += SEEDBYTES; + sig += CTILDEBYTES; sig += L * POLYZ_PACKEDBYTES; while (*hints_written < OMEGA) { sig[*hints_written] = 0; @@ -243,16 +244,16 @@ void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], * * Returns 1 in case of malformed signature; otherwise 0. **************************************************/ -int unpack_sig(uint8_t c[SEEDBYTES], +int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]) { unsigned int i, j, k; - for(i = 0; i < SEEDBYTES; ++i) + for(i = 0; i < CTILDEBYTES; ++i) c[i] = sig[i]; - sig += SEEDBYTES; + sig += CTILDEBYTES; for(i = 0; i < L; ++i) polyz_unpack(&z->vec[i], sig + i*POLYZ_PACKEDBYTES); @@ -282,4 +283,4 @@ int unpack_sig(uint8_t c[SEEDBYTES], return 1; return 0; -} +} \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4f/packing.h b/crypto_sign/dilithium2/m4f/packing.h index 030d31c5..35553545 100644 --- a/crypto_sign/dilithium2/m4f/packing.h +++ b/crypto_sign/dilithium2/m4f/packing.h @@ -12,21 +12,21 @@ void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], const uint8_t rho[SEEDBYTES], co #define pack_sk DILITHIUM_NAMESPACE(pack_sk) void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], const uint8_t rho[SEEDBYTES], - const uint8_t tr[SEEDBYTES], + const uint8_t tr[TRBYTES], const uint8_t key[SEEDBYTES], const polyveck *t0, const polyvecl *s1, const polyveck *s2); #define pack_sig DILITHIUM_NAMESPACE(pack_sig) -void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[SEEDBYTES], const polyvecl *z, const polyveck *h); +void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h); #define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); #define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[SEEDBYTES], + uint8_t tr[TRBYTES], uint8_t key[SEEDBYTES], polyveck *t0, smallpoly s1[L], @@ -34,10 +34,10 @@ void unpack_sk(uint8_t rho[SEEDBYTES], const uint8_t sk[CRYPTO_SECRETKEYBYTES]); #define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) -int unpack_sig(uint8_t c[SEEDBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); +int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); #define pack_sig_c DILITHIUM_NAMESPACE(pack_sig_c) -void pack_sig_c(uint8_t sig[CRYPTO_BYTES], const uint8_t c[SEEDBYTES]); +void pack_sig_c(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES]); #define pack_sig_z DILITHIUM_NAMESPACE(pack_sig_z) void pack_sig_z(uint8_t sig[CRYPTO_BYTES], const polyvecl *z); diff --git a/crypto_sign/dilithium2/m4f/params.h b/crypto_sign/dilithium2/m4f/params.h index f51f901e..507de467 100644 --- a/crypto_sign/dilithium2/m4f/params.h +++ b/crypto_sign/dilithium2/m4f/params.h @@ -8,6 +8,8 @@ #define SEEDBYTES 32 #define CRHBYTES 64 +#define TRBYTES 64 +#define RNDBYTES 32 #define N 256 #define Q 8380417 #define D 13 @@ -22,7 +24,7 @@ #define GAMMA1 (1 << 17) #define GAMMA2 ((Q-1)/88) #define OMEGA 80 -#define CRYPTO_ALGNAME "Dilithium2" +#define CTILDEBYTES 32 #elif DILITHIUM_MODE == 3 #define K 6 @@ -33,7 +35,7 @@ #define GAMMA1 (1 << 19) #define GAMMA2 ((Q-1)/32) #define OMEGA 55 -#define CRYPTO_ALGNAME "Dilithium3" +#define CTILDEBYTES 48 #elif DILITHIUM_MODE == 5 #define K 8 @@ -44,7 +46,7 @@ #define GAMMA1 (1 << 19) #define GAMMA2 ((Q-1)/32) #define OMEGA 75 -#define CRYPTO_ALGNAME "Dilithium5" +#define CTILDEBYTES 64 #endif @@ -71,10 +73,11 @@ #endif #define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLYT1_PACKEDBYTES) -#define CRYPTO_SECRETKEYBYTES (3*SEEDBYTES \ +#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES \ + + TRBYTES \ + L*POLYETA_PACKEDBYTES \ + K*POLYETA_PACKEDBYTES \ + K*POLYT0_PACKEDBYTES) -#define CRYPTO_BYTES (SEEDBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) +#define CRYPTO_BYTES (CTILDEBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) -#endif +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4f/poly.c b/crypto_sign/dilithium2/m4f/poly.c index eae636e2..0d40fda3 100644 --- a/crypto_sign/dilithium2/m4f/poly.c +++ b/crypto_sign/dilithium2/m4f/poly.c @@ -323,7 +323,7 @@ int poly_chknorm(const poly *a, int32_t B) { * * Description: Sample polynomial with uniformly random coefficients * in [0,Q-1] by performing rejection sampling on the -* output stream of SHAKE256(seed|nonce) or AES256CTR(seed,nonce). +* output stream of SHAKE256(seed|nonce). * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length SEEDBYTES @@ -409,7 +409,7 @@ static unsigned int rej_eta(int32_t *a, * * Description: Sample polynomial with uniformly random coefficients * in [-ETA,ETA] by performing rejection sampling on the -* output stream from SHAKE256(seed|nonce) or AES256CTR(seed,nonce). +* output stream from SHAKE256(seed|nonce). * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length SEEDBYTES @@ -444,7 +444,7 @@ void poly_uniform_eta(poly *a, * * Description: Sample polynomial with uniformly random coefficients * in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream -* of SHAKE256(seed|nonce) or AES256CTR(seed,nonce). +* of SHAKE256(seed|nonce). * * Arguments: - poly *a: pointer to output polynomial * - const uint8_t seed[]: byte array with seed of length CRHBYTES diff --git a/crypto_sign/dilithium2/m4f/polyvec.c b/crypto_sign/dilithium2/m4f/polyvec.c index b19d0b9a..e20749c0 100644 --- a/crypto_sign/dilithium2/m4f/polyvec.c +++ b/crypto_sign/dilithium2/m4f/polyvec.c @@ -11,8 +11,7 @@ * * Description: Implementation of ExpandA. Generates matrix A with uniformly * random coefficients a_{i,j} by performing rejection -* sampling on the output stream of SHAKE128(rho|j|i) -* or AES256CTR(rho,j|i). +* sampling on the output stream of SHAKE128(rho|j|i). * * Arguments: - polyvecl mat[K]: output matrix * - const uint8_t rho[]: byte array containing seed rho diff --git a/crypto_sign/dilithium2/m4f/sign.c b/crypto_sign/dilithium2/m4f/sign.c index 0573f5d3..04bec45c 100644 --- a/crypto_sign/dilithium2/m4f/sign.c +++ b/crypto_sign/dilithium2/m4f/sign.c @@ -22,7 +22,7 @@ **************************************************/ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; - uint8_t tr[SEEDBYTES]; + uint8_t tr[TRBYTES]; const uint8_t *rho, *rhoprime, *key; polyvecl mat[K]; polyvecl s1, s1hat; @@ -58,7 +58,7 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { pack_pk(pk, rho, &t1); /* Compute H(rho, t1) and write secret key */ - shake256(tr, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES); + shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); pack_sk(sk, rho, tr, key, &t0, &s1, &s2); return 0; @@ -84,9 +84,10 @@ int crypto_sign_signature(uint8_t *sig, size_t mlen, const uint8_t *sk) { - uint8_t seedbuf[3*SEEDBYTES + 2*CRHBYTES]; - uint8_t *rho, *tr, *key, *mu, *rhoprime; + uint8_t seedbuf[2 * SEEDBYTES + TRBYTES + RNDBYTES + 2 * CRHBYTES]; + uint8_t *rho, *tr, *key, *mu, *rhoprime, *rnd; uint16_t nonce = 0; + unsigned int n; polyvecl mat[K], y, z; polyveck t0, w1, w0; poly cp; @@ -99,23 +100,23 @@ int crypto_sign_signature(uint8_t *sig, rho = seedbuf; tr = rho + SEEDBYTES; - key = tr + SEEDBYTES; - mu = key + SEEDBYTES; + key = tr + TRBYTES; + rnd = key + SEEDBYTES; + mu = rnd + RNDBYTES; rhoprime = mu + CRHBYTES; unpack_sk(rho, tr, key, &t0, s1_prime, s2_prime, sk); - /* Compute CRH(tr, msg) */ + /* Compute mu = CRH(tr, msg) */ shake256_inc_init(&state); - shake256_inc_absorb(&state, tr, SEEDBYTES); + shake256_inc_absorb(&state, tr, TRBYTES); shake256_inc_absorb(&state, m, mlen); shake256_inc_finalize(&state); shake256_inc_squeeze(mu, CRHBYTES, &state); -#ifdef DILITHIUM_RANDOMIZED_SIGNING - randombytes(rhoprime, CRHBYTES); -#else - shake256(rhoprime, CRHBYTES, key, SEEDBYTES + CRHBYTES); -#endif + for (n = 0; n < RNDBYTES; n++) { + rnd[n] = 0; + } + shake256(rhoprime, CRHBYTES, key, SEEDBYTES + RNDBYTES + CRHBYTES); /* Expand matrix and transform vectors */ polyvec_matrix_expand(mat, rho); @@ -144,7 +145,7 @@ int crypto_sign_signature(uint8_t *sig, shake256_inc_absorb(&state, mu, CRHBYTES); shake256_inc_absorb(&state, sig, K*POLYW1_PACKEDBYTES); shake256_inc_finalize(&state); - shake256_inc_squeeze(sig, SEEDBYTES, &state); + shake256_inc_squeeze(sig, CTILDEBYTES, &state); poly_challenge(&cp, sig); poly_small_ntt_precomp(&cp_small, &cp_small_prime, &cp); @@ -248,8 +249,8 @@ int crypto_sign_verify(const uint8_t *sig, uint8_t buf[K*POLYW1_PACKEDBYTES]; uint8_t rho[SEEDBYTES]; uint8_t mu[CRHBYTES]; - uint8_t c[SEEDBYTES]; - uint8_t c2[SEEDBYTES]; + uint8_t c[CTILDEBYTES]; + uint8_t c2[CTILDEBYTES]; poly cp; polyvecl mat[K], z; polyveck t1, w1, h; @@ -265,9 +266,9 @@ int crypto_sign_verify(const uint8_t *sig, return -1; /* Compute CRH(h(rho, t1), msg) */ - shake256(mu, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES); + shake256(mu, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); shake256_inc_init(&state); - shake256_inc_absorb(&state, mu, SEEDBYTES); + shake256_inc_absorb(&state, mu, CRHBYTES); shake256_inc_absorb(&state, m, mlen); shake256_inc_finalize(&state); shake256_inc_squeeze(mu, CRHBYTES, &state); @@ -298,8 +299,8 @@ int crypto_sign_verify(const uint8_t *sig, shake256_inc_absorb(&state, mu, CRHBYTES); shake256_inc_absorb(&state, buf, K*POLYW1_PACKEDBYTES); shake256_inc_finalize(&state); - shake256_inc_squeeze(c2, SEEDBYTES, &state); - for(i = 0; i < SEEDBYTES; ++i) + shake256_inc_squeeze(c2, CTILDEBYTES, &state); + for(i = 0; i < CTILDEBYTES; ++i) if(c[i] != c2[i]) return -1; From 619a125887edf8c5ccae423c90ef853ad45c4f3b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 15:51:41 +0800 Subject: [PATCH 075/107] include compat.h to allow SPHINCS+ to build --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index dbe94161..28350a51 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit dbe9416182ce4f4d9cdb9a42da31dbf5ba5e6e4c +Subproject commit 28350a519b5788741347b956a497f64b7a954fd7 From c4fd63c4349a0e8d06b51f11c5a7ec09ff77bf39 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 23 Feb 2024 15:51:58 +0800 Subject: [PATCH 076/107] fix build on stm32f4discovery --- mk/stm32f4discovery.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 6c819423..2b10ef4b 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -4,6 +4,8 @@ OPENCM3_TARGET=lib/stm32/f4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ mupq/crypto_sign/tuov% \ + mupq/crypto_sign/ov-Ip% \ + crypto_sign/ov-Ip% \ mupq/crypto_sign/falcon-1024-tree% include mk/opencm3.mk From e852f55fca54a90e044bbf91f6bbea2c32153950 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 27 Feb 2024 21:37:53 +0100 Subject: [PATCH 077/107] Update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 546f6372..6ea4e1e6 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 546f6372e0e1e0703eedbed796c2d6a5a32b71aa +Subproject commit 6ea4e1e6a7f8b7f41c2b6f91b38d92f69bcc22fa From e69876456b63536eed96a18f00bb59ee39f8d1dd Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 27 Feb 2024 21:38:09 +0100 Subject: [PATCH 078/107] Update skiplist.py --- skiplist.py | 431 +++++++++++++++++++--------------------------------- 1 file changed, 159 insertions(+), 272 deletions(-) diff --git a/skiplist.py b/skiplist.py index 07e9c008..47192e42 100644 --- a/skiplist.py +++ b/skiplist.py @@ -1,198 +1,115 @@ skip_list = [ - {'scheme': 'kyber1024', 'implementation': 'm4fspeed', 'estmemory': 15360}, - {'scheme': 'kyber1024', 'implementation': 'm4fstack', 'estmemory': 11264}, - {'scheme': 'kyber1024-90s', 'implementation': 'm4fspeed', 'estmemory': 17408}, - {'scheme': 'kyber1024-90s', 'implementation': 'm4fstack', 'estmemory': 13312}, - {'scheme': 'kyber512', 'implementation': 'm4fspeed', 'estmemory': 10240}, - {'scheme': 'kyber512', 'implementation': 'm4fstack', 'estmemory': 7168}, - {'scheme': 'kyber512-90s', 'implementation': 'm4fspeed', 'estmemory': 12288}, - {'scheme': 'kyber512-90s', 'implementation': 'm4fstack', 'estmemory': 9216}, - {'scheme': 'kyber768', 'implementation': 'm4fspeed', 'estmemory': 13312}, - {'scheme': 'kyber768', 'implementation': 'm4fstack', 'estmemory': 9216}, - {'scheme': 'kyber768-90s', 'implementation': 'm4fspeed', 'estmemory': 14336}, - {'scheme': 'kyber768-90s', 'implementation': 'm4fstack', 'estmemory': 11264}, - {'scheme': 'bikel3', 'implementation': 'opt', 'estmemory': 175104}, + {'scheme': 'aimer-l1-param1', 'implementation': 'ref', 'estmemory': 206848}, + {'scheme': 'aimer-l1-param2', 'implementation': 'ref', 'estmemory': 461824}, + {'scheme': 'aimer-l1-param3', 'implementation': 'ref', 'estmemory': 1442816}, + {'scheme': 'aimer-l3-param1', 'implementation': 'ref', 'estmemory': 452608}, + {'scheme': 'aimer-l3-param2', 'implementation': 'ref', 'estmemory': 1091584}, + {'scheme': 'aimer-l5-param1', 'implementation': 'ref', 'estmemory': 926720}, + {'scheme': 'aimer-l5-param2', 'implementation': 'ref', 'estmemory': 2169856}, + {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, + {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, + {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, + {'scheme': 'ascon-sign-128s-simple', 'implementation': 'ref', 'estmemory': 12288}, + {'scheme': 'ascon-sign-192f-robust', 'implementation': 'ref', 'estmemory': 43008}, + {'scheme': 'ascon-sign-192f-simple', 'implementation': 'ref', 'estmemory': 41984}, + {'scheme': 'ascon-sign-192s-robust', 'implementation': 'ref', 'estmemory': 23552}, + {'scheme': 'ascon-sign-192s-simple', 'implementation': 'ref', 'estmemory': 22528}, + {'scheme': 'bikel1', 'implementation': 'm4f', 'estmemory': 103424}, {'scheme': 'bikel1', 'implementation': 'opt', 'estmemory': 90112}, {'scheme': 'bikel3', 'implementation': 'm4f', 'estmemory': 194560}, - {'scheme': 'bikel1', 'implementation': 'm4f', 'estmemory': 103424}, - {'scheme': 'frodokem640aes', 'implementation': 'm4', 'estmemory': 124928}, - {'scheme': 'firesaber', 'implementation': 'm4f', 'estmemory': 15360}, - {'scheme': 'frodokem640shake', 'implementation': 'm4', 'estmemory': 113664}, - {'scheme': 'lightsaber', 'implementation': 'm4f', 'estmemory': 10240}, - {'scheme': 'ntruhps2048509', 'implementation': 'm4f', 'estmemory': 25600}, - {'scheme': 'ntruhps2048677', 'implementation': 'm4f', 'estmemory': 33792}, - {'scheme': 'ntruhps4096821', 'implementation': 'm4f', 'estmemory': 40960}, - {'scheme': 'ntruhrss701', 'implementation': 'm4f', 'estmemory': 32768}, - {'scheme': 'saber', 'implementation': 'm4f', 'estmemory': 12288}, - {'scheme': 'ntrulpr953', 'implementation': 'm4f', 'estmemory': 40960}, - {'scheme': 'ntrulpr857', 'implementation': 'm4f', 'estmemory': 38912}, - {'scheme': 'ntrulpr761', 'implementation': 'm4f', 'estmemory': 29696}, - {'scheme': 'ntrulpr653', 'implementation': 'm4f', 'estmemory': 24576}, - {'scheme': 'ntrulpr1277', 'implementation': 'm4f', 'estmemory': 64512}, - {'scheme': 'ntrulpr1013', 'implementation': 'm4f', 'estmemory': 41984}, - {'scheme': 'sikep434', 'implementation': 'm4', 'estmemory': 10240}, - {'scheme': 'sikep610', 'implementation': 'm4', 'estmemory': 14336}, - {'scheme': 'sikep751', 'implementation': 'm4', 'estmemory': 16384}, - {'scheme': 'sikep503', 'implementation': 'm4', 'estmemory': 11264}, - {'scheme': 'sntrup953', 'implementation': 'm4f', 'estmemory': 96256}, - {'scheme': 'sntrup857', 'implementation': 'm4f', 'estmemory': 108544}, - {'scheme': 'sntrup761', 'implementation': 'm4f', 'estmemory': 111616}, - {'scheme': 'sntrup653', 'implementation': 'm4f', 'estmemory': 97280}, - {'scheme': 'sntrup1277', 'implementation': 'm4f', 'estmemory': 99328}, - {'scheme': 'sntrup1013', 'implementation': 'm4f', 'estmemory': 110592}, - {'scheme': 'sikep434', 'implementation': 'opt', 'estmemory': 10240}, - {'scheme': 'sikep610', 'implementation': 'opt', 'estmemory': 14336}, - {'scheme': 'sikep503', 'implementation': 'opt', 'estmemory': 10240}, - {'scheme': 'sikep751', 'implementation': 'opt', 'estmemory': 16384}, - {'scheme': 'kyber1024', 'implementation': 'clean', 'estmemory': 28672}, - {'scheme': 'kyber1024-90s', 'implementation': 'clean', 'estmemory': 28672}, - {'scheme': 'kyber512', 'implementation': 'clean', 'estmemory': 14336}, - {'scheme': 'kyber512-90s', 'implementation': 'clean', 'estmemory': 15360}, - {'scheme': 'kyber768', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'kyber768-90s', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'frodokem1344aes', 'implementation': 'clean', 'estmemory': 3852288}, - {'scheme': 'frodokem1344aes', 'implementation': 'opt', 'estmemory': 305152}, - {'scheme': 'frodokem1344shake', 'implementation': 'clean', 'estmemory': 3852288}, - {'scheme': 'frodokem1344shake', 'implementation': 'opt', 'estmemory': 252928}, - {'scheme': 'firesaber', 'implementation': 'clean', 'estmemory': 28672}, - {'scheme': 'frodokem640aes', 'implementation': 'clean', 'estmemory': 932864}, - {'scheme': 'frodokem640aes', 'implementation': 'opt', 'estmemory': 144384}, - {'scheme': 'frodokem640shake', 'implementation': 'clean', 'estmemory': 932864}, - {'scheme': 'frodokem640shake', 'implementation': 'opt', 'estmemory': 119808}, - {'scheme': 'frodokem976aes', 'implementation': 'clean', 'estmemory': 2080768}, - {'scheme': 'frodokem976aes', 'implementation': 'opt', 'estmemory': 222208}, - {'scheme': 'frodokem976shake', 'implementation': 'clean', 'estmemory': 2079744}, - {'scheme': 'frodokem976shake', 'implementation': 'opt', 'estmemory': 185344}, - {'scheme': 'hqc-rmrs-128', 'implementation': 'clean', 'estmemory': 81920}, - {'scheme': 'hqc-rmrs-192', 'implementation': 'clean', 'estmemory': 161792}, - {'scheme': 'hqc-rmrs-256', 'implementation': 'clean', 'estmemory': 257024}, - {'scheme': 'lightsaber', 'implementation': 'clean', 'estmemory': 15360}, - {'scheme': 'mceliece348864', 'implementation': 'clean', 'estmemory': 833536}, - {'scheme': 'mceliece348864f', 'implementation': 'clean', 'estmemory': 833536}, - {'scheme': 'mceliece460896', 'implementation': 'clean', 'estmemory': 4733952}, - {'scheme': 'mceliece460896f', 'implementation': 'clean', 'estmemory': 4733952}, - {'scheme': 'mceliece6688128', 'implementation': 'clean', 'estmemory': 5255168}, - {'scheme': 'mceliece6688128f', 'implementation': 'clean', 'estmemory': 5255168}, - {'scheme': 'mceliece6960119', 'implementation': 'clean', 'estmemory': 5257216}, - {'scheme': 'mceliece6960119f', 'implementation': 'clean', 'estmemory': 5257216}, - {'scheme': 'mceliece8192128', 'implementation': 'clean', 'estmemory': 5568512}, - {'scheme': 'mceliece8192128f', 'implementation': 'clean', 'estmemory': 5568512}, - {'scheme': 'ntruhps2048509', 'implementation': 'clean', 'estmemory': 29696}, - {'scheme': 'ntruhps2048677', 'implementation': 'clean', 'estmemory': 38912}, - {'scheme': 'ntruhps4096821', 'implementation': 'clean', 'estmemory': 47104}, - {'scheme': 'ntruhrss701', 'implementation': 'clean', 'estmemory': 38912}, - {'scheme': 'ntrulpr953', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'ntrulpr857', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'ntrulpr761', 'implementation': 'clean', 'estmemory': 18432}, - {'scheme': 'ntrulpr653', 'implementation': 'clean', 'estmemory': 18432}, - {'scheme': 'ntrulpr1277', 'implementation': 'clean', 'estmemory': 28672}, - {'scheme': 'ntrulpr1013', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'saber', 'implementation': 'clean', 'estmemory': 20480}, - {'scheme': 'sntrup953', 'implementation': 'clean', 'estmemory': 22528}, - {'scheme': 'sntrup857', 'implementation': 'clean', 'estmemory': 20480}, - {'scheme': 'sntrup761', 'implementation': 'clean', 'estmemory': 18432}, - {'scheme': 'sntrup653', 'implementation': 'clean', 'estmemory': 16384}, - {'scheme': 'sntrup1277', 'implementation': 'clean', 'estmemory': 29696}, - {'scheme': 'sntrup1013', 'implementation': 'clean', 'estmemory': 23552}, + {'scheme': 'bikel3', 'implementation': 'opt', 'estmemory': 175104}, + {'scheme': 'biscuit128f', 'implementation': 'ref', 'estmemory': 145408}, + {'scheme': 'biscuit128s', 'implementation': 'ref', 'estmemory': 1099776}, + {'scheme': 'biscuit192f', 'implementation': 'ref', 'estmemory': 282624}, + {'scheme': 'biscuit192s', 'implementation': 'ref', 'estmemory': 2257920}, + {'scheme': 'biscuit256f', 'implementation': 'ref', 'estmemory': 505856}, + {'scheme': 'biscuit256s', 'implementation': 'ref', 'estmemory': 4004864}, + {'scheme': 'cross-sha2-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, + {'scheme': 'cross-sha2-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, + {'scheme': 'cross-sha2-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'cross-sha2-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, + {'scheme': 'cross-sha2-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, + {'scheme': 'cross-sha2-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, + {'scheme': 'cross-sha2-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, + {'scheme': 'cross-sha2-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, + {'scheme': 'cross-sha2-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, + {'scheme': 'cross-sha2-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, + {'scheme': 'cross-sha2-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, + {'scheme': 'cross-sha2-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, + {'scheme': 'cross-sha3-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, + {'scheme': 'cross-sha3-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, + {'scheme': 'cross-sha3-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'cross-sha3-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, + {'scheme': 'cross-sha3-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, + {'scheme': 'cross-sha3-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, + {'scheme': 'cross-sha3-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, + {'scheme': 'cross-sha3-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, + {'scheme': 'cross-sha3-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, + {'scheme': 'cross-sha3-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, + {'scheme': 'cross-sha3-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, + {'scheme': 'cross-sha3-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, + {'scheme': 'dilithium2', 'implementation': 'clean', 'estmemory': 59392}, {'scheme': 'dilithium2', 'implementation': 'm4f', 'estmemory': 57344}, + {'scheme': 'dilithium3', 'implementation': 'clean', 'estmemory': 90112}, {'scheme': 'dilithium3', 'implementation': 'm4f', 'estmemory': 79872}, - {'scheme': 'dilithium5', 'implementation': 'm4f', 'estmemory': 130048}, - {'scheme': 'dilithium2', 'implementation': 'clean', 'estmemory': 60416}, - {'scheme': 'dilithium2aes', 'implementation': 'clean', 'estmemory': 61440}, - {'scheme': 'dilithium3aes', 'implementation': 'clean', 'estmemory': 92160}, - {'scheme': 'dilithium3', 'implementation': 'clean', 'estmemory': 91136}, {'scheme': 'dilithium5', 'implementation': 'clean', 'estmemory': 136192}, - {'scheme': 'dilithium5aes', 'implementation': 'clean', 'estmemory': 138240}, - {'scheme': 'falcon-1024', 'implementation': 'clean', 'estmemory': 90112}, - {'scheme': 'falcon-512', 'implementation': 'clean', 'estmemory': 47104}, - {'scheme': 'rainbowI-circumzenithal', 'implementation': 'clean', 'estmemory': 490496}, - {'scheme': 'rainbowI-classic', 'implementation': 'clean', 'estmemory': 445440}, - {'scheme': 'rainbowI-compressed', 'implementation': 'clean', 'estmemory': 387072}, - {'scheme': 'rainbowIII-circumzenithal', 'implementation': 'clean', 'estmemory': 2383872}, - {'scheme': 'rainbowIII-classic', 'implementation': 'clean', 'estmemory': 2046976}, - {'scheme': 'rainbowIII-compressed', 'implementation': 'clean', 'estmemory': 2032640}, - {'scheme': 'rainbowV-circumzenithal', 'implementation': 'clean', 'estmemory': 6140928}, - {'scheme': 'rainbowV-classic', 'implementation': 'clean', 'estmemory': 3587072}, - {'scheme': 'rainbowV-compressed', 'implementation': 'clean', 'estmemory': 4732928}, - {'scheme': 'sphincs-haraka-128f-robust', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'sphincs-haraka-128f-simple', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'sphincs-haraka-128s-robust', 'implementation': 'clean', 'estmemory': 13312}, - {'scheme': 'sphincs-haraka-128s-simple', 'implementation': 'clean', 'estmemory': 13312}, - {'scheme': 'sphincs-haraka-192f-robust', 'implementation': 'clean', 'estmemory': 43008}, - {'scheme': 'sphincs-haraka-192f-simple', 'implementation': 'clean', 'estmemory': 43008}, - {'scheme': 'sphincs-haraka-192s-robust', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'sphincs-haraka-192s-simple', 'implementation': 'clean', 'estmemory': 23552}, - {'scheme': 'sphincs-haraka-256f-robust', 'implementation': 'clean', 'estmemory': 59392}, - {'scheme': 'sphincs-haraka-256f-simple', 'implementation': 'clean', 'estmemory': 59392}, - {'scheme': 'sphincs-haraka-256s-robust', 'implementation': 'clean', 'estmemory': 38912}, - {'scheme': 'sphincs-haraka-256s-simple', 'implementation': 'clean', 'estmemory': 38912}, - {'scheme': 'sphincs-sha256-128f-robust', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'sphincs-sha256-128f-simple', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'sphincs-sha256-128s-robust', 'implementation': 'clean', 'estmemory': 12288}, - {'scheme': 'sphincs-sha256-128s-simple', 'implementation': 'clean', 'estmemory': 12288}, - {'scheme': 'sphincs-sha256-192f-robust', 'implementation': 'clean', 'estmemory': 41984}, - {'scheme': 'sphincs-sha256-192f-simple', 'implementation': 'clean', 'estmemory': 41984}, - {'scheme': 'sphincs-sha256-192s-robust', 'implementation': 'clean', 'estmemory': 22528}, - {'scheme': 'sphincs-sha256-192s-simple', 'implementation': 'clean', 'estmemory': 22528}, - {'scheme': 'sphincs-sha256-256f-robust', 'implementation': 'clean', 'estmemory': 57344}, - {'scheme': 'sphincs-sha256-256f-simple', 'implementation': 'clean', 'estmemory': 57344}, - {'scheme': 'sphincs-sha256-256s-robust', 'implementation': 'clean', 'estmemory': 37888}, - {'scheme': 'sphincs-sha256-256s-simple', 'implementation': 'clean', 'estmemory': 37888}, - {'scheme': 'sphincs-shake256-128f-robust', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'sphincs-shake256-128f-simple', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'sphincs-shake256-128s-robust', 'implementation': 'clean', 'estmemory': 12288}, - {'scheme': 'sphincs-shake256-128s-simple', 'implementation': 'clean', 'estmemory': 12288}, - {'scheme': 'sphincs-shake256-192f-robust', 'implementation': 'clean', 'estmemory': 41984}, - {'scheme': 'sphincs-shake256-192f-simple', 'implementation': 'clean', 'estmemory': 41984}, - {'scheme': 'sphincs-shake256-192s-robust', 'implementation': 'clean', 'estmemory': 22528}, - {'scheme': 'sphincs-shake256-192s-simple', 'implementation': 'clean', 'estmemory': 21504}, - {'scheme': 'sphincs-shake256-256f-robust', 'implementation': 'clean', 'estmemory': 57344}, - {'scheme': 'sphincs-shake256-256f-simple', 'implementation': 'clean', 'estmemory': 57344}, - {'scheme': 'sphincs-shake256-256s-robust', 'implementation': 'clean', 'estmemory': 37888}, - {'scheme': 'sphincs-shake256-256s-simple', 'implementation': 'clean', 'estmemory': 37888}, - {'scheme': 'falcon-1024-tree', 'implementation': 'opt-ct', 'estmemory': 186368}, - {'scheme': 'falcon-1024-tree', 'implementation': 'opt-leaktime', 'estmemory': 186368}, + {'scheme': 'dilithium5', 'implementation': 'm4f', 'estmemory': 129024}, + {'scheme': 'falcon-1024', 'implementation': 'clean', 'estmemory': 91136}, + {'scheme': 'falcon-1024', 'implementation': 'm4-ct', 'estmemory': 89088}, + {'scheme': 'falcon-1024', 'implementation': 'opt-ct', 'estmemory': 89088}, {'scheme': 'falcon-1024', 'implementation': 'opt-leaktime', 'estmemory': 90112}, - {'scheme': 'falcon-1024', 'implementation': 'opt-ct', 'estmemory': 90112}, - {'scheme': 'falcon-512-tree', 'implementation': 'opt-ct', 'estmemory': 91136}, - {'scheme': 'falcon-512-tree', 'implementation': 'opt-leaktime', 'estmemory': 91136}, - {'scheme': 'falcon-512', 'implementation': 'opt-ct', 'estmemory': 47104}, + {'scheme': 'falcon-1024-tree', 'implementation': 'opt-ct', 'estmemory': 185344}, + {'scheme': 'falcon-1024-tree', 'implementation': 'opt-leaktime', 'estmemory': 186368}, + {'scheme': 'falcon-512', 'implementation': 'clean', 'estmemory': 48128}, + {'scheme': 'falcon-512', 'implementation': 'm4-ct', 'estmemory': 46080}, + {'scheme': 'falcon-512', 'implementation': 'opt-ct', 'estmemory': 46080}, {'scheme': 'falcon-512', 'implementation': 'opt-leaktime', 'estmemory': 47104}, - {'scheme': 'falcon-1024', 'implementation': 'm4-ct', 'estmemory': 90112}, - {'scheme': 'falcon-512-tree', 'implementation': 'm4-ct', 'estmemory': 91136}, - {'scheme': 'falcon-512', 'implementation': 'm4-ct', 'estmemory': 47104}, - {'scheme': 'rainbowI-circumzenithal', 'implementation': 'm4f', 'estmemory': 308224}, - {'scheme': 'rainbowI-classic', 'implementation': 'm4f', 'estmemory': 308224}, - {'scheme': 'rainbowI-compressed', 'implementation': 'm4f', 'estmemory': 308224}, - {'scheme': 'picnicl1full', 'implementation': 'opt', 'estmemory': 40960}, - {'scheme': 'picnicl1fs', 'implementation': 'opt', 'estmemory': 43008}, - {'scheme': 'picnic3l1', 'implementation': 'opt-mem', 'estmemory': 51200}, - {'scheme': 'picnic3l1', 'implementation': 'opt', 'estmemory': 106496}, - {'scheme': 'ov-Ip', 'implementation': 'm4f', 'estmemory': 534528}, - {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fstack', 'estmemory': 425984}, - {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fspeed', 'estmemory': 565248}, - {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fstack', 'estmemory': 425984}, - {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fspeed', 'estmemory': 425984}, - {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, - {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, - {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, - {'scheme': 'mayo3', 'implementation': 'm4f', 'estmemory': 477184}, + {'scheme': 'falcon-512-tree', 'implementation': 'm4-ct', 'estmemory': 90112}, + {'scheme': 'falcon-512-tree', 'implementation': 'opt-ct', 'estmemory': 90112}, + {'scheme': 'falcon-512-tree', 'implementation': 'opt-leaktime', 'estmemory': 91136}, + {'scheme': 'haetae2', 'implementation': 'm4f', 'estmemory': 60416}, + {'scheme': 'haetae2', 'implementation': 'ref', 'estmemory': 59392}, + {'scheme': 'haetae3', 'implementation': 'm4f', 'estmemory': 90112}, + {'scheme': 'haetae3', 'implementation': 'ref', 'estmemory': 87040}, + {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, + {'scheme': 'haetae5', 'implementation': 'ref', 'estmemory': 109568}, + {'scheme': 'hawk1024', 'implementation': 'ref', 'estmemory': 32768}, + {'scheme': 'hawk256', 'implementation': 'ref', 'estmemory': 10240}, + {'scheme': 'hawk512', 'implementation': 'ref', 'estmemory': 17408}, + {'scheme': 'hqc-128', 'implementation': 'clean', 'estmemory': 66560}, + {'scheme': 'hqc-192', 'implementation': 'clean', 'estmemory': 130048}, + {'scheme': 'hqc-256', 'implementation': 'clean', 'estmemory': 205824}, + {'scheme': 'kyber1024', 'implementation': 'clean', 'estmemory': 27648}, + {'scheme': 'kyber1024', 'implementation': 'm4fspeed', 'estmemory': 16384}, + {'scheme': 'kyber1024', 'implementation': 'm4fstack', 'estmemory': 12288}, + {'scheme': 'kyber512', 'implementation': 'clean', 'estmemory': 14336}, + {'scheme': 'kyber512', 'implementation': 'm4fspeed', 'estmemory': 10240}, + {'scheme': 'kyber512', 'implementation': 'm4fstack', 'estmemory': 7168}, + {'scheme': 'kyber768', 'implementation': 'clean', 'estmemory': 20480}, + {'scheme': 'kyber768', 'implementation': 'm4fspeed', 'estmemory': 13312}, + {'scheme': 'kyber768', 'implementation': 'm4fstack', 'estmemory': 10240}, {'scheme': 'mayo1', 'implementation': 'm4f', 'estmemory': 446464}, - {'scheme': 'mayo2', 'implementation': 'm4f', 'estmemory': 287744}, - {'scheme': 'mayo3', 'implementation': 'ref', 'estmemory': 1144832}, {'scheme': 'mayo1', 'implementation': 'ref', 'estmemory': 404480}, + {'scheme': 'mayo2', 'implementation': 'm4f', 'estmemory': 287744}, {'scheme': 'mayo2', 'implementation': 'ref', 'estmemory': 279552}, - {'scheme': 'hawk512', 'implementation': 'ref', 'estmemory': 17408}, - {'scheme': 'hawk1024', 'implementation': 'ref', 'estmemory': 32768}, - {'scheme': 'hawk256', 'implementation': 'ref', 'estmemory': 10240}, - {'scheme': 'ascon-sign-128s-simple', 'implementation': 'ref', 'estmemory': 12288}, - {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, - {'scheme': 'ascon-sign-192s-simple', 'implementation': 'ref', 'estmemory': 22528}, - {'scheme': 'ascon-sign-192f-robust', 'implementation': 'ref', 'estmemory': 43008}, - {'scheme': 'ascon-sign-192f-simple', 'implementation': 'ref', 'estmemory': 41984}, - {'scheme': 'ascon-sign-192s-robust', 'implementation': 'ref', 'estmemory': 23552}, - {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, - {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, + {'scheme': 'mayo3', 'implementation': 'm4f', 'estmemory': 477184}, + {'scheme': 'mayo3', 'implementation': 'ref', 'estmemory': 1144832}, + {'scheme': 'mceliece348864', 'implementation': 'clean', 'estmemory': 693248}, + {'scheme': 'mceliece348864f', 'implementation': 'clean', 'estmemory': 693248}, + {'scheme': 'mceliece460896', 'implementation': 'clean', 'estmemory': 1425408}, + {'scheme': 'mceliece460896f', 'implementation': 'clean', 'estmemory': 1426432}, + {'scheme': 'mceliece6688128', 'implementation': 'clean', 'estmemory': 2627584}, + {'scheme': 'mceliece6688128f', 'implementation': 'clean', 'estmemory': 2628608}, + {'scheme': 'mceliece6960119', 'implementation': 'clean', 'estmemory': 2585600}, + {'scheme': 'mceliece6960119f', 'implementation': 'clean', 'estmemory': 2586624}, + {'scheme': 'mceliece8192128', 'implementation': 'clean', 'estmemory': 3259392}, + {'scheme': 'mceliece8192128f', 'implementation': 'clean', 'estmemory': 3260416}, + {'scheme': 'meds13220', 'implementation': 'ref', 'estmemory': 209920}, + {'scheme': 'meds134180', 'implementation': 'ref', 'estmemory': 1152000}, + {'scheme': 'meds167717', 'implementation': 'ref', 'estmemory': 927744}, + {'scheme': 'meds41711', 'implementation': 'ref', 'estmemory': 1387520}, + {'scheme': 'meds55604', 'implementation': 'ref', 'estmemory': 509952}, + {'scheme': 'meds9923', 'implementation': 'ref', 'estmemory': 1019904}, {'scheme': 'mirith_IIIa_fast', 'implementation': 'ref', 'estmemory': 287744}, {'scheme': 'mirith_IIIa_short', 'implementation': 'ref', 'estmemory': 2197504}, {'scheme': 'mirith_IIIb_fast', 'implementation': 'ref', 'estmemory': 320512}, @@ -211,12 +128,12 @@ {'scheme': 'mirith_hypercube_IIIb_fast', 'implementation': 'ref', 'estmemory': 211968}, {'scheme': 'mirith_hypercube_IIIb_short', 'implementation': 'ref', 'estmemory': 526336}, {'scheme': 'mirith_hypercube_IIIb_shorter', 'implementation': 'ref', 'estmemory': 3916800}, - {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'ref', 'estmemory': 89088}, {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'opt', 'estmemory': 88064}, + {'scheme': 'mirith_hypercube_Ia_fast', 'implementation': 'ref', 'estmemory': 89088}, {'scheme': 'mirith_hypercube_Ia_short', 'implementation': 'ref', 'estmemory': 227328}, {'scheme': 'mirith_hypercube_Ia_shorter', 'implementation': 'ref', 'estmemory': 1779712}, - {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'ref', 'estmemory': 109568}, {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'opt', 'estmemory': 109568}, + {'scheme': 'mirith_hypercube_Ib_fast', 'implementation': 'ref', 'estmemory': 109568}, {'scheme': 'mirith_hypercube_Ib_short', 'implementation': 'ref', 'estmemory': 247808}, {'scheme': 'mirith_hypercube_Ib_shorter', 'implementation': 'ref', 'estmemory': 1800192}, {'scheme': 'mirith_hypercube_Va_fast', 'implementation': 'ref', 'estmemory': 344064}, @@ -225,30 +142,24 @@ {'scheme': 'mirith_hypercube_Vb_fast', 'implementation': 'ref', 'estmemory': 382976}, {'scheme': 'mirith_hypercube_Vb_short', 'implementation': 'ref', 'estmemory': 916480}, {'scheme': 'mirith_hypercube_Vb_shorter', 'implementation': 'ref', 'estmemory': 4218880}, - {'scheme': 'cross-sha3-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, - {'scheme': 'cross-sha3-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, - {'scheme': 'cross-sha3-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, - {'scheme': 'cross-sha2-r-sdp-3-small', 'implementation': 'ref', 'estmemory': 1295360}, - {'scheme': 'cross-sha2-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, - {'scheme': 'cross-sha2-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, - {'scheme': 'cross-sha2-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, - {'scheme': 'cross-sha3-r-sdp-5-small', 'implementation': 'ref', 'estmemory': 1748992}, - {'scheme': 'cross-sha2-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, - {'scheme': 'cross-sha3-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, - {'scheme': 'cross-sha2-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, - {'scheme': 'cross-sha3-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, - {'scheme': 'cross-sha3-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, - {'scheme': 'cross-sha2-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, - {'scheme': 'cross-sha2-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, - {'scheme': 'cross-sha2-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, - {'scheme': 'cross-sha2-r-sdpg-1-small', 'implementation': 'ref', 'estmemory': 477184}, - {'scheme': 'cross-sha3-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, - {'scheme': 'cross-sha3-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, - {'scheme': 'cross-sha2-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, - {'scheme': 'cross-sha2-r-sdpg-1-fast', 'implementation': 'ref', 'estmemory': 143360}, - {'scheme': 'cross-sha3-r-sdpg-3-fast', 'implementation': 'ref', 'estmemory': 230400}, - {'scheme': 'cross-sha3-r-sdp-5-fast', 'implementation': 'ref', 'estmemory': 914432}, - {'scheme': 'cross-sha3-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, + {'scheme': 'mqom_cat1_gf251_fast', 'implementation': 'ref', 'estmemory': 411648}, + {'scheme': 'mqom_cat1_gf251_short', 'implementation': 'ref', 'estmemory': 675840}, + {'scheme': 'mqom_cat1_gf31_fast', 'implementation': 'ref', 'estmemory': 624640}, + {'scheme': 'mqom_cat1_gf31_short', 'implementation': 'ref', 'estmemory': 878592}, + {'scheme': 'mqom_cat3_gf251_fast', 'implementation': 'ref', 'estmemory': 1307648}, + {'scheme': 'mqom_cat3_gf251_short', 'implementation': 'ref', 'estmemory': 1903616}, + {'scheme': 'mqom_cat3_gf31_fast', 'implementation': 'ref', 'estmemory': 2171904}, + {'scheme': 'mqom_cat3_gf31_short', 'implementation': 'ref', 'estmemory': 2688000}, + {'scheme': 'mqom_cat5_gf251_fast', 'implementation': 'ref', 'estmemory': 3260416}, + {'scheme': 'mqom_cat5_gf251_short', 'implementation': 'ref', 'estmemory': 4146176}, + {'scheme': 'ov-Ip', 'implementation': 'm4f', 'estmemory': 534528}, + {'scheme': 'ov-Ip', 'implementation': 'ref', 'estmemory': 534528}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fspeed', 'estmemory': 565248}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'm4fstack', 'estmemory': 425984}, + {'scheme': 'ov-Ip-pkc', 'implementation': 'ref', 'estmemory': 568320}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fspeed', 'estmemory': 425984}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'm4fstack', 'estmemory': 425984}, + {'scheme': 'ov-Ip-pkc-skc', 'implementation': 'ref', 'estmemory': 330752}, {'scheme': 'perk-128-fast-3', 'implementation': 'm4', 'estmemory': 33792}, {'scheme': 'perk-128-fast-3', 'implementation': 'ref', 'estmemory': 323584}, {'scheme': 'perk-128-fast-5', 'implementation': 'm4', 'estmemory': 34816}, @@ -273,81 +184,57 @@ {'scheme': 'perk-256-short-3', 'implementation': 'ref', 'estmemory': 4222976}, {'scheme': 'perk-256-short-5', 'implementation': 'm4', 'estmemory': 109568}, {'scheme': 'perk-256-short-5', 'implementation': 'ref', 'estmemory': 4221952}, - {'scheme': 'haetae2', 'implementation': 'ref', 'estmemory': 59392}, - {'scheme': 'haetae3', 'implementation': 'ref', 'estmemory': 88064}, - {'scheme': 'haetae5', 'implementation': 'ref', 'estmemory': 109568}, - {'scheme': 'haetae2', 'implementation': 'm4f', 'estmemory': 60416}, - {'scheme': 'haetae3', 'implementation': 'm4f', 'estmemory': 90112}, - {'scheme': 'haetae5', 'implementation': 'm4f', 'estmemory': 112640}, - {'scheme': 'mqom_cat5_gf251_short', 'implementation': 'ref', 'estmemory': 4146176}, - {'scheme': 'mqom_cat3_gf251_fast', 'implementation': 'ref', 'estmemory': 1307648}, - {'scheme': 'mqom_cat3_gf31_short', 'implementation': 'ref', 'estmemory': 2688000}, - {'scheme': 'mqom_cat1_gf31_fast', 'implementation': 'ref', 'estmemory': 624640}, - {'scheme': 'mqom_cat1_gf251_fast', 'implementation': 'ref', 'estmemory': 411648}, - {'scheme': 'mqom_cat5_gf251_fast', 'implementation': 'ref', 'estmemory': 3260416}, - {'scheme': 'mqom_cat3_gf31_fast', 'implementation': 'ref', 'estmemory': 2171904}, - {'scheme': 'mqom_cat1_gf31_short', 'implementation': 'ref', 'estmemory': 878592}, - {'scheme': 'mqom_cat1_gf251_short', 'implementation': 'ref', 'estmemory': 675840}, - {'scheme': 'mqom_cat3_gf251_short', 'implementation': 'ref', 'estmemory': 1903616}, - {'scheme': 'snova-43-25-16-2-esk', 'implementation': 'ref', 'estmemory': 1274880}, - {'scheme': 'snova-43-25-16-2-ssk', 'implementation': 'ref', 'estmemory': 1072128}, - {'scheme': 'snova-61-33-16-2-esk', 'implementation': 'ref', 'estmemory': 3232768}, - {'scheme': 'snova-28-17-16-2-ssk', 'implementation': 'ref', 'estmemory': 320512}, - {'scheme': 'snova-25-8-16-3-ssk', 'implementation': 'ref', 'estmemory': 194560}, - {'scheme': 'snova-25-8-16-3-esk', 'implementation': 'ref', 'estmemory': 232448}, - {'scheme': 'snova-24-5-16-4-ssk', 'implementation': 'ref', 'estmemory': 172032}, {'scheme': 'snova-24-5-16-4-esk', 'implementation': 'ref', 'estmemory': 205824}, - {'scheme': 'snova-60-10-16-4-esk', 'implementation': 'ref', 'estmemory': 2342912}, - {'scheme': 'snova-66-15-16-3-ssk', 'implementation': 'ref', 'estmemory': 2185216}, - {'scheme': 'snova-66-15-16-3-esk', 'implementation': 'ref', 'estmemory': 2617344}, - {'scheme': 'snova-49-11-16-3-ssk', 'implementation': 'ref', 'estmemory': 880640}, - {'scheme': 'snova-49-11-16-3-esk', 'implementation': 'ref', 'estmemory': 1055744}, - {'scheme': 'snova-61-33-16-2-ssk', 'implementation': 'ref', 'estmemory': 2716672}, + {'scheme': 'snova-24-5-16-4-ssk', 'implementation': 'ref', 'estmemory': 172032}, + {'scheme': 'snova-25-8-16-3-esk', 'implementation': 'ref', 'estmemory': 232448}, + {'scheme': 'snova-25-8-16-3-ssk', 'implementation': 'ref', 'estmemory': 194560}, {'scheme': 'snova-28-17-16-2-esk', 'implementation': 'ref', 'estmemory': 380928}, - {'scheme': 'snova-60-10-16-4-ssk', 'implementation': 'ref', 'estmemory': 1953792}, + {'scheme': 'snova-28-17-16-2-ssk', 'implementation': 'ref', 'estmemory': 320512}, {'scheme': 'snova-37-8-16-4-esk', 'implementation': 'ref', 'estmemory': 775168}, {'scheme': 'snova-37-8-16-4-ssk', 'implementation': 'ref', 'estmemory': 646144}, - {'scheme': 'sphincs-a-shake-128s', 'implementation': 'ref', 'estmemory': 595968}, + {'scheme': 'snova-43-25-16-2-esk', 'implementation': 'ref', 'estmemory': 1274880}, + {'scheme': 'snova-43-25-16-2-ssk', 'implementation': 'ref', 'estmemory': 1072128}, + {'scheme': 'snova-49-11-16-3-esk', 'implementation': 'ref', 'estmemory': 1055744}, + {'scheme': 'snova-49-11-16-3-ssk', 'implementation': 'ref', 'estmemory': 880640}, + {'scheme': 'snova-60-10-16-4-esk', 'implementation': 'ref', 'estmemory': 2342912}, + {'scheme': 'snova-60-10-16-4-ssk', 'implementation': 'ref', 'estmemory': 1953792}, + {'scheme': 'snova-61-33-16-2-esk', 'implementation': 'ref', 'estmemory': 3232768}, + {'scheme': 'snova-61-33-16-2-ssk', 'implementation': 'ref', 'estmemory': 2717696}, + {'scheme': 'snova-66-15-16-3-esk', 'implementation': 'ref', 'estmemory': 2617344}, + {'scheme': 'snova-66-15-16-3-ssk', 'implementation': 'ref', 'estmemory': 2185216}, + {'scheme': 'sphincs-a-sha2-128f', 'implementation': 'ref', 'estmemory': 301056}, + {'scheme': 'sphincs-a-sha2-128s', 'implementation': 'ref', 'estmemory': 595968}, + {'scheme': 'sphincs-a-sha2-192f', 'implementation': 'ref', 'estmemory': 542720}, + {'scheme': 'sphincs-a-sha2-192s', 'implementation': 'ref', 'estmemory': 1307648}, + {'scheme': 'sphincs-a-sha2-256f', 'implementation': 'ref', 'estmemory': 1124352}, + {'scheme': 'sphincs-a-sha2-256s', 'implementation': 'ref', 'estmemory': 2291712}, {'scheme': 'sphincs-a-shake-128f', 'implementation': 'ref', 'estmemory': 301056}, - {'scheme': 'sphincs-a-shake-192s', 'implementation': 'ref', 'estmemory': 1307648}, + {'scheme': 'sphincs-a-shake-128s', 'implementation': 'ref', 'estmemory': 595968}, {'scheme': 'sphincs-a-shake-192f', 'implementation': 'ref', 'estmemory': 541696}, - {'scheme': 'sphincs-a-shake-256s', 'implementation': 'ref', 'estmemory': 2291712}, + {'scheme': 'sphincs-a-shake-192s', 'implementation': 'ref', 'estmemory': 1306624}, {'scheme': 'sphincs-a-shake-256f', 'implementation': 'ref', 'estmemory': 1124352}, - {'scheme': 'sphincs-a-sha2-128s', 'implementation': 'ref', 'estmemory': 596992}, - {'scheme': 'sphincs-a-sha2-128f', 'implementation': 'ref', 'estmemory': 302080}, - {'scheme': 'sphincs-a-sha2-192s', 'implementation': 'ref', 'estmemory': 1307648}, - {'scheme': 'sphincs-a-sha2-192f', 'implementation': 'ref', 'estmemory': 542720}, - {'scheme': 'sphincs-a-sha2-256s', 'implementation': 'ref', 'estmemory': 2292736}, - {'scheme': 'sphincs-a-sha2-256f', 'implementation': 'ref', 'estmemory': 1125376}, - {'scheme': 'aimer-l1-param2', 'implementation': 'ref', 'estmemory': 461824}, - {'scheme': 'aimer-l1-param1', 'implementation': 'ref', 'estmemory': 206848}, - {'scheme': 'aimer-l3-param1', 'implementation': 'ref', 'estmemory': 452608}, - {'scheme': 'aimer-l5-param1', 'implementation': 'ref', 'estmemory': 926720}, - {'scheme': 'aimer-l3-param2', 'implementation': 'ref', 'estmemory': 1091584}, - {'scheme': 'aimer-l5-param2', 'implementation': 'ref', 'estmemory': 2169856}, - {'scheme': 'aimer-l1-param3', 'implementation': 'ref', 'estmemory': 1442816}, - {'scheme': 'meds167717', 'implementation': 'ref', 'estmemory': 927744}, - {'scheme': 'meds41711', 'implementation': 'ref', 'estmemory': 1388544}, - {'scheme': 'meds13220', 'implementation': 'ref', 'estmemory': 210944}, - {'scheme': 'meds134180', 'implementation': 'ref', 'estmemory': 1152000}, - {'scheme': 'meds9923', 'implementation': 'ref', 'estmemory': 1021952}, - {'scheme': 'meds55604', 'implementation': 'ref', 'estmemory': 510976}, - {'scheme': 'biscuit128f', 'implementation': 'ref', 'estmemory': 145408}, - {'scheme': 'biscuit128s', 'implementation': 'ref', 'estmemory': 1099776}, - {'scheme': 'biscuit192f', 'implementation': 'ref', 'estmemory': 282624}, - {'scheme': 'biscuit192s', 'implementation': 'ref', 'estmemory': 2257920}, - {'scheme': 'biscuit256f', 'implementation': 'ref', 'estmemory': 505856}, - {'scheme': 'biscuit256s', 'implementation': 'ref', 'estmemory': 4004864}, + {'scheme': 'sphincs-a-shake-256s', 'implementation': 'ref', 'estmemory': 2291712}, + {'scheme': 'sphincs-sha2-128f-simple', 'implementation': 'clean', 'estmemory': 21504}, + {'scheme': 'sphincs-sha2-128s-simple', 'implementation': 'clean', 'estmemory': 12288}, + {'scheme': 'sphincs-sha2-192f-simple', 'implementation': 'clean', 'estmemory': 43008}, + {'scheme': 'sphincs-sha2-192s-simple', 'implementation': 'clean', 'estmemory': 23552}, + {'scheme': 'sphincs-sha2-256f-simple', 'implementation': 'clean', 'estmemory': 59392}, + {'scheme': 'sphincs-sha2-256s-simple', 'implementation': 'clean', 'estmemory': 39936}, + {'scheme': 'sphincs-shake-128f-simple', 'implementation': 'clean', 'estmemory': 21504}, + {'scheme': 'sphincs-shake-128s-simple', 'implementation': 'clean', 'estmemory': 12288}, + {'scheme': 'sphincs-shake-192f-simple', 'implementation': 'clean', 'estmemory': 41984}, + {'scheme': 'sphincs-shake-192s-simple', 'implementation': 'clean', 'estmemory': 22528}, + {'scheme': 'sphincs-shake-256f-simple', 'implementation': 'clean', 'estmemory': 59392}, + {'scheme': 'sphincs-shake-256s-simple', 'implementation': 'clean', 'estmemory': 38912}, + {'scheme': 'tuov_iii', 'implementation': 'ref', 'estmemory': 3281920}, + {'scheme': 'tuov_iii_pkc', 'implementation': 'ref', 'estmemory': 3468288}, + {'scheme': 'tuov_iii_pkc_skc', 'implementation': 'ref', 'estmemory': 3790848}, {'scheme': 'tuov_ip', 'implementation': 'ref', 'estmemory': 3790848}, {'scheme': 'tuov_ip_pkc', 'implementation': 'ref', 'estmemory': 799744}, {'scheme': 'tuov_ip_pkc_skc', 'implementation': 'ref', 'estmemory': 865280}, {'scheme': 'tuov_is', 'implementation': 'ref', 'estmemory': 1111040}, {'scheme': 'tuov_is_pkc', 'implementation': 'ref', 'estmemory': 1176576}, {'scheme': 'tuov_is_pkc_skc', 'implementation': 'ref', 'estmemory': 1275904}, - {'scheme': 'tuov_iii', 'implementation': 'ref', 'estmemory': 3280896}, - {'scheme': 'tuov_iii_pkc', 'implementation': 'ref', 'estmemory': 3468288}, - {'scheme': 'tuov_iii_pkc_skc', 'implementation': 'ref', 'estmemory': 3790848}, - {'scheme': 'tuov_v', 'implementation': 'ref', 'estmemory': 8388608}, {'scheme': 'tuov_v_pkc', 'implementation': 'ref', 'estmemory': 7083008}, {'scheme': 'tuov_v_pkc_skc', 'implementation': 'ref', 'estmemory': 4639744}, ] From b15618e6ffd87b934c30073d4280b9183c0a3022 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Tue, 27 Feb 2024 21:55:55 +0100 Subject: [PATCH 079/107] Update README.md to reflect the changes --- README.md | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 485c0ecc..082dce55 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ The design goals of the library are to offer ## Previous NIST PQC -The master branch of **pqm4** contains schemes that either [selected for standardization by NIST](https://csrc.nist.gov/Projects/post-quantum-cryptography/selected-algorithms-2022) or part of the [4th round of the NIST PQC competition](https://csrc.nist.gov/Projects/post-quantum-cryptography/round-4-submissions). +The master branch of **pqm4** contains schemes that either [selected for standardization by NIST](https://csrc.nist.gov/Projects/post-quantum-cryptography/selected-algorithms-2022), +part of the [4th round of the NIST PQC standardization process](https://csrc.nist.gov/Projects/post-quantum-cryptography/round-4-submissions), +or part or the [first round of additional signatures of the NIST PQC standardization process](https://csrc.nist.gov/projects/pqc-dig-sig/round-1-additional-signatures). Implementations for previous NIST PQC rounds are available here: - Round 3: https://github.com/mupq/pqm4/releases/tag/Round3 @@ -26,13 +28,23 @@ Implementations for previous NIST PQC rounds are available here: - Round 1: https://github.com/mupq/pqm4/releases/tag/Round1 ## Changes in Round 2 -For the second round of the NIST PQC, **pqm4** was extended (see [#78](https://github.com/mupq/pqm4/pull/78)) with the following features: +For the second round of the NIST PQC process, **pqm4** was extended (see [#78](https://github.com/mupq/pqm4/pull/78)) with the following features: - common code was moved to [mupq](https://github.com/mupq/mupq) for reuse in [pqriscv](https://github.com/mupq/pqriscv), - much simpler build process, - automated profiling of cycles spent in symmetric primitives (SHA-2, SHA-3, AES), - reporting of code-size, - integration of clean implementations from [PQClean](https://github.com/PQClean/PQClean). +## Changes in Round 3 +For the third round of the NIST PQC process, **pqm4** was extended with the following features: +- overhaul of the build process to support multiple target boards, and +- use of the QEMU simulator to measure stack usage of larger schemes. + +## Changes in Round 4 / Round 1 of Additional signatures +For the fourth round of the NIST PQC process **pqm4** was extended with the following features: +- Switch to the Nucleo-L4R5ZI board as the default board for measurements, and +- an overhaul of the console output. + ## Schemes included in pqm4 For most of the schemes there are multiple implementations. @@ -47,7 +59,10 @@ The naming scheme for these implementations is as follows: The testing and benchmarking framework of **pqm4** targets several development boards, all featuring an ARM Cortex-M4 chip: -* `stm32f4discovery` (default): The [STM32F4 Discovery board](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) +* `nucleo-l4r5zi` (default): The [NUCLEO-L4R5ZI board](https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html) + featuring 2MB of Flash and 640KB of RAM. This board does not require a + separate USB serial interface converter. +* `stm32f4discovery`: The [STM32F4 Discovery board](https://www.st.com/en/evaluation-tools/stm32f4discovery.html) featuring 1MB of Flash, and 192KB of RAM. Connecting the development to the host computer requires a mini-USB cable and a USB-TTL converter together with a 2-pin dupont / jumper cable. @@ -56,9 +71,6 @@ boards, all featuring an ARM Cortex-M4 chip: separate USB serial interface converter. * `cw308t-stm32f3`: The ChipWhisperer [CW308-STM32F3 target board](https://rtfm.newae.com/Targets/UFO%20Targets/CW308T-STM32F/) (in the F3 configuration) featuring 256KB of Flash and 40KB of RAM. -* `nucleo-l4r5zi`: The [NUCLEO-L4R5ZI board](https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html) - featuring 2MB of Flash and 640KB of RAM. This board does not require a - separate USB serial interface converter. * `mps2-an386`: The ARM MPS2(+) FPGA prototyping board when used with the ARM-Cortex M4 bitstream (see [ARM AN386](https://developer.arm.com/documentation/dai0386/c)) featuring two 4MB RAM blocks, one used in lieu of Flash one as RAM. This board @@ -67,7 +79,7 @@ boards, all featuring an ARM Cortex-M4 chip: ### Installing the ARM toolchain The **pqm4** build system assumes that you have the [arm-none-eabi toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) -toolchain installed. +toolchain installed. All benchmarks are performed using this toolchain. On most Linux systems, the correct toolchain gets installed when you install the `arm-none-eabi-gcc` (or `gcc-arm-none-eabi`) package. On some Linux distributions, you will also have to explicitly install `libnewlib-arm-none-eabi` . @@ -78,12 +90,12 @@ refer to the stlink Github page for instructions on how to [compile it from sour (in that case, be careful to use libusb-1.0.0-dev, not libusb-0.1). ### Installing OpenOCD -For the `nucleo-l4r5zi` board [OpenOCD](http://openocd.org) (tested with version 0.11) is used for flashing binaries. +For the `nucleo-l4r5zi` board [OpenOCD](http://openocd.org) (tested with version 0.12) is used for flashing binaries. Depending on your operating system, OpenOCD may be available in your package manager -- if not, please refer to the OpenOCD README for instructions on how to [compile it from source](http://openocd.org/doc-release/README). ### Python3 -The benchmarking scripts used in **pqm4** require Python >= 3.6. +The benchmarking scripts used in **pqm4** require Python >= 3.8. ### Installing pyserial The host-side Python code for most platforms requires the [pyserial](https://github.com/pyserial/pyserial) module. From 470917e1f8897eecd06e792c0ba6996e28da39cd Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Sun, 17 Mar 2024 21:38:08 +0100 Subject: [PATCH 080/107] Update mupq --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 6ea4e1e6..66102a0c 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 6ea4e1e6a7f8b7f41c2b6f91b38d92f69bcc22fa +Subproject commit 66102a0c237849e7c88adb88cfa4934b398a3a0b From 527e9d626633161fdb3c95c9ca50dd0170914e94 Mon Sep 17 00:00:00 2001 From: Richard Petri Date: Sun, 17 Mar 2024 21:36:16 +0100 Subject: [PATCH 081/107] Update benchmarks --- benchmarks.csv | 872 ++++++++++++++++++++++++++++++++----------------- benchmarks.md | 872 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 1144 insertions(+), 600 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index 5abed05d..9270fca8 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -1,320 +1,592 @@ Speed Evaluation,,,,,,,,,, Key Encapsulation Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Encapsulation [cycles] (mean),Encapsulation [cycles] (min),Encapsulation [cycles] (max),Decapsulation [cycles] (mean),Decapsulation [cycles] (min),Decapsulation [cycles] (max) -bikel1 (100 executions),m4f,24974536,24950520,24991477,3394030,3378190,3414910,51214664,51198795,51235513 -bikel1 (100 executions),opt,68198074,68181729,68218850,5085537,5068825,5101896,121429912,121416187,121446269 -hqc-rmrs-128 (100 executions),clean,2883811,2850356,3090278,5236720,5150902,5554288,7594631,7482072,7890446 -kyber1024 (100 executions),clean,1649604,1646417,1686328,2016366,2013177,2053070,2159906,2156716,2196609 -kyber1024 (100 executions),m4fspeed,1122936,1120610,1147966,1315737,1313449,1340766,1209901,1207648,1234899 -kyber1024 (100 executions),m4fstack,1126561,1124115,1138795,1323943,1321497,1336212,1219060,1216614,1231295 -kyber1024-90s (100 executions),clean,3008837,3007295,3024024,3275730,3274235,3290907,3516691,3515163,3531901 -kyber1024-90s (100 executions),m4fspeed,973196,961657,978853,1068184,1056648,1073886,1059775,1048239,1065477 -kyber1024-90s (100 executions),m4fstack,979692,972492,985031,1079272,1072072,1084611,1071817,1064616,1077155 -kyber512 (100 executions),clean,636181,635670,648917,843945,843433,856680,940320,939808,953055 -kyber512 (100 executions),m4fspeed,434438,433217,446786,530469,529247,542816,476712,475491,489060 -kyber512 (100 executions),m4fstack,433718,433191,446122,531676,531150,544080,478166,477640,490570 -kyber512-90s (100 executions),clean,948446,947802,964084,1112852,1112208,1128491,1261630,1260986,1277269 -kyber512-90s (100 executions),m4fspeed,369011,364769,373816,421685,417443,426490,420333,416092,425139 -kyber512-90s (100 executions),m4fstack,369736,361461,370708,424339,416065,425312,423234,414960,424207 -kyber768 (100 executions),clean,1059876,1057827,1071809,1352934,1350884,1364866,1471055,1469005,1482987 -kyber768 (100 executions),m4fspeed,706531,703969,718271,863343,860765,875091,783369,780788,795114 -kyber768 (100 executions),m4fstack,707275,705435,719983,867363,865520,880070,788053,786210,800760 -kyber768-90s (100 executions),clean,1816649,1815810,1831510,2032562,2031722,2047390,2225597,2224757,2240425 -kyber768-90s (100 executions),m4fspeed,614455,610716,619096,694064,690330,698723,688999,685265,693658 -kyber768-90s (100 executions),m4fstack,617709,613688,622666,700599,696577,705555,696202,692181,701159 +bikel1 (10 executions),m4f,27382389,27382366,27382406,3363252,3363238,3363291,56744036,56744013,56744062 +bikel1 (10 executions),opt,76272765,76272741,76272809,5295900,5295877,5295931,138514606,138514541,138514711 +bikel3 (10 executions),m4f,66285221,66285184,66285235,8441498,8441478,8441521,150282952,150282849,150282974 +bikel3 (10 executions),opt,248083316,248083286,248083345,16405238,16405236,16405241,423262047,423261952,423262086 +hqc-128 (10 executions),clean,52705201,52705180,52705224,105650897,105650877,105650927,159569179,159569176,159569183 +hqc-192 (10 executions),clean,161458617,161458590,161458638,323146261,323146250,323146292,486156251,486156214,486156266 +hqc-256 (10 executions),clean,295934078,295934057,295934104,591853870,591853850,591853898,891163005,891162988,891163038 +kyber1024 (10 executions),m4fspeed,1004995,1004386,1005713,1023370,1022780,1024086,1094273,1093643,1094989 +kyber1024 (10 executions),m4fstack,1011563,1007750,1019668,1035234,1031419,1043376,1106876,1103061,1114980 +kyber512 (10 executions),m4fspeed,387426,387191,387884,386486,386251,386942,427576,427342,428033 +kyber512 (10 executions),m4fstack,387995,386694,398090,389242,387941,399338,430376,429075,440473 +kyber768 (10 executions),m4fspeed,632049,631494,632680,651880,651323,652515,706301,705744,706936 +kyber768 (10 executions),m4fstack,635213,632659,643980,658865,656311,667633,713751,711197,722519 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) -dilithium2 (10000 executions),clean,1944539,1890031,1991828,7144383,3140649,63849339,2064129,2063522,2064634 -dilithium2 (10000 executions),m4f,1597999,1543482,1644972,4111596,1975193,28355968,1571804,1571197,1572305 -dilithium2aes (10000 executions),clean,4995899,4936813,5118217,11648989,6130462,61958375,4669616,4610387,4791733 -dilithium3 (10000 executions),clean,3365142,3363198,3378304,11634591,4892049,79793644,3430286,3429812,3430778 -dilithium3 (10000 executions),m4f,2830024,2828027,2832150,6588465,3224221,46880624,2691283,2690800,2691739 -dilithium3aes (10000 executions),clean,8980662,8870698,9135481,19843507,10319280,112310317,8314038,8205198,8468692 -dilithium5 (10000 executions),m4f,4826422,4737706,4914744,8779067,5416181,52012847,4705693,4705090,4706259 -falcon-1024 (100 executions),clean,589059133,334912351,1243184474,133598726,133189548,133921649,1547336,1546772,1548051 -falcon-1024 (100 executions),m4-ct,480071949,271647441,1227690897,85125001,84882111,85556430,994972,983996,1002867 -falcon-1024 (100 executions),opt-ct,437448136,271659962,1092676507,85113093,84848956,85473992,994270,984187,1002619 -falcon-1024 (100 executions),opt-leaktime,413908640,243261195,1126577305,76314462,75745413,76892801,994634,982708,1002471 -falcon-512 (100 executions),clean,217740948,129494100,511780471,61102456,60847251,61330321,774876,774536,775376 -falcon-512 (100 executions),m4-ct,155757768,101804738,436771421,38979435,38774219,39146132,481452,472089,488157 -falcon-512 (100 executions),opt-ct,169979748,101804734,511094390,38995196,38771533,39280349,481457,472109,488208 -falcon-512 (100 executions),opt-leaktime,154344796,89719505,442643356,35503133,35166340,35923860,480806,472450,489614 -falcon-512-tree (100 executions),m4-ct,179772454,116934668,497881688,17649735,17489319,17847797,480619,471367,488548 -falcon-512-tree (100 executions),opt-ct,185495778,116934665,591766146,17664284,17480589,17824518,482085,472168,488509 -falcon-512-tree (100 executions),opt-leaktime,157683545,101416387,370593247,19162650,18816478,19426978,481577,472170,488230 -sphincs-haraka-128f-robust (3 executions),clean,106427973,106427961,106427997,2699060638,2698241211,2699997157,174647895,173477158,176638141 -sphincs-haraka-128f-simple (3 executions),clean,74934480,74934458,74934492,1887299882,1887134522,1887382565,118143703,113925327,123851044 -sphincs-haraka-128s-robust (3 executions),clean,6775943571,6775943546,6775943591,53822326627,53821272834,53824434213,68158360,65114417,72841330 -sphincs-haraka-128s-simple (3 executions),clean,4758339537,4758339511,4758339556,37472069032,37470580002,37474550750,44603270,44272388,44768737 -sphincs-haraka-192f-robust (3 executions),clean,157886973,157886961,157886995,4729109673,4724305900,4731687311,261039514,258813178,263734554 -sphincs-haraka-192f-simple (3 executions),clean,110403519,110403498,110403532,3167446164,3164466253,3169681094,171820185,169915924,174138430 -sphincs-haraka-192s-robust (3 executions),clean,10070301104,10070301092,10070301120,105836052151,105833943123,105838864162,102385564,100510789,104729057 -sphincs-haraka-192s-simple (3 executions),clean,7028359469,7028359462,7028359475,69349184156,69348190870,69350922453,64929339,63356226,65840010 -sphincs-haraka-256f-robust (3 executions),clean,422110917,422110915,422110921,9925037310,9919761990,9929258109,282995607,280533063,286865365 -sphincs-haraka-256f-simple (3 executions),clean,293499115,293499091,293499129,6701863848,6699462526,6705176025,183796029,182221816,186447361 -sphincs-haraka-256s-robust (3 executions),clean,6739159318,6739159309,6739159328,105302624797,105300748903,105304266285,156467817,154826875,159398072 -sphincs-haraka-256s-simple (3 executions),clean,4683144675,4683144642,4683144705,69202732323,69201324370,69205052507,101719411,100063540,104037675 -sphincs-sha256-128f-robust (3 executions),clean,29123270,29123249,29123282,716257523,715884705,716674437,42248922,41497196,42869922 -sphincs-sha256-128f-simple (3 executions),clean,15388375,15388352,15388387,382533954,382308022,382976925,21150671,20677650,21741991 -sphincs-sha256-128s-robust (3 executions),clean,1864047221,1864042048,1864050532,14012634889,14012400685,14012822953,14847302,14422375,15206848 -sphincs-sha256-128s-simple (3 executions),clean,985367046,985355790,985385031,7495603716,7495252193,7496247958,7165875,6861584,7419441 -sphincs-sha256-192f-robust (3 executions),clean,43116184,43116173,43116205,1195381634,1193980671,1196819904,64857703,64364605,65153579 -sphincs-sha256-192f-simple (3 executions),clean,22645923,22645911,22645947,639321913,639157877,639638579,32940330,31955780,33534443 -sphincs-sha256-192s-robust (3 executions),clean,2758781668,2758721187,2758814880,25556205325,25555467827,25556897376,23195383,22702335,23589803 -sphincs-sha256-192s-simple (3 executions),clean,1450073477,1449766386,1450529270,13764196955,13762891584,13765362825,11763703,11695761,11899525 -sphincs-sha256-256f-robust (3 executions),clean,158034870,158034868,158034873,3305447599,3303450474,3306582779,94366505,92087788,96189482 -sphincs-sha256-256f-simple (3 executions),clean,59808433,59807808,59808748,1281329322,1280242352,1282332972,32947097,32522594,33490507 -sphincs-sha256-256s-robust (3 executions),clean,2524393357,2524337328,2524432487,31056826302,31055874069,31057485164,47434569,46022129,48212821 -sphincs-sha256-256s-simple (3 executions),clean,952799879,952642357,953062293,12304132668,12303657740,12304436252,16715346,16326849,17137621 -sphincs-shake256-128f-robust (3 executions),clean,113347070,113347058,113347093,2788974930,2787812662,2790137173,158730948,156406568,160667913 -sphincs-shake256-128f-simple (3 executions),clean,59759081,59759080,59759082,1483676214,1483213924,1484204563,83065165,81414021,84584221 -sphincs-shake256-128s-robust (3 executions),clean,7255773038,7255773014,7255773057,54573950176,54572529688,54575241560,53615181,51549111,55423008 -sphincs-shake256-128s-simple (3 executions),clean,3825341548,3825341531,3825341564,29086410120,29085749525,29087533088,29495105,28966755,30155531 -sphincs-shake256-192f-robust (3 executions),clean,167154323,167154303,167154334,4461897673,4458767619,4464636487,240590626,238634394,243329332 -sphincs-shake256-192f-simple (3 executions),clean,88333405,88333405,88333406,2409188992,2408787940,2409991046,123334622,122866683,123668857 -sphincs-shake256-192s-robust (3 executions),clean,10698254977,10698254964,10698254997,93298513700,93295644767,93301121760,81201582,77549977,83809891 -sphincs-shake256-192s-simple (3 executions),clean,5652907918,5652907897,5652907934,50824666973,50823330463,50826137107,41687543,40818602,42623345 -sphincs-shake256-256f-robust (3 executions),clean,444922977,444922967,444922998,8993352645,8987821428,9000464222,243254884,240752880,244703467 -sphincs-shake256-256f-simple (3 executions),clean,235448503,235448502,235448505,4865464381,4864247499,4867289711,127387108,125561248,129010103 -sphincs-shake256-256s-robust (3 executions),clean,7117488480,7117488473,7117488486,81040359080,81037593485,81043519709,124099579,123967874,124362934 -sphincs-shake256-256s-simple (3 executions),clean,3764358451,3764358431,3764358466,44857260081,44856516353,44858138896,62264803,61656689,62670229 +aimer-l1-param1 (10 executions),ref,392943,392938,392977,32386301,32386203,32386424,31111672,31111588,31111782 +aimer-l1-param2 (10 executions),ref,392938,392938,392941,79450721,79450349,79451595,78429263,78398061,78434987 +aimer-l3-param1 (10 executions),ref,981288,981288,981290,90953716,90953603,90953763,88350755,88350600,88350906 +ascon-sign-128f-robust (10 executions),ref,122506162,122506099,122506254,2855797836,2855797243,2855798602,174707763,169973472,179525137 +ascon-sign-128f-simple (10 executions),ref,69376878,69376875,69376883,1629111557,1629111334,1629112028,97798317,95509050,98714007 +ascon-sign-128s-robust (10 executions),ref,7842366557,7842366432,7842366620,59267552580,59267543517,59267565672,60232378,57865239,62848708 +ascon-sign-128s-simple (10 executions),ref,4441129007,4441128624,4441129583,33877719255,33877704467,33877739518,33665713,31101669,34993483 +ascon-sign-192f-robust (10 executions),ref,222614206,222614156,222614345,5712962198,5712960682,5712963829,321026499,315341414,327745233 +ascon-sign-192f-simple (10 executions),ref,128167067,128167038,128167083,3345487807,3345484178,3345492588,179328421,175094665,183794127 +ascon-sign-192s-robust (10 executions),ref,14249838562,14249837693,14249840118,126646612223,126646594160,126646651564,111451290,108763808,114965691 +ascon-sign-192s-simple (10 executions),ref,8204011592,8204011246,8204011971,74760768141,74760751354,74760789761,61679880,58983014,64202741 +biscuit128f (10 executions),ref,1054719,1054719,1054720,274072426,274072411,274072461,254371114,254371087,254371140 +biscuit192f (10 executions),ref,1886203,1886199,1886238,765314258,765314227,765314291,713412502,713412394,713412608 +biscuit256f (10 executions),ref,3301990,3301983,3302022,1747187940,1747187918,1747187973,1678998604,1678998013,1678998987 +cross-sha2-r-sdp-1-fast (10 executions),ref,5614888,5590276,5650611,216566013,215745202,217395250,143008126,141803162,144002548 +cross-sha2-r-sdp-3-fast (10 executions),ref,8201340,8148672,8208465,241899820,241815860,242049039,123896179,123524606,124545760 +cross-sha2-r-sdpg-1-fast (10 executions),ref,2151163,2115797,2174685,116162852,116120174,116181821,87741423,87209686,88267494 +cross-sha2-r-sdpg-1-small (10 executions),ref,2151212,2115845,2174734,391718680,391662566,391774957,368397996,367703173,369416443 +cross-sha2-r-sdpg-3-fast (10 executions),ref,3049185,2996960,3055381,136242875,136234139,136299163,84236165,83659318,85067521 +cross-sha2-r-sdpg-5-fast (10 executions),ref,4302017,4249738,4308343,221761047,221758357,221762936,134821310,134547992,135025658 +cross-sha3-r-sdp-1-fast (10 executions),ref,967965,963482,978861,58864285,58853041,58876854,30641221,30631654,30661122 +cross-sha3-r-sdp-3-fast (10 executions),ref,2195040,2191401,2205040,90064203,90034522,90080511,48561804,48542657,48577008 +cross-sha3-r-sdpg-1-fast (10 executions),ref,290136,287742,297758,29963868,29960918,29974902,20093649,20078626,20103416 +cross-sha3-r-sdpg-1-small (10 executions),ref,290135,287741,297757,102853622,102847774,102861948,75137510,75126803,75159685 +cross-sha3-r-sdpg-3-fast (10 executions),ref,627948,625525,637639,43573841,43565461,43582933,27513830,27493024,27525746 +cross-sha3-r-sdpg-5-fast (10 executions),ref,1146280,1142409,1153794,93557878,93547167,93566329,59948216,59857434,60043852 +dilithium2 (90 executions),clean,1873447,1838554,1903845,7846622,3321671,28761609,2062804,2062332,2063181 +dilithium2 (100 executions),m4f,1427684,1390524,1466437,4219137,1813668,12587382,1417706,1417251,1418128 +dilithium3 (90 executions),clean,3205542,3204354,3206592,12108503,5097440,50759276,3377010,3376729,3377395 +dilithium3 (100 executions),m4f,2515970,2514894,2516922,5896583,2935265,23718896,2411234,2410948,2411551 +dilithium5 (90 executions),clean,5346066,5287239,5395626,15205929,7953360,49173429,5609664,5609137,5610119 +dilithium5 (100 executions),m4f,4273211,4210308,4329697,8062110,4882708,18398575,4185407,4184878,4185954 +falcon-1024 (10 executions),m4-ct,354880005,284902033,635131652,87741288,87506676,87922628,991320,982548,997219 +falcon-1024 (10 executions),opt-ct,555202324,284912829,1157528581,87710190,87606677,87841235,993584,983066,997523 +falcon-1024 (10 executions),opt-leaktime,438412062,334858742,625013074,80139483,79891200,80551967,994127,984891,997390 +falcon-1024-tree (10 executions),opt-ct,500950316,327706067,969046860,39207109,39013867,39449442,992787,982032,998080 +falcon-1024-tree (10 executions),opt-leaktime,372505822,284807343,551245131,42213136,41842229,42582424,995859,984960,998421 +falcon-512 (10 executions),m4-ct,161245486,110088298,279215300,40225282,40072879,40389913,478930,472982,485577 +falcon-512 (10 executions),opt-ct,151650543,116181731,228216352,40147309,40003575,40360540,480990,472795,485260 +falcon-512 (10 executions),opt-leaktime,159608965,111149933,301580807,37267337,36991076,37518518,478421,471680,484872 +falcon-512-tree (10 executions),m4-ct,167653515,121618919,272326714,18250061,18135371,18325579,479823,471774,485540 +falcon-512-tree (10 executions),opt-ct,184949574,121623805,270290280,18248036,18069599,18462666,484565,484059,485335 +falcon-512-tree (10 executions),opt-leaktime,156710258,106732109,326634247,20050613,19891001,20227947,482101,472948,485643 +haetae2 (100 executions),m4f,6743278,1555292,25393506,21993963,4721290,86765689,918459,918244,918668 +haetae2 (100 executions),ref,9363639,1716264,41895014,31631089,6247382,216853925,1104080,1103874,1104329 +haetae3 (100 executions),m4f,12925388,2752846,52240529,30891994,7467529,160522018,1760745,1760408,1761081 +haetae3 (100 executions),ref,20247658,3023325,101863701,41078691,9771906,168213225,1998105,1997691,1998406 +haetae5 (100 executions),m4f,19064310,3530778,94189003,44679058,9277906,182948586,2323830,2323454,2324229 +haetae5 (100 executions),ref,18169623,3864921,64304046,63180459,12011324,264538555,2461679,2461294,2462068 +hawk1024 (100 executions),ref,246017495,183762252,662190563,4309675,4309595,4309759,2782441,2780257,2784348 +hawk256 (100 executions),ref,15758436,11600791,35345186,1042002,954957,2294025,627815,627480,628077 +hawk512 (100 executions),ref,53733289,45271209,174603165,1972051,1971984,1972127,1293829,1292946,1294494 +mayo1 (10 executions),m4f,5242008,5241998,5242042,9100704,9100681,9100722,4952860,4952848,4952890 +mayo1 (10 executions),ref,7977004,7976973,7977015,18005446,18005440,18005487,6294480,6294464,6294503 +mayo2 (10 executions),m4f,11917959,11917940,11917980,11979613,11979582,11979624,5130148,5130131,5130180 +mayo2 (10 executions),ref,18432706,18432701,18432740,23546659,23546640,23546680,5494246,5494236,5494276 +mayo3 (10 executions),m4f,18946738,18946737,18946740,32477408,32477407,32477411,16852927,16852799,16853047 +meds13220 (10 executions),ref,47801890,47796259,47805424,1774401869,1773011038,1779733959,1767764521,1766326468,1773152168 +meds55604 (10 executions),ref,253603604,253590695,253615749,8009948412,8009909000,8009995748,8320756990,8320682364,8320835448 +mirith_IIIa_fast (10 executions),ref,3009088,3009084,3009123,891195817,891191657,891198221,831725932,831697264,831742620 +mirith_IIIb_fast (10 executions),ref,4565011,4565007,4565046,1298812706,1298810546,1298815343,1214260655,1214247570,1214277229 +mirith_Ia_fast (10 executions),ref,1303728,1303721,1303764,296732107,296728990,296734109,276059526,276031297,276080171 +mirith_Ib_fast (10 executions),ref,2514924,2514920,2514964,565778762,565776437,565781372,528408968,528400758,528415550 +mirith_Va_fast (10 executions),ref,6254885,6254885,6254887,2373353150,2373347664,2373358665,2233960878,2233908923,2234010721 +mirith_Vb_fast (10 executions),ref,8807561,8807538,8807580,3406388587,3406385114,3406391954,3205119426,3205069724,3205181151 +mirith_hypercube_IIIa_fast (10 executions),ref,3009085,3009081,3009121,323235292,323169167,323309072,313483184,313455293,313507476 +mirith_hypercube_IIIa_short (10 executions),ref,3009092,3009084,3009125,718708882,718706940,718725922,730959561,730953898,730965347 +mirith_hypercube_IIIb_fast (10 executions),ref,4565028,4565013,4565053,450970203,450912625,451011870,441590516,441574663,441613045 +mirith_hypercube_IIIb_short (10 executions),ref,4565027,4565008,4565047,845096869,845094881,845114293,860321543,860312205,860325520 +mirith_hypercube_Ia_fast (10 executions),opt,995563,995419,995752,58999862,58972041,59042031,53599779,53565299,53623234 +mirith_hypercube_Ia_fast (10 executions),ref,1303715,1303715,1303718,116964064,116941316,116990779,111505597,111482197,111525936 +mirith_hypercube_Ia_short (10 executions),ref,1303722,1303721,1303724,370999431,370999393,370999483,364000112,363996085,364002214 +mirith_hypercube_Ib_fast (10 executions),opt,1879815,1879488,1880127,83825209,83797728,83857763,78145476,78137727,78153192 +mirith_hypercube_Ib_fast (10 executions),ref,2514929,2514917,2514959,205510181,205497961,205547801,199772762,199769009,199782994 +mirith_hypercube_Ib_short (10 executions),ref,2514920,2514920,2514923,447351952,447351902,447351992,440279587,440278101,440281382 +mirith_hypercube_Va_fast (10 executions),ref,6254896,6254886,6254922,808070687,808007911,808157180,792058628,792006360,792098565 +mirith_hypercube_Vb_fast (10 executions),ref,8807565,8807542,8807583,1134272446,1134201632,1134368110,1117085816,1117059819,1117104354 +mqom_cat1_gf251_fast (10 executions),ref,7780082,7761398,7795766,149063790,149045955,149079787,136742778,136613266,136821602 +mqom_cat1_gf31_fast (10 executions),ref,8472628,8471619,8473585,243796920,243782136,243811088,244346110,244239828,244424317 +ov-Ip (10 executions),m4f,139186121,139186115,139186154,2465106,2465096,2465133,993538,979943,997098 +ov-Ip (10 executions),ref,350783613,350783583,350783641,6479343,6479329,6479364,1301328,1301328,1301329 +ov-Ip-pkc (10 executions),m4fspeed,175417340,175417323,175417366,2484348,2484345,2484383,11197952,11185489,11202816 +ov-Ip-pkc (10 executions),m4fstack,175417332,175417319,175417363,2484355,2484351,2484391,12047546,12033622,12049099 +ov-Ip-pkc (10 executions),ref,375129899,375129876,375129925,6924383,6924364,6924403,11429702,11429685,11429720 +ov-Ip-pkc-skc (10 executions),m4fspeed,175417478,175417464,175417508,89193259,89193250,89193291,11987533,11972791,11991175 +ov-Ip-pkc-skc (10 executions),m4fstack,175417481,175417467,175417513,89193257,89193252,89193294,12046865,12036910,12049102 +ov-Ip-pkc-skc (10 executions),ref,375129970,375129961,375129979,241521035,241521010,241521062,12160652,12160649,12160655 +perk-128-fast-3 (10 executions),m4,600370,588589,617172,176603058,172398218,179515947,80954403,80639115,81369755 +perk-128-fast-3 (10 executions),ref,704259,693368,736117,217778838,217461187,218268228,96466250,96183326,96888788 +perk-128-fast-5 (10 executions),m4,731441,731364,731540,169489946,165666000,172125278,78073374,77727738,78357997 +perk-128-fast-5 (10 executions),ref,913665,909095,954075,215313534,214778346,215586755,93670132,93146285,93977473 +perk-128-short-3 (10 executions),m4,590902,588605,599700,953694810,909659772,990039092,460190199,458863203,461050669 +perk-128-short-5 (10 executions),m4,731445,731335,731531,897819203,874104462,910961959,428108291,426956727,428829873 +perk-192-fast-3 (10 executions),m4,1417042,1416960,1417171,417178570,409941430,430893116,194559724,193854854,195157065 +perk-192-fast-5 (10 executions),m4,1674275,1664390,1675499,398534166,393310316,407792875,186556828,185719616,187993601 +perk-192-short-3 (10 executions),m4,1421844,1416962,1464701,2361914331,2294967247,2446192375,1177027799,1172107658,1180352563 +perk-192-short-5 (10 executions),m4,1675264,1674747,1675426,2199500885,2155317947,2244259412,1098396172,1096382473,1100817952 +perk-256-fast-3 (10 executions),m4,2473015,2472888,2473216,878427616,863486856,896605165,418401493,416315010,421403946 +perk-256-fast-5 (10 executions),m4,2885058,2878858,2939569,826739240,816655441,839215281,397855320,396898494,398693053 +perk-256-short-3 (10 executions),m4,2478803,2472893,2531188,5056839759,5015570985,5098913929,2638814692,2626576274,2645713279 +perk-256-short-5 (10 executions),m4,2889949,2878822,2988248,4678162399,4520673553,4740505898,2453866153,2446870524,2460260204 +snova-24-5-16-4-esk (10 executions),ref,24840838,24840391,24841191,139251354,139235721,139274512,88454046,88453528,88454429 +snova-24-5-16-4-ssk (10 executions),ref,24772323,24771821,24772994,174094748,160180156,299202162,88453756,88453293,88454408 +snova-25-8-16-3-esk (10 executions),ref,35280792,35280693,35280867,71674196,65171606,130098735,42542485,42542403,42542553 +snova-25-8-16-3-ssk (10 executions),ref,35195324,35195216,35195579,112654217,93165980,158103540,42542507,42542396,42542732 +snova-28-17-16-2-esk (10 executions),ref,51177590,51177548,51177647,23387139,21270788,42311786,19180389,19180360,19180440 +snova-28-17-16-2-ssk (10 executions),ref,51065038,51064999,51065086,52865514,50757388,71788606,19180379,19180357,19180425 +snova-37-8-16-4-ssk (10 executions),ref,122023801,122023399,122024216,533063912,533033960,533090127,335806349,335805890,335806820 +sphincs-a-sha2-128f (10 executions),ref,30278936,30278762,30279211,382270810,382269421,382271497,35695646,35693840,35698828 +sphincs-a-sha2-128s (10 executions),ref,814836852,814834574,814838039,6981930727,6981924687,6981936443,187090082,187087928,187093600 +sphincs-a-sha2-192f (10 executions),ref,45930664,45930481,45930983,634374072,634373011,634375225,35145783,35144266,35146607 +sphincs-a-shake-128f (10 executions),ref,61578406,61578107,61578885,1188147363,1188146489,1188148063,76330135,76328602,76331478 +sphincs-a-shake-128s (10 executions),ref,2342298427,2342296403,2342299607,22926754899,22926752978,22926758555,241835141,241830735,241838908 +sphincs-a-shake-192f (10 executions),ref,110027677,110027323,110027950,1814954350,1814953585,1814955913,64022276,64020853,64023988 +sphincs-sha2-128f-simple (10 executions),clean,15742990,15742958,15742996,368575228,368575193,368575246,21923628,21369867,22456717 +sphincs-sha2-128s-simple (10 executions),clean,1007731522,1007731504,1007731551,7657558168,7657558117,7657558212,7471794,7228491,7797915 +sphincs-sha2-192f-simple (10 executions),clean,23570224,23570214,23570257,666398438,666398401,666398468,35457937,35087854,35973969 +sphincs-sha2-192s-simple (10 executions),clean,1509654951,1509654914,1509654968,15452089990,15452089934,15452090071,13494855,12947211,14303224 +sphincs-sha2-256f-simple (10 executions),clean,62583556,62583533,62583577,1377768608,1377768561,1377768713,37302611,36599268,38058007 +sphincs-sha2-256s-simple (10 executions),clean,1001040810,1001040779,1001040845,14326202444,14326202404,14326202506,19637153,18985943,20132079 +sphincs-shake-128f-simple (10 executions),clean,50505025,50505022,50505030,1182422563,1182422491,1182422621,70501834,68595319,71605565 +sphincs-shake-128s-simple (10 executions),clean,3231401965,3231401936,3231402005,24553696412,24553696311,24553696516,24366771,22962144,25470425 +sphincs-shake-192f-simple (10 executions),clean,74890591,74890566,74890617,1937690056,1937690000,1937690169,103305801,101234011,104969964 +sphincs-shake-192s-simple (10 executions),clean,4793551013,4793550980,4793551045,43114327277,43114327182,43114327407,35026412,33413152,36300013 +sphincs-shake-256f-simple (10 executions),clean,200110912,200110878,200110926,4026533198,4026533128,4026533250,108394619,106138946,111648895 +sphincs-shake-256s-simple (10 executions),clean,3201898694,3201898656,3201898741,38175697620,38175697525,38175697766,52912174,51224772,53979746 Memory Evaluation,,,,,,,,,, Key Encapsulation Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Encapsulation [bytes],Decapsulation [bytes],,,,,, -bikel1,m4f,44084,32132,91384,,,,,, -bikel1,opt,36000,25908,78588,,,,,, -hqc-rmrs-128,clean,48852,64436,71172,,,,,, -kyber1024,clean,15100,18772,20348,,,,,, -kyber1024,m4fspeed,6400,7496,7512,,,,,, -kyber1024,m4fstack,3296,3368,3392,,,,,, -kyber1024-90s,clean,15364,19044,20620,,,,,, -kyber1024-90s,m4fspeed,7156,8252,8268,,,,,, -kyber1024-90s,m4fstack,4060,4132,4156,,,,,, -kyber512,clean,6116,8780,9556,,,,,, -kyber512,m4fspeed,4320,5424,5432,,,,,, -kyber512,m4fstack,2248,2336,2352,,,,,, -kyber512-90s,clean,6572,9236,10012,,,,,, -kyber512-90s,m4fspeed,5076,6180,6188,,,,,, -kyber512-90s,m4fstack,3012,3100,3116,,,,,, -kyber768,clean,10212,13380,14476,,,,,, -kyber768,m4fspeed,5344,6456,6472,,,,,, -kyber768,m4fstack,2784,2856,2872,,,,,, -kyber768-90s,clean,10676,13844,14940,,,,,, -kyber768-90s,m4fspeed,6108,7220,7236,,,,,, -kyber768-90s,m4fstack,3540,3612,3628,,,,,, +bikel1,m4f,43976,32192,91372,,,,,, +bikel1,opt,35748,25836,78540,,,,,, +bikel3,m4f,85744,62944,175128,,,,,, +bikel3,opt,69444,50556,155388,,,,,, +hqc-128,clean,33644,51428,55892,,,,,, +hqc-192,clean,65668,101636,110660,,,,,, +hqc-256,clean,103756,161508,175972,,,,,, +kyber1024,clean,15136,18784,20360,,,,,, +kyber1024,m4fspeed,6436,7500,9076,,,,,, +kyber1024,m4fstack,3332,3372,4948,,,,,, +kyber512,clean,6168,8800,9576,,,,,, +kyber512,m4fspeed,4364,5436,6212,,,,,, +kyber512,m4fstack,2292,2348,3124,,,,,, +kyber768,clean,10272,13408,14504,,,,,, +kyber768,m4fspeed,5396,6468,7564,,,,,, +kyber768,m4fstack,2820,2860,3956,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, -dilithium2,clean,38308,51932,36220,,,,,, -dilithium2,m4f,38408,49380,36212,,,,,, -dilithium2aes,clean,39776,53400,37688,,,,,, -dilithium3,clean,60844,79588,57732,,,,,, -dilithium3,m4f,60836,68836,57724,,,,,, -dilithium3aes,clean,62312,81056,59200,,,,,, -dilithium5,m4f,97692,115932,92788,,,,,, -falcon-1024,clean,36296,82532,8820,,,,,, -falcon-1024,m4-ct,1400,2644,412,,,,,, -falcon-1024,opt-ct,1384,2644,520,,,,,, -falcon-1024,opt-leaktime,1368,2716,412,,,,,, -falcon-512,clean,18416,42508,4724,,,,,, -falcon-512,m4-ct,1312,2556,412,,,,,, -falcon-512,opt-ct,1344,2556,412,,,,,, -falcon-512,opt-leaktime,1296,2620,412,,,,,, -falcon-512-tree,m4-ct,1408,2796,412,,,,,, -falcon-512-tree,opt-ct,1384,2796,412,,,,,, -falcon-512-tree,opt-leaktime,1344,2804,412,,,,,, -sphincs-haraka-128f-robust,clean,3636,3728,4188,,,,,, -sphincs-haraka-128f-simple,clean,3628,3720,4180,,,,,, -sphincs-haraka-128s-robust,clean,3960,3920,3492,,,,,, -sphincs-haraka-128s-simple,clean,3872,3912,3484,,,,,, -sphincs-haraka-192f-robust,clean,5044,5192,5412,,,,,, -sphincs-haraka-192f-simple,clean,5064,5184,5404,,,,,, -sphincs-haraka-192s-robust,clean,5392,5352,4748,,,,,, -sphincs-haraka-192s-simple,clean,5456,5344,4740,,,,,, -sphincs-haraka-256f-robust,clean,7044,7120,7020,,,,,, -sphincs-haraka-256f-simple,clean,7036,7032,7012,,,,,, -sphincs-haraka-256s-robust,clean,7424,7264,6640,,,,,, -sphincs-haraka-256s-simple,clean,7416,7256,6632,,,,,, -sphincs-sha256-128f-robust,clean,2276,2340,2828,,,,,, -sphincs-sha256-128f-simple,clean,2124,2188,2676,,,,,, -sphincs-sha256-128s-robust,clean,2492,2560,2132,,,,,, -sphincs-sha256-128s-simple,clean,2340,2408,1980,,,,,, -sphincs-sha256-192f-robust,clean,3692,3840,4060,,,,,, -sphincs-sha256-192f-simple,clean,3532,3680,3900,,,,,, -sphincs-sha256-192s-robust,clean,4004,4000,3396,,,,,, -sphincs-sha256-192s-simple,clean,3952,3840,3236,,,,,, -sphincs-sha256-256f-robust,clean,5700,5776,5676,,,,,, -sphincs-sha256-256f-simple,clean,5532,5500,5508,,,,,, -sphincs-sha256-256s-robust,clean,6080,5920,5268,,,,,, -sphincs-sha256-256s-simple,clean,5804,5752,5100,,,,,, -sphincs-shake256-128f-robust,clean,2036,2200,2580,,,,,, -sphincs-shake256-128f-simple,clean,2036,2092,2580,,,,,, -sphincs-shake256-128s-robust,clean,2360,2312,1896,,,,,, -sphincs-shake256-128s-simple,clean,2360,2312,1884,,,,,, -sphincs-shake256-192f-robust,clean,3452,3592,3812,,,,,, -sphincs-shake256-192f-simple,clean,3452,3484,3812,,,,,, -sphincs-shake256-192s-robust,clean,3872,3752,3148,,,,,, -sphincs-shake256-192s-simple,clean,3872,3752,3148,,,,,, -sphincs-shake256-256f-robust,clean,5460,5528,5428,,,,,, -sphincs-shake256-256f-simple,clean,5460,5528,5428,,,,,, -sphincs-shake256-256s-robust,clean,5840,5672,5020,,,,,, -sphincs-shake256-256s-simple,clean,5840,5672,5020,,,,,, +aimer-l1-param1,ref,10952,187724,196728,,,,,, +aimer-l1-param2,ref,10952,442668,451672,,,,,, +aimer-l3-param1,ref,23864,413940,435640,,,,,, +ascon-sign-128f-robust,ref,3260,2772,2992,,,,,, +ascon-sign-128f-simple,ref,2632,2144,2448,,,,,, +ascon-sign-128s-robust,ref,3452,2916,2240,,,,,, +ascon-sign-128s-simple,ref,2824,2268,1752,,,,,, +ascon-sign-192f-robust,ref,6092,4924,4504,,,,,, +ascon-sign-192f-simple,ref,4808,3640,3704,,,,,, +ascon-sign-192s-robust,ref,6380,5116,4332,,,,,, +ascon-sign-192s-simple,ref,5096,3812,3048,,,,,, +biscuit128f,ref,600,137348,14560,,,,,, +biscuit192f,ref,640,265964,20796,,,,,, +biscuit256f,ref,720,477468,33108,,,,,, +cross-sha2-r-sdp-1-fast,ref,5200,218304,105604,,,,,, +cross-sha2-r-sdp-3-fast,ref,9920,324764,158132,,,,,, +cross-sha2-r-sdpg-1-fast,ref,2760,130824,69536,,,,,, +cross-sha2-r-sdpg-1-small,ref,2760,466288,245480,,,,,, +cross-sha2-r-sdpg-3-fast,ref,4536,205148,108452,,,,,, +cross-sha2-r-sdpg-5-fast,ref,7408,398612,213684,,,,,, +cross-sha3-r-sdp-1-fast,ref,4672,218400,105576,,,,,, +cross-sha3-r-sdp-3-fast,ref,9336,324688,157792,,,,,, +cross-sha3-r-sdpg-1-fast,ref,2328,130928,69560,,,,,, +cross-sha3-r-sdpg-1-small,ref,2328,466400,245512,,,,,, +cross-sha3-r-sdpg-3-fast,ref,4032,205080,108236,,,,,, +cross-sha3-r-sdpg-5-fast,ref,6824,398600,213436,,,,,, +dilithium2,clean,38304,51968,36192,,,,,, +dilithium2,m4f,38296,49416,36184,,,,,, +dilithium3,clean,60832,79616,57728,,,,,, +dilithium3,m4f,60824,68864,57720,,,,,, +dilithium5,clean,97696,122724,92940,,,,,, +dilithium5,m4f,97688,116076,92824,,,,,, +falcon-1024,clean,34988,84604,8784,,,,,, +falcon-1024,m4-ct,1156,2508,376,,,,,, +falcon-1024,opt-ct,1156,2508,376,,,,,, +falcon-1024,opt-leaktime,1212,2580,376,,,,,, +falcon-1024-tree,opt-ct,1252,2772,376,,,,,, +falcon-1024-tree,opt-leaktime,1212,2988,376,,,,,, +falcon-512,clean,18092,43548,4688,,,,,, +falcon-512,m4-ct,1156,2428,376,,,,,, +falcon-512,opt-ct,1156,2428,376,,,,,, +falcon-512,opt-leaktime,1156,2492,376,,,,,, +falcon-512-tree,m4-ct,1212,2636,376,,,,,, +falcon-512-tree,opt-ct,1156,2636,376,,,,,, +falcon-512-tree,opt-leaktime,1212,2828,376,,,,,, +haetae2,m4f,19756,55568,23296,,,,,, +haetae2,ref,26092,54444,29696,,,,,, +haetae3,m4f,29596,83420,31784,,,,,, +haetae3,ref,43492,80428,48424,,,,,, +haetae5,m4f,34084,103964,37300,,,,,, +haetae5,ref,54868,100228,62024,,,,,, +hawk1024,ref,27972,7980,11468,,,,,, +hawk256,ref,7900,3320,3712,,,,,, +hawk512,ref,14580,4856,6272,,,,,, +mayo1,m4f,74444,113468,440676,,,,,, +mayo1,ref,74444,218644,399348,,,,,, +mayo2,m4f,111532,124644,278444,,,,,, +mayo2,ref,111532,238324,270260,,,,,, +mayo3,m4f,244748,340668,469780,,,,,, +meds13220,ref,44000,180404,47716,,,,,, +meds55604,ref,162196,392852,160324,,,,,, +mirith_IIIa_fast,ref,21832,266480,46156,,,,,, +mirith_IIIb_fast,ref,32872,298208,59172,,,,,, +mirith_Ia_fast,ref,10208,122424,22836,,,,,, +mirith_Ib_fast,ref,19064,151016,33764,,,,,, +mirith_Va_fast,ref,45000,484464,85252,,,,,, +mirith_Vb_fast,ref,62864,535176,106004,,,,,, +mirith_hypercube_IIIa_fast,ref,21832,167024,42692,,,,,, +mirith_hypercube_IIIa_short,ref,21832,486448,56596,,,,,, +mirith_hypercube_IIIb_fast,ref,32872,189520,55244,,,,,, +mirith_hypercube_IIIb_short,ref,32872,509056,68632,,,,,, +mirith_hypercube_Ia_fast,opt,10216,76944,20864,,,,,, +mirith_hypercube_Ia_fast,ref,10208,76944,20864,,,,,, +mirith_hypercube_Ia_short,ref,10208,217624,31212,,,,,, +mirith_hypercube_Ib_fast,opt,19072,96928,31316,,,,,, +mirith_hypercube_Ib_fast,ref,19064,96928,31316,,,,,, +mirith_hypercube_Ib_short,ref,19064,237408,41220,,,,,, +mirith_hypercube_Va_fast,ref,45000,308440,81056,,,,,, +mirith_hypercube_Vb_fast,ref,62864,344832,101220,,,,,, +mqom_cat1_gf251_fast,ref,184356,399396,252684,,,,,, +mqom_cat1_gf31_fast,ref,262888,612816,421596,,,,,, +ov-Ip,m4f,15676,5216,2512,,,,,, +ov-Ip,ref,15724,12728,6236,,,,,, +ov-Ip-pkc,m4fspeed,142244,5216,280944,,,,,, +ov-Ip-pkc,m4fstack,142244,5216,6548,,,,,, +ov-Ip-pkc,ref,15724,12728,284560,,,,,, +ov-Ip-pkc-skc,m4fspeed,380164,243128,281028,,,,,, +ov-Ip-pkc-skc,m4fstack,380164,243128,6548,,,,,, +ov-Ip-pkc-skc,ref,253628,253580,284560,,,,,, +perk-128-fast-3,m4,7696,24020,20684,,,,,, +perk-128-fast-3,ref,7728,313412,313284,,,,,, +perk-128-fast-5,m4,9032,25160,21752,,,,,, +perk-128-fast-5,ref,9032,305688,305480,,,,,, +perk-128-short-3,m4,7696,27780,25228,,,,,, +perk-128-short-5,m4,9032,28616,26056,,,,,, +perk-192-fast-3,m4,14952,47720,41352,,,,,, +perk-192-fast-5,m4,16864,48776,42416,,,,,, +perk-192-short-3,m4,14952,51344,46656,,,,,, +perk-192-short-5,m4,16864,51888,47256,,,,,, +perk-256-fast-3,m4,25504,80304,69912,,,,,, +perk-256-fast-5,m4,28064,80896,70640,,,,,, +perk-256-short-3,m4,25504,82264,74784,,,,,, +perk-256-short-5,m4,28064,82056,74808,,,,,, +snova-24-5-16-4-esk,ref,169008,89984,118152,,,,,, +snova-24-5-16-4-ssk,ref,169008,169104,118152,,,,,, +snova-25-8-16-3-esk,ref,190696,87400,122656,,,,,, +snova-25-8-16-3-ssk,ref,190696,190836,122656,,,,,, +snova-28-17-16-2-esk,ref,309216,127232,199684,,,,,, +snova-28-17-16-2-ssk,ref,309216,309356,199684,,,,,, +snova-37-8-16-4-ssk,ref,640324,640428,411516,,,,,, +sphincs-a-sha2-128f,ref,281168,280772,280656,,,,,, +sphincs-a-sha2-128s,ref,585984,585732,585396,,,,,, +sphincs-a-sha2-192f,ref,504084,502636,502356,,,,,, +sphincs-a-shake-128f,ref,281072,280676,280560,,,,,, +sphincs-a-shake-128s,ref,585888,585636,585264,,,,,, +sphincs-a-shake-192f,ref,503544,502092,501816,,,,,, +sphincs-sha2-128f-simple,clean,2856,2468,2664,,,,,, +sphincs-sha2-128s-simple,clean,3084,2556,1968,,,,,, +sphincs-sha2-192f-simple,clean,5468,4404,4356,,,,,, +sphincs-sha2-192s-simple,clean,5796,4540,3700,,,,,, +sphincs-sha2-256f-simple,clean,8460,6412,5980,,,,,, +sphincs-sha2-256s-simple,clean,8756,6540,5580,,,,,, +sphincs-shake-128f-simple,clean,2760,2372,2568,,,,,, +sphincs-shake-128s-simple,clean,2988,2460,1872,,,,,, +sphincs-shake-192f-simple,clean,4928,3860,3816,,,,,, +sphincs-shake-192s-simple,clean,5252,3996,3160,,,,,, +sphincs-shake-256f-simple,clean,7928,5876,5448,,,,,, +sphincs-shake-256s-simple,clean,8220,6004,5048,,,,,, +tuov_v,ref,503544,502092,501816,,,,,, Hashing Evaluation,,,,,,,,,, Key Encapsulation Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Encapsulation [%],Decapsulation [%],,,,,, -bikel1,m4f,0.7,15.1,1.0,,,,,, -bikel1,opt,0.3,10.1,0.4,,,,,, -hqc-rmrs-128,clean,54.7,42.3,33.8,,,,,, -kyber1024,clean,54.0,53.6,42.5,,,,,, -kyber1024,m4fspeed,79.1,81.9,75.6,,,,,, -kyber1024,m4fstack,78.8,81.4,75.0,,,,,, -kyber1024-90s,clean,73.6,70.4,63.8,,,,,, -kyber1024-90s,m4fspeed,70.7,72.9,67.5,,,,,, -kyber1024-90s,m4fstack,70.2,72.2,66.8,,,,,, -kyber512,clean,54.3,51.6,36.9,,,,,, -kyber512,m4fspeed,79.4,82.0,72.7,,,,,, -kyber512,m4fstack,79.4,81.7,72.4,,,,,, -kyber512-90s,clean,68.4,62.6,52.5,,,,,, -kyber512-90s,m4fspeed,72.2,74.2,66.2,,,,,, -kyber512-90s,m4fstack,72.1,73.8,65.7,,,,,, -kyber768,clean,52.4,52.3,39.5,,,,,, -kyber768,m4fspeed,78.4,81.8,74.0,,,,,, -kyber768,m4fstack,78.3,81.3,73.5,,,,,, -kyber768-90s,clean,71.2,67.3,59.3,,,,,, -kyber768-90s,m4fspeed,70.6,73.1,66.5,,,,,, -kyber768-90s,m4fstack,70.3,72.5,65.9,,,,,, +bikel1,m4f,0.2,15.9,0.9,,,,,, +bikel1,opt,0.1,10.1,0.4,,,,,, +bikel3,m4f,0.1,12.2,0.7,,,,,, +bikel3,opt,0.0,6.3,0.2,,,,,, +hqc-128,clean,0.4,0.8,0.5,,,,,, +hqc-192,clean,0.3,0.5,0.3,,,,,, +hqc-256,clean,0.2,0.4,0.3,,,,,, +kyber1024,clean,49.9,45.7,38.6,,,,,, +kyber1024,m4fspeed,76.1,75.9,71.0,,,,,, +kyber1024,m4fstack,75.8,75.2,70.4,,,,,, +kyber512,clean,49.8,41.4,32.6,,,,,, +kyber512,m4fspeed,76.5,74.4,67.3,,,,,, +kyber512,m4fstack,76.6,74.0,67.0,,,,,, +kyber768,clean,48.4,43.2,35.4,,,,,, +kyber768,m4fspeed,75.4,74.9,69.1,,,,,, +kyber768,m4fstack,75.3,74.3,68.6,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, -dilithium2,clean,68.2,38.8,61.4,,,,,, -dilithium2,m4f,82.8,65.5,80.5,,,,,, -dilithium2aes,clean,2.8,3.6,5.2,,,,,, -dilithium3,clean,71.6,38.7,64.9,,,,,, -dilithium3,m4f,85.0,64.8,82.6,,,,,, -dilithium3aes,clean,2.3,2.4,3.7,,,,,, -dilithium5,m4f,86.0,69.2,84.5,,,,,, -falcon-1024,clean,8.2,0.3,26.9,,,,,, -falcon-1024,m4-ct,11.0,0.5,34.0,,,,,, -falcon-1024,opt-ct,11.0,0.5,34.0,,,,,, -falcon-1024,opt-leaktime,12.8,0.5,34.0,,,,,, -falcon-512,clean,13.1,0.4,29.3,,,,,, -falcon-512,m4-ct,18.3,0.5,35.7,,,,,, -falcon-512,opt-ct,18.3,0.5,35.7,,,,,, -falcon-512,opt-leaktime,19.6,0.6,35.8,,,,,, -falcon-512-tree,m4-ct,15.9,1.2,35.7,,,,,, -falcon-512-tree,opt-ct,16.2,1.2,35.6,,,,,, -falcon-512-tree,opt-leaktime,16.8,1.1,35.9,,,,,, -sphincs-haraka-128f-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-128f-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-128s-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-128s-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-192f-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-192f-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-192s-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-192s-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-256f-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-256f-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-256s-robust,clean,0.0,0.0,0.0,,,,,, -sphincs-haraka-256s-simple,clean,0.0,0.0,0.0,,,,,, -sphincs-sha256-128f-robust,clean,87.7,87.7,87.8,,,,,, -sphincs-sha256-128f-simple,clean,85.3,85.2,85.1,,,,,, -sphincs-sha256-128s-robust,clean,87.7,87.6,87.7,,,,,, -sphincs-sha256-128s-simple,clean,85.3,85.1,85.0,,,,,, -sphincs-sha256-192f-robust,clean,87.2,87.4,87.6,,,,,, -sphincs-sha256-192f-simple,clean,84.9,85.1,85.1,,,,,, -sphincs-sha256-192s-robust,clean,87.3,87.5,87.9,,,,,, -sphincs-sha256-192s-simple,clean,84.9,85.2,85.6,,,,,, -sphincs-sha256-256f-robust,clean,90.9,91.0,91.3,,,,,, -sphincs-sha256-256f-simple,clean,84.6,84.8,84.9,,,,,, -sphincs-sha256-256s-robust,clean,91.1,91.1,91.6,,,,,, -sphincs-sha256-256s-simple,clean,84.9,85.4,85.6,,,,,, -sphincs-shake256-128f-robust,clean,97.4,97.4,97.5,,,,,, -sphincs-shake256-128f-simple,clean,95.7,95.7,95.7,,,,,, -sphincs-shake256-128s-robust,clean,97.5,97.4,97.4,,,,,, -sphincs-shake256-128s-simple,clean,95.7,95.7,95.6,,,,,, -sphincs-shake256-192f-robust,clean,97.4,97.3,97.4,,,,,, -sphincs-shake256-192f-simple,clean,95.7,95.6,95.6,,,,,, -sphincs-shake256-192s-robust,clean,97.4,97.3,97.4,,,,,, -sphincs-shake256-192s-simple,clean,95.7,95.6,95.6,,,,,, -sphincs-shake256-256f-robust,clean,97.4,97.3,97.4,,,,,, -sphincs-shake256-256f-simple,clean,95.6,95.6,95.6,,,,,, -sphincs-shake256-256s-robust,clean,97.4,97.2,97.4,,,,,, -sphincs-shake256-256s-simple,clean,95.7,95.6,95.6,,,,,, +aimer-l1-param1,ref,72.0,47.2,46.7,,,,,, +aimer-l1-param2,ref,72.0,48.7,48.7,,,,,, +aimer-l3-param1,ref,77.4,41.7,41.6,,,,,, +ascon-sign-128f-robust,ref,0.0,0.0,0.0,,,,,, +ascon-sign-128f-simple,ref,0.0,0.0,0.0,,,,,, +ascon-sign-128s-robust,ref,0.0,0.0,0.0,,,,,, +ascon-sign-128s-simple,ref,0.0,0.0,0.0,,,,,, +ascon-sign-192f-robust,ref,0.0,0.0,0.0,,,,,, +ascon-sign-192f-simple,ref,0.0,0.0,0.0,,,,,, +ascon-sign-192s-robust,ref,0.0,0.0,0.0,,,,,, +ascon-sign-192s-simple,ref,0.0,0.0,0.0,,,,,, +biscuit128f,ref,54.3,9.7,8.9,,,,,, +biscuit192f,ref,54.0,6.0,5.5,,,,,, +biscuit256f,ref,54.0,4.4,4.2,,,,,, +cross-sha2-r-sdp-1-fast,ref,90.2,86.3,91.0,,,,,, +cross-sha2-r-sdp-3-fast,ref,86.5,79.8,81.7,,,,,, +cross-sha2-r-sdpg-1-fast,ref,92.9,90.9,92.1,,,,,, +cross-sha2-r-sdpg-1-small,ref,92.9,90.6,92.9,,,,,, +cross-sha2-r-sdpg-3-fast,ref,90.5,87.2,86.9,,,,,, +cross-sha2-r-sdpg-5-fast,ref,88.0,83.0,82.4,,,,,, +cross-sha3-r-sdp-1-fast,ref,67.1,61.2,72.0,,,,,, +cross-sha3-r-sdp-3-fast,ref,67.7,57.5,62.4,,,,,, +cross-sha3-r-sdpg-1-fast,ref,71.8,74.8,77.1,,,,,, +cross-sha3-r-sdpg-1-small,ref,71.8,74.7,78.4,,,,,, +cross-sha3-r-sdpg-3-fast,ref,71.7,68.2,68.7,,,,,, +cross-sha3-r-sdpg-5-fast,ref,71.1,66.1,66.8,,,,,, +dilithium2,clean,60.9,30.2,52.9,,,,,, +dilithium2,m4f,79.9,62.2,76.8,,,,,, +dilithium3,clean,64.7,33.8,56.8,,,,,, +dilithium3,m4f,82.3,57.9,79.4,,,,,, +dilithium5,clean,67.0,38.4,61.1,,,,,, +dilithium5,m4f,83.4,63.5,81.7,,,,,, +falcon-1024,clean,6.5,0.3,23.7,,,,,, +falcon-1024,m4-ct,7.4,0.4,32.4,,,,,, +falcon-1024,opt-ct,11.7,0.4,32.2,,,,,, +falcon-1024,opt-leaktime,12.3,0.5,32.4,,,,,, +falcon-1024-tree,opt-ct,5.2,0.9,32.3,,,,,, +falcon-1024-tree,opt-leaktime,11.9,0.9,32.4,,,,,, +falcon-512,clean,10.9,0.4,26.0,,,,,, +falcon-512,m4-ct,15.3,0.5,34.3,,,,,, +falcon-512,opt-ct,17.2,0.5,33.6,,,,,, +falcon-512,opt-leaktime,16.0,0.5,33.8,,,,,, +falcon-512-tree,m4-ct,18.4,1.1,33.9,,,,,, +falcon-512-tree,opt-ct,14.5,1.1,33.9,,,,,, +falcon-512-tree,opt-leaktime,18.7,1.0,33.9,,,,,, +haetae2,m4f,12.4,56.7,54.1,,,,,, +haetae2,ref,10.6,42.4,45.1,,,,,, +haetae3,m4f,14.6,56.6,57.1,,,,,, +haetae3,ref,14.4,42.4,50.3,,,,,, +haetae5,m4f,15.7,56.6,57.5,,,,,, +haetae5,ref,15.7,42.8,54.3,,,,,, +hawk1024,ref,1.7,49.3,8.3,,,,,, +hawk256,ref,32.8,54.6,10.7,,,,,, +hawk512,ref,2.6,48.7,8.6,,,,,, +mayo1,m4f,59.5,35.0,63.0,,,,,, +mayo1,ref,39.1,17.7,49.6,,,,,, +mayo2,m4f,35.2,35.5,81.2,,,,,, +mayo2,ref,22.8,18.1,75.8,,,,,, +mayo3,m4f,55.4,32.6,62.2,,,,,, +meds13220,ref,2.5,5.1,4.8,,,,,, +meds55604,ref,1.6,3.0,2.9,,,,,, +mirith_IIIa_fast,ref,64.3,6.7,6.5,,,,,, +mirith_IIIb_fast,ref,64.5,4.7,4.6,,,,,, +mirith_Ia_fast,ref,61.4,10.1,9.7,,,,,, +mirith_Ib_fast,ref,61.2,6.6,6.4,,,,,, +mirith_Va_fast,ref,64.8,4.3,4.4,,,,,, +mirith_Vb_fast,ref,64.5,3.1,3.2,,,,,, +mirith_hypercube_IIIa_fast,ref,64.3,18.7,17.1,,,,,, +mirith_hypercube_IIIa_short,ref,64.3,54.7,56.1,,,,,, +mirith_hypercube_IIIb_fast,ref,64.5,13.7,12.4,,,,,, +mirith_hypercube_IIIb_short,ref,64.5,47.3,48.4,,,,,, +mirith_hypercube_Ia_fast,opt,78.1,51.5,49.1,,,,,, +mirith_hypercube_Ia_fast,ref,61.4,26.7,24.3,,,,,, +mirith_hypercube_Ia_short,ref,61.4,66.7,67.1,,,,,, +mirith_hypercube_Ib_fast,opt,79.5,44.8,42.3,,,,,, +mirith_hypercube_Ib_fast,ref,61.2,18.7,17.0,,,,,, +mirith_hypercube_Ib_short,ref,61.2,56.6,56.8,,,,,, +mirith_hypercube_Va_fast,ref,64.8,13.4,12.3,,,,,, +mirith_hypercube_Vb_fast,ref,64.5,11.0,10.1,,,,,, +mqom_cat1_gf251_fast,ref,73.5,33.0,33.1,,,,,, +mqom_cat1_gf31_fast,ref,64.6,19.8,19.2,,,,,, +ov-Ip,m4f,7.5,0.9,1.1,,,,,, +ov-Ip,ref,3.0,0.3,0.9,,,,,, +ov-Ip-pkc,m4fspeed,6.4,0.9,81.5,,,,,, +ov-Ip-pkc,m4fstack,6.4,0.9,81.4,,,,,, +ov-Ip-pkc,ref,3.0,0.3,80.0,,,,,, +ov-Ip-pkc-skc,m4fspeed,6.4,12.5,81.7,,,,,, +ov-Ip-pkc-skc,m4fstack,6.4,12.5,81.4,,,,,, +ov-Ip-pkc-skc,ref,3.0,4.7,80.7,,,,,, +perk-128-fast-3,m4,68.9,67.0,71.6,,,,,, +perk-128-fast-3,ref,58.8,28.4,61.5,,,,,, +perk-128-fast-5,m4,62.8,65.8,70.6,,,,,, +perk-128-fast-5,ref,50.5,27.2,60.1,,,,,, +perk-128-short-3,m4,68.8,65.7,69.8,,,,,, +perk-128-short-5,m4,62.7,64.6,68.6,,,,,, +perk-192-fast-3,m4,73.2,67.4,72.2,,,,,, +perk-192-fast-5,m4,67.7,66.5,71.3,,,,,, +perk-192-short-3,m4,73.3,64.3,66.1,,,,,, +perk-192-short-5,m4,67.5,63.3,64.8,,,,,, +perk-256-fast-3,m4,74.4,69.9,74.9,,,,,, +perk-256-fast-5,m4,68.2,69.1,74.1,,,,,, +perk-256-short-3,m4,74.1,65.0,65.5,,,,,, +perk-256-short-5,m4,68.3,63.7,64.0,,,,,, +snova-24-5-16-4-esk,ref,12.2,0.0,3.4,,,,,, +snova-24-5-16-4-ssk,ref,12.2,1.9,3.4,,,,,, +snova-25-8-16-3-esk,ref,9.6,0.1,8.0,,,,,, +snova-25-8-16-3-ssk,ref,9.7,3.5,8.0,,,,,, +snova-28-17-16-2-esk,ref,10.6,0.2,28.1,,,,,, +snova-28-17-16-2-ssk,ref,10.6,10.7,28.1,,,,,, +snova-37-8-16-4-ssk,ref,8.8,2.0,3.4,,,,,, +sphincs-a-sha2-128f,ref,43.3,86.6,48.2,,,,,, +sphincs-a-sha2-128s,ref,72.9,88.3,11.7,,,,,, +sphincs-a-sha2-192f,ref,57.5,88.3,46.0,,,,,, +sphincs-a-shake-128f,ref,72.3,96.2,76.0,,,,,, +sphincs-a-shake-128s,ref,90.9,96.9,31.8,,,,,, +sphincs-a-shake-192f,ref,82.6,96.5,70.7,,,,,, +sphincs-sha2-128f-simple,clean,90.8,90.7,90.6,,,,,, +sphincs-sha2-128s-simple,clean,90.8,90.7,90.4,,,,,, +sphincs-sha2-192f-simple,clean,90.2,90.8,90.7,,,,,, +sphincs-sha2-192s-simple,clean,90.3,91.1,91.5,,,,,, +sphincs-sha2-256f-simple,clean,90.2,90.7,90.9,,,,,, +sphincs-sha2-256s-simple,clean,90.2,91.3,91.3,,,,,, +sphincs-shake-128f-simple,clean,97.6,97.6,97.5,,,,,, +sphincs-shake-128s-simple,clean,97.6,97.6,97.5,,,,,, +sphincs-shake-192f-simple,clean,97.5,97.4,97.4,,,,,, +sphincs-shake-192s-simple,clean,97.5,97.4,97.4,,,,,, +sphincs-shake-256f-simple,clean,97.5,97.4,97.4,,,,,, +sphincs-shake-256s-simple,clean,97.5,97.3,97.4,,,,,, Size Evaluation,,,,,,,,,, Key Encapsulation Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, -bikel1,m4f,177664,24,49,177737,,,,, -bikel1,opt,34947,24,1,34972,,,,, -hqc-rmrs-128,clean,17116,0,0,17116,,,,, -kyber1024,clean,6068,0,0,6068,,,,, -kyber1024,m4fspeed,16496,0,0,16496,,,,, -kyber1024,m4fstack,13752,0,0,13752,,,,, -kyber1024-90s,clean,6424,0,0,6424,,,,, -kyber1024-90s,m4fspeed,16948,0,0,16948,,,,, -kyber1024-90s,m4fstack,13996,0,0,13996,,,,, -kyber512,clean,4872,0,0,4872,,,,, -kyber512,m4fspeed,15332,0,0,15332,,,,, -kyber512,m4fstack,12820,0,0,12820,,,,, -kyber512-90s,clean,5088,0,0,5088,,,,, -kyber512-90s,m4fspeed,15784,0,0,15784,,,,, -kyber512-90s,m4fstack,13052,0,0,13052,,,,, -kyber768,clean,4888,0,0,4888,,,,, -kyber768,m4fspeed,15540,0,0,15540,,,,, -kyber768,m4fstack,12836,0,0,12836,,,,, -kyber768-90s,clean,5120,0,0,5120,,,,, -kyber768-90s,m4fspeed,16000,0,0,16000,,,,, -kyber768-90s,m4fstack,13068,0,0,13068,,,,, +bikel1,m4f,181088,24,49,181161,,,,, +bikel1,opt,34451,24,1,34476,,,,, +bikel3,m4f,198034,24,49,198107,,,,, +bikel3,opt,43091,24,1,43116,,,,, +hqc-128,clean,18628,0,0,18628,,,,, +hqc-192,clean,21104,0,0,21104,,,,, +hqc-256,clean,26260,0,0,26260,,,,, +kyber1024,clean,6296,0,0,6296,,,,, +kyber1024,m4fspeed,16928,0,0,16928,,,,, +kyber1024,m4fstack,14136,0,0,14136,,,,, +kyber512,clean,5164,0,0,5164,,,,, +kyber512,m4fspeed,15840,0,0,15840,,,,, +kyber512,m4fstack,13324,0,0,13324,,,,, +kyber768,clean,5168,0,0,5168,,,,, +kyber768,m4fspeed,16008,0,0,16008,,,,, +kyber768,m4fstack,13332,0,0,13332,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, -fdilithium2,clean,7888,0,0,7888,,,,, -dilithium2,m4f,18480,0,0,18480,,,,, -dilithium2aes,clean,14954,0,0,14954,,,,, -dilithium3,clean,7384,0,0,7384,,,,, -dilithium3,m4f,19924,0,0,19924,,,,, -dilithium3aes,clean,14442,0,0,14442,,,,, -dilithium5,m4f,18248,0,0,18248,,,,, -falcon-1024,clean,82281,0,0,82281,,,,, -falcon-1024,m4-ct,83069,0,79872,162941,,,,, -falcon-1024,opt-ct,83069,0,79872,162941,,,,, -falcon-1024,opt-leaktime,76261,0,79872,156133,,,,, -falcon-512,clean,82249,0,0,82249,,,,, -falcon-512,m4-ct,83069,0,39936,123005,,,,, -falcon-512,opt-ct,83069,0,39936,123005,,,,, -falcon-512,opt-leaktime,76261,0,39936,116197,,,,, -falcon-512-tree,m4-ct,82821,0,27648,110469,,,,, -falcon-512-tree,opt-ct,82821,0,27648,110469,,,,, -falcon-512-tree,opt-leaktime,76013,0,27648,103661,,,,, -sphincs-haraka-128f-robust,clean,16428,0,0,16428,,,,, -sphincs-haraka-128f-simple,clean,16276,0,0,16276,,,,, -sphincs-haraka-128s-robust,clean,16700,0,0,16700,,,,, -sphincs-haraka-128s-simple,clean,16552,0,0,16552,,,,, -sphincs-haraka-192f-robust,clean,16484,0,0,16484,,,,, -sphincs-haraka-192f-simple,clean,16300,0,0,16300,,,,, -sphincs-haraka-192s-robust,clean,17020,0,0,17020,,,,, -sphincs-haraka-192s-simple,clean,16836,0,0,16836,,,,, -sphincs-haraka-256f-robust,clean,16868,0,0,16868,,,,, -sphincs-haraka-256f-simple,clean,16624,0,0,16624,,,,, -sphincs-haraka-256s-robust,clean,17196,0,0,17196,,,,, -sphincs-haraka-256s-simple,clean,16952,0,0,16952,,,,, -sphincs-sha256-128f-robust,clean,4740,0,0,4740,,,,, -sphincs-sha256-128f-simple,clean,4504,0,0,4504,,,,, -sphincs-sha256-128s-robust,clean,5012,0,0,5012,,,,, -sphincs-sha256-128s-simple,clean,4776,0,0,4776,,,,, -sphincs-sha256-192f-robust,clean,5020,0,0,5020,,,,, -sphincs-sha256-192f-simple,clean,4668,0,0,4668,,,,, -sphincs-sha256-192s-robust,clean,5564,0,0,5564,,,,, -sphincs-sha256-192s-simple,clean,5208,0,0,5208,,,,, -sphincs-sha256-256f-robust,clean,5488,0,0,5488,,,,, -sphincs-sha256-256f-simple,clean,5048,0,0,5048,,,,, -sphincs-sha256-256s-robust,clean,5812,0,0,5812,,,,, -sphincs-sha256-256s-simple,clean,5368,0,0,5368,,,,, -sphincs-shake256-128f-robust,clean,4024,0,0,4024,,,,, -sphincs-shake256-128f-simple,clean,3884,0,0,3884,,,,, -sphincs-shake256-128s-robust,clean,4296,0,0,4296,,,,, -sphincs-shake256-128s-simple,clean,4152,0,0,4152,,,,, -sphincs-shake256-192f-robust,clean,4124,0,0,4124,,,,, -sphincs-shake256-192f-simple,clean,3952,0,0,3952,,,,, -sphincs-shake256-192s-robust,clean,4660,0,0,4660,,,,, -sphincs-shake256-192s-simple,clean,4488,0,0,4488,,,,, -sphincs-shake256-256f-robust,clean,4520,0,0,4520,,,,, -sphincs-shake256-256f-simple,clean,4308,0,0,4308,,,,, -sphincs-shake256-256s-robust,clean,4844,0,0,4844,,,,, -sphincs-shake256-256s-simple,clean,4636,0,0,4636,,,,, +aimer-l1-param1,ref,19302,468,0,19770,,,,, +aimer-l1-param2,ref,19894,468,0,20362,,,,, +aimer-l3-param1,ref,23398,468,0,23866,,,,, +ascon-sign-128f-robust,ref,17664,0,0,17664,,,,, +ascon-sign-128f-simple,ref,17596,0,0,17596,,,,, +ascon-sign-128s-robust,ref,17972,0,0,17972,,,,, +ascon-sign-128s-simple,ref,17904,0,0,17904,,,,, +ascon-sign-192f-robust,ref,17960,0,0,17960,,,,, +ascon-sign-192f-simple,ref,17912,0,0,17912,,,,, +ascon-sign-192s-robust,ref,18472,0,0,18472,,,,, +ascon-sign-192s-simple,ref,18424,0,0,18424,,,,, +biscuit128f,ref,7580,0,0,7580,,,,, +biscuit192f,ref,7780,0,0,7780,,,,, +biscuit256f,ref,8216,0,0,8216,,,,, +cross-sha2-r-sdp-1-fast,ref,14244,0,104,14348,,,,, +cross-sha2-r-sdp-3-fast,ref,14744,0,128,14872,,,,, +cross-sha2-r-sdpg-1-fast,ref,18409,0,104,18513,,,,, +cross-sha2-r-sdpg-1-small,ref,18674,0,104,18778,,,,, +cross-sha2-r-sdpg-3-fast,ref,19609,0,128,19737,,,,, +cross-sha2-r-sdpg-5-fast,ref,18669,0,152,18821,,,,, +cross-sha3-r-sdp-1-fast,ref,14472,0,208,14680,,,,, +cross-sha3-r-sdp-3-fast,ref,14884,0,208,15092,,,,, +cross-sha3-r-sdpg-1-fast,ref,18605,0,208,18813,,,,, +cross-sha3-r-sdpg-1-small,ref,18846,0,208,19054,,,,, +cross-sha3-r-sdpg-3-fast,ref,19689,0,208,19897,,,,, +cross-sha3-r-sdpg-5-fast,ref,18593,0,208,18801,,,,, +dilithium2,clean,8064,0,0,8064,,,,, +dilithium2,m4f,18596,0,0,18596,,,,, +dilithium3,clean,7580,0,0,7580,,,,, +dilithium3,m4f,20108,0,0,20108,,,,, +dilithium5,clean,7808,0,0,7808,,,,, +dilithium5,m4f,18468,0,0,18468,,,,, +falcon-1024,clean,82647,0,0,82647,,,,, +falcon-1024,m4-ct,81825,0,79872,161697,,,,, +falcon-1024,opt-ct,81825,0,79872,161697,,,,, +falcon-1024,opt-leaktime,75429,0,79872,155301,,,,, +falcon-1024-tree,opt-ct,81569,0,55296,136865,,,,, +falcon-1024-tree,opt-leaktime,75173,0,55296,130469,,,,, +falcon-512,clean,82611,0,0,82611,,,,, +falcon-512,m4-ct,81825,0,39936,121761,,,,, +falcon-512,opt-ct,81825,0,39936,121761,,,,, +falcon-512,opt-leaktime,75429,0,39936,115365,,,,, +falcon-512-tree,m4-ct,81569,0,27648,109217,,,,, +falcon-512-tree,opt-ct,81569,0,27648,109217,,,,, +falcon-512-tree,opt-leaktime,75173,0,27648,102821,,,,, +haetae2,m4f,35708,0,0,35708,,,,, +haetae2,ref,25568,0,0,25568,,,,, +haetae3,m4f,35936,0,0,35936,,,,, +haetae3,ref,25980,0,0,25980,,,,, +haetae5,m4f,35692,0,0,35692,,,,, +haetae5,ref,25688,0,0,25688,,,,, +hawk1024,ref,102031,0,0,102031,,,,, +hawk256,ref,102015,0,0,102015,,,,, +hawk512,ref,102027,0,0,102027,,,,, +mayo1,m4f,19300,8,0,19308,,,,, +mayo1,ref,26436,8,0,26444,,,,, +mayo2,m4f,17292,8,0,17300,,,,, +mayo2,ref,24404,8,0,24412,,,,, +mayo3,m4f,23612,8,0,23620,,,,, +meds13220,ref,16844,0,0,16844,,,,, +meds55604,ref,9012,0,0,9012,,,,, +mirith_IIIa_fast,ref,7720,256,0,7976,,,,, +mirith_IIIb_fast,ref,7760,256,0,8016,,,,, +mirith_Ia_fast,ref,7610,256,0,7866,,,,, +mirith_Ib_fast,ref,7602,256,0,7858,,,,, +mirith_Va_fast,ref,7890,256,0,8146,,,,, +mirith_Vb_fast,ref,7914,256,0,8170,,,,, +mirith_hypercube_IIIa_fast,ref,8966,256,0,9222,,,,, +mirith_hypercube_IIIa_short,ref,9139,256,0,9395,,,,, +mirith_hypercube_IIIb_fast,ref,9002,256,0,9258,,,,, +mirith_hypercube_IIIb_short,ref,9159,256,0,9415,,,,, +mirith_hypercube_Ia_fast,opt,10932,0,0,10932,,,,, +mirith_hypercube_Ia_fast,ref,8844,256,0,9100,,,,, +mirith_hypercube_Ia_short,ref,8781,256,0,9037,,,,, +mirith_hypercube_Ib_fast,opt,10908,0,0,10908,,,,, +mirith_hypercube_Ib_fast,ref,8820,256,0,9076,,,,, +mirith_hypercube_Ib_short,ref,8825,256,0,9081,,,,, +mirith_hypercube_Va_fast,ref,9140,256,0,9396,,,,, +mirith_hypercube_Vb_fast,ref,9160,256,0,9416,,,,, +mqom_cat1_gf251_fast,ref,16865,0,0,16865,,,,, +mqom_cat1_gf31_fast,ref,23718,0,0,23718,,,,, +ov-Ip,m4f,118939,0,0,118939,,,,, +ov-Ip,ref,29215,0,0,29215,,,,, +ov-Ip-pkc,m4fspeed,119131,0,0,119131,,,,, +ov-Ip-pkc,m4fstack,119059,0,0,119059,,,,, +ov-Ip-pkc,ref,29423,0,0,29423,,,,, +ov-Ip-pkc-skc,m4fspeed,119175,0,0,119175,,,,, +ov-Ip-pkc-skc,m4fstack,119103,0,0,119103,,,,, +ov-Ip-pkc-skc,ref,29467,0,0,29467,,,,, +perk-128-fast-3,m4,13421,4,0,13425,,,,, +perk-128-fast-3,ref,11053,4,0,11057,,,,, +perk-128-fast-5,m4,13493,4,0,13497,,,,, +perk-128-fast-5,ref,11129,4,0,11133,,,,, +perk-128-short-3,m4,26313,4,0,26317,,,,, +perk-128-short-5,m4,26461,4,0,26465,,,,, +perk-192-fast-3,m4,12253,4,0,12257,,,,, +perk-192-fast-5,m4,12277,4,0,12281,,,,, +perk-192-short-3,m4,24189,4,0,24193,,,,, +perk-192-short-5,m4,24913,4,0,24917,,,,, +perk-256-fast-3,m4,12337,4,0,12341,,,,, +perk-256-fast-5,m4,12337,4,0,12341,,,,, +perk-256-short-3,m4,31905,4,0,31909,,,,, +perk-256-short-5,m4,32989,4,0,32993,,,,, +snova-24-5-16-4-esk,ref,52132,0,336,52468,,,,, +snova-24-5-16-4-ssk,ref,52132,0,336,52468,,,,, +snova-25-8-16-3-esk,ref,28240,0,299,28539,,,,, +snova-25-8-16-3-ssk,ref,28240,0,299,28539,,,,, +snova-28-17-16-2-esk,ref,16436,0,280,16716,,,,, +snova-28-17-16-2-ssk,ref,16436,0,280,16716,,,,, +snova-37-8-16-4-ssk,ref,52440,0,336,52776,,,,, +sphincs-a-sha2-128f,ref,6343,0,0,6343,,,,, +sphincs-a-sha2-128s,ref,6899,0,0,6899,,,,, +sphincs-a-sha2-192f,ref,6867,0,0,6867,,,,, +sphincs-a-shake-128f,ref,5552,0,0,5552,,,,, +sphincs-a-shake-128s,ref,6108,0,0,6108,,,,, +sphincs-a-shake-192f,ref,5916,0,0,5916,,,,, +sphincs-sha2-128f-simple,clean,4956,0,0,4956,,,,, +sphincs-sha2-128s-simple,clean,5264,0,0,5264,,,,, +sphincs-sha2-192f-simple,clean,5444,0,0,5444,,,,, +sphincs-sha2-192s-simple,clean,5968,0,0,5968,,,,, +sphincs-sha2-256f-simple,clean,5728,0,0,5728,,,,, +sphincs-sha2-256s-simple,clean,6084,0,0,6084,,,,, +sphincs-shake-128f-simple,clean,4184,0,0,4184,,,,, +sphincs-shake-128s-simple,clean,4492,0,0,4492,,,,, +sphincs-shake-192f-simple,clean,4472,0,0,4472,,,,, +sphincs-shake-192s-simple,clean,4984,0,0,4984,,,,, +sphincs-shake-256f-simple,clean,4720,0,0,4720,,,,, +sphincs-shake-256s-simple,clean,5076,0,0,5076,,,,, diff --git a/benchmarks.md b/benchmarks.md index b5837140..e2b4a4e3 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -2,327 +2,599 @@ ## Key Encapsulation Schemes | scheme | implementation | key generation [cycles] | encapsulation [cycles] | decapsulation [cycles] | | ------ | -------------- | ----------------------- | ---------------------- | ---------------------- | -| bikel1 (100 executions) | m4f | AVG: 24,974,536
MIN: 24,950,520
MAX: 24,991,477 | AVG: 3,394,030
MIN: 3,378,190
MAX: 3,414,910 | AVG: 51,214,664
MIN: 51,198,795
MAX: 51,235,513 | -| bikel1 (100 executions) | opt | AVG: 68,198,074
MIN: 68,181,729
MAX: 68,218,850 | AVG: 5,085,537
MIN: 5,068,825
MAX: 5,101,896 | AVG: 121,429,912
MIN: 121,416,187
MAX: 121,446,269 | -| hqc-rmrs-128 (100 executions) | clean | AVG: 2,883,811
MIN: 2,850,356
MAX: 3,090,278 | AVG: 5,236,720
MIN: 5,150,902
MAX: 5,554,288 | AVG: 7,594,631
MIN: 7,482,072
MAX: 7,890,446 | -| kyber1024 (100 executions) | clean | AVG: 1,649,604
MIN: 1,646,417
MAX: 1,686,328 | AVG: 2,016,366
MIN: 2,013,177
MAX: 2,053,070 | AVG: 2,159,906
MIN: 2,156,716
MAX: 2,196,609 | -| kyber1024 (100 executions) | m4fspeed | AVG: 1,122,936
MIN: 1,120,610
MAX: 1,147,966 | AVG: 1,315,737
MIN: 1,313,449
MAX: 1,340,766 | AVG: 1,209,901
MIN: 1,207,648
MAX: 1,234,899 | -| kyber1024 (100 executions) | m4fstack | AVG: 1,126,561
MIN: 1,124,115
MAX: 1,138,795 | AVG: 1,323,943
MIN: 1,321,497
MAX: 1,336,212 | AVG: 1,219,060
MIN: 1,216,614
MAX: 1,231,295 | -| kyber1024-90s (100 executions) | clean | AVG: 3,008,837
MIN: 3,007,295
MAX: 3,024,024 | AVG: 3,275,730
MIN: 3,274,235
MAX: 3,290,907 | AVG: 3,516,691
MIN: 3,515,163
MAX: 3,531,901 | -| kyber1024-90s (100 executions) | m4fspeed | AVG: 973,196
MIN: 961,657
MAX: 978,853 | AVG: 1,068,184
MIN: 1,056,648
MAX: 1,073,886 | AVG: 1,059,775
MIN: 1,048,239
MAX: 1,065,477 | -| kyber1024-90s (100 executions) | m4fstack | AVG: 979,692
MIN: 972,492
MAX: 985,031 | AVG: 1,079,272
MIN: 1,072,072
MAX: 1,084,611 | AVG: 1,071,817
MIN: 1,064,616
MAX: 1,077,155 | -| kyber512 (100 executions) | clean | AVG: 636,181
MIN: 635,670
MAX: 648,917 | AVG: 843,945
MIN: 843,433
MAX: 856,680 | AVG: 940,320
MIN: 939,808
MAX: 953,055 | -| kyber512 (100 executions) | m4fspeed | AVG: 434,438
MIN: 433,217
MAX: 446,786 | AVG: 530,469
MIN: 529,247
MAX: 542,816 | AVG: 476,712
MIN: 475,491
MAX: 489,060 | -| kyber512 (100 executions) | m4fstack | AVG: 433,718
MIN: 433,191
MAX: 446,122 | AVG: 531,676
MIN: 531,150
MAX: 544,080 | AVG: 478,166
MIN: 477,640
MAX: 490,570 | -| kyber512-90s (100 executions) | clean | AVG: 948,446
MIN: 947,802
MAX: 964,084 | AVG: 1,112,852
MIN: 1,112,208
MAX: 1,128,491 | AVG: 1,261,630
MIN: 1,260,986
MAX: 1,277,269 | -| kyber512-90s (100 executions) | m4fspeed | AVG: 369,011
MIN: 364,769
MAX: 373,816 | AVG: 421,685
MIN: 417,443
MAX: 426,490 | AVG: 420,333
MIN: 416,092
MAX: 425,139 | -| kyber512-90s (100 executions) | m4fstack | AVG: 369,736
MIN: 361,461
MAX: 370,708 | AVG: 424,339
MIN: 416,065
MAX: 425,312 | AVG: 423,234
MIN: 414,960
MAX: 424,207 | -| kyber768 (100 executions) | clean | AVG: 1,059,876
MIN: 1,057,827
MAX: 1,071,809 | AVG: 1,352,934
MIN: 1,350,884
MAX: 1,364,866 | AVG: 1,471,055
MIN: 1,469,005
MAX: 1,482,987 | -| kyber768 (100 executions) | m4fspeed | AVG: 706,531
MIN: 703,969
MAX: 718,271 | AVG: 863,343
MIN: 860,765
MAX: 875,091 | AVG: 783,369
MIN: 780,788
MAX: 795,114 | -| kyber768 (100 executions) | m4fstack | AVG: 707,275
MIN: 705,435
MAX: 719,983 | AVG: 867,363
MIN: 865,520
MAX: 880,070 | AVG: 788,053
MIN: 786,210
MAX: 800,760 | -| kyber768-90s (100 executions) | clean | AVG: 1,816,649
MIN: 1,815,810
MAX: 1,831,510 | AVG: 2,032,562
MIN: 2,031,722
MAX: 2,047,390 | AVG: 2,225,597
MIN: 2,224,757
MAX: 2,240,425 | -| kyber768-90s (100 executions) | m4fspeed | AVG: 614,455
MIN: 610,716
MAX: 619,096 | AVG: 694,064
MIN: 690,330
MAX: 698,723 | AVG: 688,999
MIN: 685,265
MAX: 693,658 | -| kyber768-90s (100 executions) | m4fstack | AVG: 617,709
MIN: 613,688
MAX: 622,666 | AVG: 700,599
MIN: 696,577
MAX: 705,555 | AVG: 696,202
MIN: 692,181
MAX: 701,159 | +| bikel1 (10 executions) | m4f | AVG: 27,382,389
MIN: 27,382,366
MAX: 27,382,406 | AVG: 3,363,252
MIN: 3,363,238
MAX: 3,363,291 | AVG: 56,744,036
MIN: 56,744,013
MAX: 56,744,062 | +| bikel1 (10 executions) | opt | AVG: 76,272,765
MIN: 76,272,741
MAX: 76,272,809 | AVG: 5,295,900
MIN: 5,295,877
MAX: 5,295,931 | AVG: 138,514,606
MIN: 138,514,541
MAX: 138,514,711 | +| bikel3 (10 executions) | m4f | AVG: 66,285,221
MIN: 66,285,184
MAX: 66,285,235 | AVG: 8,441,498
MIN: 8,441,478
MAX: 8,441,521 | AVG: 150,282,952
MIN: 150,282,849
MAX: 150,282,974 | +| bikel3 (10 executions) | opt | AVG: 248,083,316
MIN: 248,083,286
MAX: 248,083,345 | AVG: 16,405,238
MIN: 16,405,236
MAX: 16,405,241 | AVG: 423,262,047
MIN: 423,261,952
MAX: 423,262,086 | +| hqc-128 (10 executions) | clean | AVG: 52,705,201
MIN: 52,705,180
MAX: 52,705,224 | AVG: 105,650,897
MIN: 105,650,877
MAX: 105,650,927 | AVG: 159,569,179
MIN: 159,569,176
MAX: 159,569,183 | +| hqc-192 (10 executions) | clean | AVG: 161,458,617
MIN: 161,458,590
MAX: 161,458,638 | AVG: 323,146,261
MIN: 323,146,250
MAX: 323,146,292 | AVG: 486,156,251
MIN: 486,156,214
MAX: 486,156,266 | +| hqc-256 (10 executions) | clean | AVG: 295,934,078
MIN: 295,934,057
MAX: 295,934,104 | AVG: 591,853,870
MIN: 591,853,850
MAX: 591,853,898 | AVG: 891,163,005
MIN: 891,162,988
MAX: 891,163,038 | +| kyber1024 (10 executions) | m4fspeed | AVG: 1,004,995
MIN: 1,004,386
MAX: 1,005,713 | AVG: 1,023,370
MIN: 1,022,780
MAX: 1,024,086 | AVG: 1,094,273
MIN: 1,093,643
MAX: 1,094,989 | +| kyber1024 (10 executions) | m4fstack | AVG: 1,011,563
MIN: 1,007,750
MAX: 1,019,668 | AVG: 1,035,234
MIN: 1,031,419
MAX: 1,043,376 | AVG: 1,106,876
MIN: 1,103,061
MAX: 1,114,980 | +| kyber512 (10 executions) | m4fspeed | AVG: 387,426
MIN: 387,191
MAX: 387,884 | AVG: 386,486
MIN: 386,251
MAX: 386,942 | AVG: 427,576
MIN: 427,342
MAX: 428,033 | +| kyber512 (10 executions) | m4fstack | AVG: 387,995
MIN: 386,694
MAX: 398,090 | AVG: 389,242
MIN: 387,941
MAX: 399,338 | AVG: 430,376
MIN: 429,075
MAX: 440,473 | +| kyber768 (10 executions) | m4fspeed | AVG: 632,049
MIN: 631,494
MAX: 632,680 | AVG: 651,880
MIN: 651,323
MAX: 652,515 | AVG: 706,301
MIN: 705,744
MAX: 706,936 | +| kyber768 (10 executions) | m4fstack | AVG: 635,213
MIN: 632,659
MAX: 643,980 | AVG: 658,865
MIN: 656,311
MAX: 667,633 | AVG: 713,751
MIN: 711,197
MAX: 722,519 | ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | -| dilithium2 (10000 executions) | clean | AVG: 1,944,539
MIN: 1,890,031
MAX: 1,991,828 | AVG: 7,144,383
MIN: 3,140,649
MAX: 63,849,339 | AVG: 2,064,129
MIN: 2,063,522
MAX: 2,064,634 | -| dilithium2 (10000 executions) | m4f | AVG: 1,597,999
MIN: 1,543,482
MAX: 1,644,972 | AVG: 4,111,596
MIN: 1,975,193
MAX: 28,355,968 | AVG: 1,571,804
MIN: 1,571,197
MAX: 1,572,305 | -| dilithium2aes (10000 executions) | clean | AVG: 4,995,899
MIN: 4,936,813
MAX: 5,118,217 | AVG: 11,648,989
MIN: 6,130,462
MAX: 61,958,375 | AVG: 4,669,616
MIN: 4,610,387
MAX: 4,791,733 | -| dilithium3 (10000 executions) | clean | AVG: 3,365,142
MIN: 3,363,198
MAX: 3,378,304 | AVG: 11,634,591
MIN: 4,892,049
MAX: 79,793,644 | AVG: 3,430,286
MIN: 3,429,812
MAX: 3,430,778 | -| dilithium3 (10000 executions) | m4f | AVG: 2,830,024
MIN: 2,828,027
MAX: 2,832,150 | AVG: 6,588,465
MIN: 3,224,221
MAX: 46,880,624 | AVG: 2,691,283
MIN: 2,690,800
MAX: 2,691,739 | -| dilithium3aes (10000 executions) | clean | AVG: 8,980,662
MIN: 8,870,698
MAX: 9,135,481 | AVG: 19,843,507
MIN: 10,319,280
MAX: 112,310,317 | AVG: 8,314,038
MIN: 8,205,198
MAX: 8,468,692 | -| dilithium5 (10000 executions) | m4f | AVG: 4,826,422
MIN: 4,737,706
MAX: 4,914,744 | AVG: 8,779,067
MIN: 5,416,181
MAX: 52,012,847 | AVG: 4,705,693
MIN: 4,705,090
MAX: 4,706,259 | -| falcon-1024 (100 executions) | clean | AVG: 589,059,133
MIN: 334,912,351
MAX: 1,243,184,474 | AVG: 133,598,726
MIN: 133,189,548
MAX: 133,921,649 | AVG: 1,547,336
MIN: 1,546,772
MAX: 1,548,051 | -| falcon-1024 (100 executions) | m4-ct | AVG: 480,071,949
MIN: 271,647,441
MAX: 1,227,690,897 | AVG: 85,125,001
MIN: 84,882,111
MAX: 85,556,430 | AVG: 994,972
MIN: 983,996
MAX: 1,002,867 | -| falcon-1024 (100 executions) | opt-ct | AVG: 437,448,136
MIN: 271,659,962
MAX: 1,092,676,507 | AVG: 85,113,093
MIN: 84,848,956
MAX: 85,473,992 | AVG: 994,270
MIN: 984,187
MAX: 1,002,619 | -| falcon-1024 (100 executions) | opt-leaktime | AVG: 413,908,640
MIN: 243,261,195
MAX: 1,126,577,305 | AVG: 76,314,462
MIN: 75,745,413
MAX: 76,892,801 | AVG: 994,634
MIN: 982,708
MAX: 1,002,471 | -| falcon-512 (100 executions) | clean | AVG: 217,740,948
MIN: 129,494,100
MAX: 511,780,471 | AVG: 61,102,456
MIN: 60,847,251
MAX: 61,330,321 | AVG: 774,876
MIN: 774,536
MAX: 775,376 | -| falcon-512 (100 executions) | m4-ct | AVG: 155,757,768
MIN: 101,804,738
MAX: 436,771,421 | AVG: 38,979,435
MIN: 38,774,219
MAX: 39,146,132 | AVG: 481,452
MIN: 472,089
MAX: 488,157 | -| falcon-512 (100 executions) | opt-ct | AVG: 169,979,748
MIN: 101,804,734
MAX: 511,094,390 | AVG: 38,995,196
MIN: 38,771,533
MAX: 39,280,349 | AVG: 481,457
MIN: 472,109
MAX: 488,208 | -| falcon-512 (100 executions) | opt-leaktime | AVG: 154,344,796
MIN: 89,719,505
MAX: 442,643,356 | AVG: 35,503,133
MIN: 35,166,340
MAX: 35,923,860 | AVG: 480,806
MIN: 472,450
MAX: 489,614 | -| falcon-512-tree (100 executions) | m4-ct | AVG: 179,772,454
MIN: 116,934,668
MAX: 497,881,688 | AVG: 17,649,735
MIN: 17,489,319
MAX: 17,847,797 | AVG: 480,619
MIN: 471,367
MAX: 488,548 | -| falcon-512-tree (100 executions) | opt-ct | AVG: 185,495,778
MIN: 116,934,665
MAX: 591,766,146 | AVG: 17,664,284
MIN: 17,480,589
MAX: 17,824,518 | AVG: 482,085
MIN: 472,168
MAX: 488,509 | -| falcon-512-tree (100 executions) | opt-leaktime | AVG: 157,683,545
MIN: 101,416,387
MAX: 370,593,247 | AVG: 19,162,650
MIN: 18,816,478
MAX: 19,426,978 | AVG: 481,577
MIN: 472,170
MAX: 488,230 | -| sphincs-haraka-128f-robust (3 executions) | clean | AVG: 106,427,973
MIN: 106,427,961
MAX: 106,427,997 | AVG: 2,699,060,638
MIN: 2,698,241,211
MAX: 2,699,997,157 | AVG: 174,647,895
MIN: 173,477,158
MAX: 176,638,141 | -| sphincs-haraka-128f-simple (3 executions) | clean | AVG: 74,934,480
MIN: 74,934,458
MAX: 74,934,492 | AVG: 1,887,299,882
MIN: 1,887,134,522
MAX: 1,887,382,565 | AVG: 118,143,703
MIN: 113,925,327
MAX: 123,851,044 | -| sphincs-haraka-128s-robust (3 executions) | clean | AVG: 6,775,943,571
MIN: 6,775,943,546
MAX: 6,775,943,591 | AVG: 53,822,326,627
MIN: 53,821,272,834
MAX: 53,824,434,213 | AVG: 68,158,360
MIN: 65,114,417
MAX: 72,841,330 | -| sphincs-haraka-128s-simple (3 executions) | clean | AVG: 4,758,339,537
MIN: 4,758,339,511
MAX: 4,758,339,556 | AVG: 37,472,069,032
MIN: 37,470,580,002
MAX: 37,474,550,750 | AVG: 44,603,270
MIN: 44,272,388
MAX: 44,768,737 | -| sphincs-haraka-192f-robust (3 executions) | clean | AVG: 157,886,973
MIN: 157,886,961
MAX: 157,886,995 | AVG: 4,729,109,673
MIN: 4,724,305,900
MAX: 4,731,687,311 | AVG: 261,039,514
MIN: 258,813,178
MAX: 263,734,554 | -| sphincs-haraka-192f-simple (3 executions) | clean | AVG: 110,403,519
MIN: 110,403,498
MAX: 110,403,532 | AVG: 3,167,446,164
MIN: 3,164,466,253
MAX: 3,169,681,094 | AVG: 171,820,185
MIN: 169,915,924
MAX: 174,138,430 | -| sphincs-haraka-192s-robust (3 executions) | clean | AVG: 10,070,301,104
MIN: 10,070,301,092
MAX: 10,070,301,120 | AVG: 105,836,052,151
MIN: 105,833,943,123
MAX: 105,838,864,162 | AVG: 102,385,564
MIN: 100,510,789
MAX: 104,729,057 | -| sphincs-haraka-192s-simple (3 executions) | clean | AVG: 7,028,359,469
MIN: 7,028,359,462
MAX: 7,028,359,475 | AVG: 69,349,184,156
MIN: 69,348,190,870
MAX: 69,350,922,453 | AVG: 64,929,339
MIN: 63,356,226
MAX: 65,840,010 | -| sphincs-haraka-256f-robust (3 executions) | clean | AVG: 422,110,917
MIN: 422,110,915
MAX: 422,110,921 | AVG: 9,925,037,310
MIN: 9,919,761,990
MAX: 9,929,258,109 | AVG: 282,995,607
MIN: 280,533,063
MAX: 286,865,365 | -| sphincs-haraka-256f-simple (3 executions) | clean | AVG: 293,499,115
MIN: 293,499,091
MAX: 293,499,129 | AVG: 6,701,863,848
MIN: 6,699,462,526
MAX: 6,705,176,025 | AVG: 183,796,029
MIN: 182,221,816
MAX: 186,447,361 | -| sphincs-haraka-256s-robust (3 executions) | clean | AVG: 6,739,159,318
MIN: 6,739,159,309
MAX: 6,739,159,328 | AVG: 105,302,624,797
MIN: 105,300,748,903
MAX: 105,304,266,285 | AVG: 156,467,817
MIN: 154,826,875
MAX: 159,398,072 | -| sphincs-haraka-256s-simple (3 executions) | clean | AVG: 4,683,144,675
MIN: 4,683,144,642
MAX: 4,683,144,705 | AVG: 69,202,732,323
MIN: 69,201,324,370
MAX: 69,205,052,507 | AVG: 101,719,411
MIN: 100,063,540
MAX: 104,037,675 | -| sphincs-sha256-128f-robust (3 executions) | clean | AVG: 29,123,270
MIN: 29,123,249
MAX: 29,123,282 | AVG: 716,257,523
MIN: 715,884,705
MAX: 716,674,437 | AVG: 42,248,922
MIN: 41,497,196
MAX: 42,869,922 | -| sphincs-sha256-128f-simple (3 executions) | clean | AVG: 15,388,375
MIN: 15,388,352
MAX: 15,388,387 | AVG: 382,533,954
MIN: 382,308,022
MAX: 382,976,925 | AVG: 21,150,671
MIN: 20,677,650
MAX: 21,741,991 | -| sphincs-sha256-128s-robust (3 executions) | clean | AVG: 1,864,047,221
MIN: 1,864,042,048
MAX: 1,864,050,532 | AVG: 14,012,634,889
MIN: 14,012,400,685
MAX: 14,012,822,953 | AVG: 14,847,302
MIN: 14,422,375
MAX: 15,206,848 | -| sphincs-sha256-128s-simple (3 executions) | clean | AVG: 985,367,046
MIN: 985,355,790
MAX: 985,385,031 | AVG: 7,495,603,716
MIN: 7,495,252,193
MAX: 7,496,247,958 | AVG: 7,165,875
MIN: 6,861,584
MAX: 7,419,441 | -| sphincs-sha256-192f-robust (3 executions) | clean | AVG: 43,116,184
MIN: 43,116,173
MAX: 43,116,205 | AVG: 1,195,381,634
MIN: 1,193,980,671
MAX: 1,196,819,904 | AVG: 64,857,703
MIN: 64,364,605
MAX: 65,153,579 | -| sphincs-sha256-192f-simple (3 executions) | clean | AVG: 22,645,923
MIN: 22,645,911
MAX: 22,645,947 | AVG: 639,321,913
MIN: 639,157,877
MAX: 639,638,579 | AVG: 32,940,330
MIN: 31,955,780
MAX: 33,534,443 | -| sphincs-sha256-192s-robust (3 executions) | clean | AVG: 2,758,781,668
MIN: 2,758,721,187
MAX: 2,758,814,880 | AVG: 25,556,205,325
MIN: 25,555,467,827
MAX: 25,556,897,376 | AVG: 23,195,383
MIN: 22,702,335
MAX: 23,589,803 | -| sphincs-sha256-192s-simple (3 executions) | clean | AVG: 1,450,073,477
MIN: 1,449,766,386
MAX: 1,450,529,270 | AVG: 13,764,196,955
MIN: 13,762,891,584
MAX: 13,765,362,825 | AVG: 11,763,703
MIN: 11,695,761
MAX: 11,899,525 | -| sphincs-sha256-256f-robust (3 executions) | clean | AVG: 158,034,870
MIN: 158,034,868
MAX: 158,034,873 | AVG: 3,305,447,599
MIN: 3,303,450,474
MAX: 3,306,582,779 | AVG: 94,366,505
MIN: 92,087,788
MAX: 96,189,482 | -| sphincs-sha256-256f-simple (3 executions) | clean | AVG: 59,808,433
MIN: 59,807,808
MAX: 59,808,748 | AVG: 1,281,329,322
MIN: 1,280,242,352
MAX: 1,282,332,972 | AVG: 32,947,097
MIN: 32,522,594
MAX: 33,490,507 | -| sphincs-sha256-256s-robust (3 executions) | clean | AVG: 2,524,393,357
MIN: 2,524,337,328
MAX: 2,524,432,487 | AVG: 31,056,826,302
MIN: 31,055,874,069
MAX: 31,057,485,164 | AVG: 47,434,569
MIN: 46,022,129
MAX: 48,212,821 | -| sphincs-sha256-256s-simple (3 executions) | clean | AVG: 952,799,879
MIN: 952,642,357
MAX: 953,062,293 | AVG: 12,304,132,668
MIN: 12,303,657,740
MAX: 12,304,436,252 | AVG: 16,715,346
MIN: 16,326,849
MAX: 17,137,621 | -| sphincs-shake256-128f-robust (3 executions) | clean | AVG: 113,347,070
MIN: 113,347,058
MAX: 113,347,093 | AVG: 2,788,974,930
MIN: 2,787,812,662
MAX: 2,790,137,173 | AVG: 158,730,948
MIN: 156,406,568
MAX: 160,667,913 | -| sphincs-shake256-128f-simple (3 executions) | clean | AVG: 59,759,081
MIN: 59,759,080
MAX: 59,759,082 | AVG: 1,483,676,214
MIN: 1,483,213,924
MAX: 1,484,204,563 | AVG: 83,065,165
MIN: 81,414,021
MAX: 84,584,221 | -| sphincs-shake256-128s-robust (3 executions) | clean | AVG: 7,255,773,038
MIN: 7,255,773,014
MAX: 7,255,773,057 | AVG: 54,573,950,176
MIN: 54,572,529,688
MAX: 54,575,241,560 | AVG: 53,615,181
MIN: 51,549,111
MAX: 55,423,008 | -| sphincs-shake256-128s-simple (3 executions) | clean | AVG: 3,825,341,548
MIN: 3,825,341,531
MAX: 3,825,341,564 | AVG: 29,086,410,120
MIN: 29,085,749,525
MAX: 29,087,533,088 | AVG: 29,495,105
MIN: 28,966,755
MAX: 30,155,531 | -| sphincs-shake256-192f-robust (3 executions) | clean | AVG: 167,154,323
MIN: 167,154,303
MAX: 167,154,334 | AVG: 4,461,897,673
MIN: 4,458,767,619
MAX: 4,464,636,487 | AVG: 240,590,626
MIN: 238,634,394
MAX: 243,329,332 | -| sphincs-shake256-192f-simple (3 executions) | clean | AVG: 88,333,405
MIN: 88,333,405
MAX: 88,333,406 | AVG: 2,409,188,992
MIN: 2,408,787,940
MAX: 2,409,991,046 | AVG: 123,334,622
MIN: 122,866,683
MAX: 123,668,857 | -| sphincs-shake256-192s-robust (3 executions) | clean | AVG: 10,698,254,977
MIN: 10,698,254,964
MAX: 10,698,254,997 | AVG: 93,298,513,700
MIN: 93,295,644,767
MAX: 93,301,121,760 | AVG: 81,201,582
MIN: 77,549,977
MAX: 83,809,891 | -| sphincs-shake256-192s-simple (3 executions) | clean | AVG: 5,652,907,918
MIN: 5,652,907,897
MAX: 5,652,907,934 | AVG: 50,824,666,973
MIN: 50,823,330,463
MAX: 50,826,137,107 | AVG: 41,687,543
MIN: 40,818,602
MAX: 42,623,345 | -| sphincs-shake256-256f-robust (3 executions) | clean | AVG: 444,922,977
MIN: 444,922,967
MAX: 444,922,998 | AVG: 8,993,352,645
MIN: 8,987,821,428
MAX: 9,000,464,222 | AVG: 243,254,884
MIN: 240,752,880
MAX: 244,703,467 | -| sphincs-shake256-256f-simple (3 executions) | clean | AVG: 235,448,503
MIN: 235,448,502
MAX: 235,448,505 | AVG: 4,865,464,381
MIN: 4,864,247,499
MAX: 4,867,289,711 | AVG: 127,387,108
MIN: 125,561,248
MAX: 129,010,103 | -| sphincs-shake256-256s-robust (3 executions) | clean | AVG: 7,117,488,480
MIN: 7,117,488,473
MAX: 7,117,488,486 | AVG: 81,040,359,080
MIN: 81,037,593,485
MAX: 81,043,519,709 | AVG: 124,099,579
MIN: 123,967,874
MAX: 124,362,934 | -| sphincs-shake256-256s-simple (3 executions) | clean | AVG: 3,764,358,451
MIN: 3,764,358,431
MAX: 3,764,358,466 | AVG: 44,857,260,081
MIN: 44,856,516,353
MAX: 44,858,138,896 | AVG: 62,264,803
MIN: 61,656,689
MAX: 62,670,229 | +| aimer-l1-param1 (10 executions) | ref | AVG: 392,943
MIN: 392,938
MAX: 392,977 | AVG: 32,386,301
MIN: 32,386,203
MAX: 32,386,424 | AVG: 31,111,672
MIN: 31,111,588
MAX: 31,111,782 | +| aimer-l1-param2 (10 executions) | ref | AVG: 392,938
MIN: 392,938
MAX: 392,941 | AVG: 79,450,721
MIN: 79,450,349
MAX: 79,451,595 | AVG: 78,429,263
MIN: 78,398,061
MAX: 78,434,987 | +| aimer-l3-param1 (10 executions) | ref | AVG: 981,288
MIN: 981,288
MAX: 981,290 | AVG: 90,953,716
MIN: 90,953,603
MAX: 90,953,763 | AVG: 88,350,755
MIN: 88,350,600
MAX: 88,350,906 | +| ascon-sign-128f-robust (10 executions) | ref | AVG: 122,506,162
MIN: 122,506,099
MAX: 122,506,254 | AVG: 2,855,797,836
MIN: 2,855,797,243
MAX: 2,855,798,602 | AVG: 174,707,763
MIN: 169,973,472
MAX: 179,525,137 | +| ascon-sign-128f-simple (10 executions) | ref | AVG: 69,376,878
MIN: 69,376,875
MAX: 69,376,883 | AVG: 1,629,111,557
MIN: 1,629,111,334
MAX: 1,629,112,028 | AVG: 97,798,317
MIN: 95,509,050
MAX: 98,714,007 | +| ascon-sign-128s-robust (10 executions) | ref | AVG: 7,842,366,557
MIN: 7,842,366,432
MAX: 7,842,366,620 | AVG: 59,267,552,580
MIN: 59,267,543,517
MAX: 59,267,565,672 | AVG: 60,232,378
MIN: 57,865,239
MAX: 62,848,708 | +| ascon-sign-128s-simple (10 executions) | ref | AVG: 4,441,129,007
MIN: 4,441,128,624
MAX: 4,441,129,583 | AVG: 33,877,719,255
MIN: 33,877,704,467
MAX: 33,877,739,518 | AVG: 33,665,713
MIN: 31,101,669
MAX: 34,993,483 | +| ascon-sign-192f-robust (10 executions) | ref | AVG: 222,614,206
MIN: 222,614,156
MAX: 222,614,345 | AVG: 5,712,962,198
MIN: 5,712,960,682
MAX: 5,712,963,829 | AVG: 321,026,499
MIN: 315,341,414
MAX: 327,745,233 | +| ascon-sign-192f-simple (10 executions) | ref | AVG: 128,167,067
MIN: 128,167,038
MAX: 128,167,083 | AVG: 3,345,487,807
MIN: 3,345,484,178
MAX: 3,345,492,588 | AVG: 179,328,421
MIN: 175,094,665
MAX: 183,794,127 | +| ascon-sign-192s-robust (10 executions) | ref | AVG: 14,249,838,562
MIN: 14,249,837,693
MAX: 14,249,840,118 | AVG: 126,646,612,223
MIN: 126,646,594,160
MAX: 126,646,651,564 | AVG: 111,451,290
MIN: 108,763,808
MAX: 114,965,691 | +| ascon-sign-192s-simple (10 executions) | ref | AVG: 8,204,011,592
MIN: 8,204,011,246
MAX: 8,204,011,971 | AVG: 74,760,768,141
MIN: 74,760,751,354
MAX: 74,760,789,761 | AVG: 61,679,880
MIN: 58,983,014
MAX: 64,202,741 | +| biscuit128f (10 executions) | ref | AVG: 1,054,719
MIN: 1,054,719
MAX: 1,054,720 | AVG: 274,072,426
MIN: 274,072,411
MAX: 274,072,461 | AVG: 254,371,114
MIN: 254,371,087
MAX: 254,371,140 | +| biscuit192f (10 executions) | ref | AVG: 1,886,203
MIN: 1,886,199
MAX: 1,886,238 | AVG: 765,314,258
MIN: 765,314,227
MAX: 765,314,291 | AVG: 713,412,502
MIN: 713,412,394
MAX: 713,412,608 | +| biscuit256f (10 executions) | ref | AVG: 3,301,990
MIN: 3,301,983
MAX: 3,302,022 | AVG: 1,747,187,940
MIN: 1,747,187,918
MAX: 1,747,187,973 | AVG: 1,678,998,604
MIN: 1,678,998,013
MAX: 1,678,998,987 | +| cross-sha2-r-sdp-1-fast (10 executions) | ref | AVG: 5,614,888
MIN: 5,590,276
MAX: 5,650,611 | AVG: 216,566,013
MIN: 215,745,202
MAX: 217,395,250 | AVG: 143,008,126
MIN: 141,803,162
MAX: 144,002,548 | +| cross-sha2-r-sdp-3-fast (10 executions) | ref | AVG: 8,201,340
MIN: 8,148,672
MAX: 8,208,465 | AVG: 241,899,820
MIN: 241,815,860
MAX: 242,049,039 | AVG: 123,896,179
MIN: 123,524,606
MAX: 124,545,760 | +| cross-sha2-r-sdpg-1-fast (10 executions) | ref | AVG: 2,151,163
MIN: 2,115,797
MAX: 2,174,685 | AVG: 116,162,852
MIN: 116,120,174
MAX: 116,181,821 | AVG: 87,741,423
MIN: 87,209,686
MAX: 88,267,494 | +| cross-sha2-r-sdpg-1-small (10 executions) | ref | AVG: 2,151,212
MIN: 2,115,845
MAX: 2,174,734 | AVG: 391,718,680
MIN: 391,662,566
MAX: 391,774,957 | AVG: 368,397,996
MIN: 367,703,173
MAX: 369,416,443 | +| cross-sha2-r-sdpg-3-fast (10 executions) | ref | AVG: 3,049,185
MIN: 2,996,960
MAX: 3,055,381 | AVG: 136,242,875
MIN: 136,234,139
MAX: 136,299,163 | AVG: 84,236,165
MIN: 83,659,318
MAX: 85,067,521 | +| cross-sha2-r-sdpg-5-fast (10 executions) | ref | AVG: 4,302,017
MIN: 4,249,738
MAX: 4,308,343 | AVG: 221,761,047
MIN: 221,758,357
MAX: 221,762,936 | AVG: 134,821,310
MIN: 134,547,992
MAX: 135,025,658 | +| cross-sha3-r-sdp-1-fast (10 executions) | ref | AVG: 967,965
MIN: 963,482
MAX: 978,861 | AVG: 58,864,285
MIN: 58,853,041
MAX: 58,876,854 | AVG: 30,641,221
MIN: 30,631,654
MAX: 30,661,122 | +| cross-sha3-r-sdp-3-fast (10 executions) | ref | AVG: 2,195,040
MIN: 2,191,401
MAX: 2,205,040 | AVG: 90,064,203
MIN: 90,034,522
MAX: 90,080,511 | AVG: 48,561,804
MIN: 48,542,657
MAX: 48,577,008 | +| cross-sha3-r-sdpg-1-fast (10 executions) | ref | AVG: 290,136
MIN: 287,742
MAX: 297,758 | AVG: 29,963,868
MIN: 29,960,918
MAX: 29,974,902 | AVG: 20,093,649
MIN: 20,078,626
MAX: 20,103,416 | +| cross-sha3-r-sdpg-1-small (10 executions) | ref | AVG: 290,135
MIN: 287,741
MAX: 297,757 | AVG: 102,853,622
MIN: 102,847,774
MAX: 102,861,948 | AVG: 75,137,510
MIN: 75,126,803
MAX: 75,159,685 | +| cross-sha3-r-sdpg-3-fast (10 executions) | ref | AVG: 627,948
MIN: 625,525
MAX: 637,639 | AVG: 43,573,841
MIN: 43,565,461
MAX: 43,582,933 | AVG: 27,513,830
MIN: 27,493,024
MAX: 27,525,746 | +| cross-sha3-r-sdpg-5-fast (10 executions) | ref | AVG: 1,146,280
MIN: 1,142,409
MAX: 1,153,794 | AVG: 93,557,878
MIN: 93,547,167
MAX: 93,566,329 | AVG: 59,948,216
MIN: 59,857,434
MAX: 60,043,852 | +| dilithium2 (90 executions) | clean | AVG: 1,873,447
MIN: 1,838,554
MAX: 1,903,845 | AVG: 7,846,622
MIN: 3,321,671
MAX: 28,761,609 | AVG: 2,062,804
MIN: 2,062,332
MAX: 2,063,181 | +| dilithium2 (100 executions) | m4f | AVG: 1,427,684
MIN: 1,390,524
MAX: 1,466,437 | AVG: 4,219,137
MIN: 1,813,668
MAX: 12,587,382 | AVG: 1,417,706
MIN: 1,417,251
MAX: 1,418,128 | +| dilithium3 (90 executions) | clean | AVG: 3,205,542
MIN: 3,204,354
MAX: 3,206,592 | AVG: 12,108,503
MIN: 5,097,440
MAX: 50,759,276 | AVG: 3,377,010
MIN: 3,376,729
MAX: 3,377,395 | +| dilithium3 (100 executions) | m4f | AVG: 2,515,970
MIN: 2,514,894
MAX: 2,516,922 | AVG: 5,896,583
MIN: 2,935,265
MAX: 23,718,896 | AVG: 2,411,234
MIN: 2,410,948
MAX: 2,411,551 | +| dilithium5 (90 executions) | clean | AVG: 5,346,066
MIN: 5,287,239
MAX: 5,395,626 | AVG: 15,205,929
MIN: 7,953,360
MAX: 49,173,429 | AVG: 5,609,664
MIN: 5,609,137
MAX: 5,610,119 | +| dilithium5 (100 executions) | m4f | AVG: 4,273,211
MIN: 4,210,308
MAX: 4,329,697 | AVG: 8,062,110
MIN: 4,882,708
MAX: 18,398,575 | AVG: 4,185,407
MIN: 4,184,878
MAX: 4,185,954 | +| falcon-1024 (10 executions) | m4-ct | AVG: 354,880,005
MIN: 284,902,033
MAX: 635,131,652 | AVG: 87,741,288
MIN: 87,506,676
MAX: 87,922,628 | AVG: 991,320
MIN: 982,548
MAX: 997,219 | +| falcon-1024 (10 executions) | opt-ct | AVG: 555,202,324
MIN: 284,912,829
MAX: 1,157,528,581 | AVG: 87,710,190
MIN: 87,606,677
MAX: 87,841,235 | AVG: 993,584
MIN: 983,066
MAX: 997,523 | +| falcon-1024 (10 executions) | opt-leaktime | AVG: 438,412,062
MIN: 334,858,742
MAX: 625,013,074 | AVG: 80,139,483
MIN: 79,891,200
MAX: 80,551,967 | AVG: 994,127
MIN: 984,891
MAX: 997,390 | +| falcon-1024-tree (10 executions) | opt-ct | AVG: 500,950,316
MIN: 327,706,067
MAX: 969,046,860 | AVG: 39,207,109
MIN: 39,013,867
MAX: 39,449,442 | AVG: 992,787
MIN: 982,032
MAX: 998,080 | +| falcon-1024-tree (10 executions) | opt-leaktime | AVG: 372,505,822
MIN: 284,807,343
MAX: 551,245,131 | AVG: 42,213,136
MIN: 41,842,229
MAX: 42,582,424 | AVG: 995,859
MIN: 984,960
MAX: 998,421 | +| falcon-512 (10 executions) | m4-ct | AVG: 161,245,486
MIN: 110,088,298
MAX: 279,215,300 | AVG: 40,225,282
MIN: 40,072,879
MAX: 40,389,913 | AVG: 478,930
MIN: 472,982
MAX: 485,577 | +| falcon-512 (10 executions) | opt-ct | AVG: 151,650,543
MIN: 116,181,731
MAX: 228,216,352 | AVG: 40,147,309
MIN: 40,003,575
MAX: 40,360,540 | AVG: 480,990
MIN: 472,795
MAX: 485,260 | +| falcon-512 (10 executions) | opt-leaktime | AVG: 159,608,965
MIN: 111,149,933
MAX: 301,580,807 | AVG: 37,267,337
MIN: 36,991,076
MAX: 37,518,518 | AVG: 478,421
MIN: 471,680
MAX: 484,872 | +| falcon-512-tree (10 executions) | m4-ct | AVG: 167,653,515
MIN: 121,618,919
MAX: 272,326,714 | AVG: 18,250,061
MIN: 18,135,371
MAX: 18,325,579 | AVG: 479,823
MIN: 471,774
MAX: 485,540 | +| falcon-512-tree (10 executions) | opt-ct | AVG: 184,949,574
MIN: 121,623,805
MAX: 270,290,280 | AVG: 18,248,036
MIN: 18,069,599
MAX: 18,462,666 | AVG: 484,565
MIN: 484,059
MAX: 485,335 | +| falcon-512-tree (10 executions) | opt-leaktime | AVG: 156,710,258
MIN: 106,732,109
MAX: 326,634,247 | AVG: 20,050,613
MIN: 19,891,001
MAX: 20,227,947 | AVG: 482,101
MIN: 472,948
MAX: 485,643 | +| haetae2 (100 executions) | m4f | AVG: 6,743,278
MIN: 1,555,292
MAX: 25,393,506 | AVG: 21,993,963
MIN: 4,721,290
MAX: 86,765,689 | AVG: 918,459
MIN: 918,244
MAX: 918,668 | +| haetae2 (100 executions) | ref | AVG: 9,363,639
MIN: 1,716,264
MAX: 41,895,014 | AVG: 31,631,089
MIN: 6,247,382
MAX: 216,853,925 | AVG: 1,104,080
MIN: 1,103,874
MAX: 1,104,329 | +| haetae3 (100 executions) | m4f | AVG: 12,925,388
MIN: 2,752,846
MAX: 52,240,529 | AVG: 30,891,994
MIN: 7,467,529
MAX: 160,522,018 | AVG: 1,760,745
MIN: 1,760,408
MAX: 1,761,081 | +| haetae3 (100 executions) | ref | AVG: 20,247,658
MIN: 3,023,325
MAX: 101,863,701 | AVG: 41,078,691
MIN: 9,771,906
MAX: 168,213,225 | AVG: 1,998,105
MIN: 1,997,691
MAX: 1,998,406 | +| haetae5 (100 executions) | m4f | AVG: 19,064,310
MIN: 3,530,778
MAX: 94,189,003 | AVG: 44,679,058
MIN: 9,277,906
MAX: 182,948,586 | AVG: 2,323,830
MIN: 2,323,454
MAX: 2,324,229 | +| haetae5 (100 executions) | ref | AVG: 18,169,623
MIN: 3,864,921
MAX: 64,304,046 | AVG: 63,180,459
MIN: 12,011,324
MAX: 264,538,555 | AVG: 2,461,679
MIN: 2,461,294
MAX: 2,462,068 | +| hawk1024 (100 executions) | ref | AVG: 246,017,495
MIN: 183,762,252
MAX: 662,190,563 | AVG: 4,309,675
MIN: 4,309,595
MAX: 4,309,759 | AVG: 2,782,441
MIN: 2,780,257
MAX: 2,784,348 | +| hawk256 (100 executions) | ref | AVG: 15,758,436
MIN: 11,600,791
MAX: 35,345,186 | AVG: 1,042,002
MIN: 954,957
MAX: 2,294,025 | AVG: 627,815
MIN: 627,480
MAX: 628,077 | +| hawk512 (100 executions) | ref | AVG: 53,733,289
MIN: 45,271,209
MAX: 174,603,165 | AVG: 1,972,051
MIN: 1,971,984
MAX: 1,972,127 | AVG: 1,293,829
MIN: 1,292,946
MAX: 1,294,494 | +| mayo1 (10 executions) | m4f | AVG: 5,242,008
MIN: 5,241,998
MAX: 5,242,042 | AVG: 9,100,704
MIN: 9,100,681
MAX: 9,100,722 | AVG: 4,952,860
MIN: 4,952,848
MAX: 4,952,890 | +| mayo1 (10 executions) | ref | AVG: 7,977,004
MIN: 7,976,973
MAX: 7,977,015 | AVG: 18,005,446
MIN: 18,005,440
MAX: 18,005,487 | AVG: 6,294,480
MIN: 6,294,464
MAX: 6,294,503 | +| mayo2 (10 executions) | m4f | AVG: 11,917,959
MIN: 11,917,940
MAX: 11,917,980 | AVG: 11,979,613
MIN: 11,979,582
MAX: 11,979,624 | AVG: 5,130,148
MIN: 5,130,131
MAX: 5,130,180 | +| mayo2 (10 executions) | ref | AVG: 18,432,706
MIN: 18,432,701
MAX: 18,432,740 | AVG: 23,546,659
MIN: 23,546,640
MAX: 23,546,680 | AVG: 5,494,246
MIN: 5,494,236
MAX: 5,494,276 | +| mayo3 (10 executions) | m4f | AVG: 18,946,738
MIN: 18,946,737
MAX: 18,946,740 | AVG: 32,477,408
MIN: 32,477,407
MAX: 32,477,411 | AVG: 16,852,927
MIN: 16,852,799
MAX: 16,853,047 | +| meds13220 (10 executions) | ref | AVG: 47,801,890
MIN: 47,796,259
MAX: 47,805,424 | AVG: 1,774,401,869
MIN: 1,773,011,038
MAX: 1,779,733,959 | AVG: 1,767,764,521
MIN: 1,766,326,468
MAX: 1,773,152,168 | +| meds55604 (10 executions) | ref | AVG: 253,603,604
MIN: 253,590,695
MAX: 253,615,749 | AVG: 8,009,948,412
MIN: 8,009,909,000
MAX: 8,009,995,748 | AVG: 8,320,756,990
MIN: 8,320,682,364
MAX: 8,320,835,448 | +| mirith_IIIa_fast (10 executions) | ref | AVG: 3,009,088
MIN: 3,009,084
MAX: 3,009,123 | AVG: 891,195,817
MIN: 891,191,657
MAX: 891,198,221 | AVG: 831,725,932
MIN: 831,697,264
MAX: 831,742,620 | +| mirith_IIIb_fast (10 executions) | ref | AVG: 4,565,011
MIN: 4,565,007
MAX: 4,565,046 | AVG: 1,298,812,706
MIN: 1,298,810,546
MAX: 1,298,815,343 | AVG: 1,214,260,655
MIN: 1,214,247,570
MAX: 1,214,277,229 | +| mirith_Ia_fast (10 executions) | ref | AVG: 1,303,728
MIN: 1,303,721
MAX: 1,303,764 | AVG: 296,732,107
MIN: 296,728,990
MAX: 296,734,109 | AVG: 276,059,526
MIN: 276,031,297
MAX: 276,080,171 | +| mirith_Ib_fast (10 executions) | ref | AVG: 2,514,924
MIN: 2,514,920
MAX: 2,514,964 | AVG: 565,778,762
MIN: 565,776,437
MAX: 565,781,372 | AVG: 528,408,968
MIN: 528,400,758
MAX: 528,415,550 | +| mirith_Va_fast (10 executions) | ref | AVG: 6,254,885
MIN: 6,254,885
MAX: 6,254,887 | AVG: 2,373,353,150
MIN: 2,373,347,664
MAX: 2,373,358,665 | AVG: 2,233,960,878
MIN: 2,233,908,923
MAX: 2,234,010,721 | +| mirith_Vb_fast (10 executions) | ref | AVG: 8,807,561
MIN: 8,807,538
MAX: 8,807,580 | AVG: 3,406,388,587
MIN: 3,406,385,114
MAX: 3,406,391,954 | AVG: 3,205,119,426
MIN: 3,205,069,724
MAX: 3,205,181,151 | +| mirith_hypercube_IIIa_fast (10 executions) | ref | AVG: 3,009,085
MIN: 3,009,081
MAX: 3,009,121 | AVG: 323,235,292
MIN: 323,169,167
MAX: 323,309,072 | AVG: 313,483,184
MIN: 313,455,293
MAX: 313,507,476 | +| mirith_hypercube_IIIa_short (10 executions) | ref | AVG: 3,009,092
MIN: 3,009,084
MAX: 3,009,125 | AVG: 718,708,882
MIN: 718,706,940
MAX: 718,725,922 | AVG: 730,959,561
MIN: 730,953,898
MAX: 730,965,347 | +| mirith_hypercube_IIIb_fast (10 executions) | ref | AVG: 4,565,028
MIN: 4,565,013
MAX: 4,565,053 | AVG: 450,970,203
MIN: 450,912,625
MAX: 451,011,870 | AVG: 441,590,516
MIN: 441,574,663
MAX: 441,613,045 | +| mirith_hypercube_IIIb_short (10 executions) | ref | AVG: 4,565,027
MIN: 4,565,008
MAX: 4,565,047 | AVG: 845,096,869
MIN: 845,094,881
MAX: 845,114,293 | AVG: 860,321,543
MIN: 860,312,205
MAX: 860,325,520 | +| mirith_hypercube_Ia_fast (10 executions) | opt | AVG: 995,563
MIN: 995,419
MAX: 995,752 | AVG: 58,999,862
MIN: 58,972,041
MAX: 59,042,031 | AVG: 53,599,779
MIN: 53,565,299
MAX: 53,623,234 | +| mirith_hypercube_Ia_fast (10 executions) | ref | AVG: 1,303,715
MIN: 1,303,715
MAX: 1,303,718 | AVG: 116,964,064
MIN: 116,941,316
MAX: 116,990,779 | AVG: 111,505,597
MIN: 111,482,197
MAX: 111,525,936 | +| mirith_hypercube_Ia_short (10 executions) | ref | AVG: 1,303,722
MIN: 1,303,721
MAX: 1,303,724 | AVG: 370,999,431
MIN: 370,999,393
MAX: 370,999,483 | AVG: 364,000,112
MIN: 363,996,085
MAX: 364,002,214 | +| mirith_hypercube_Ib_fast (10 executions) | opt | AVG: 1,879,815
MIN: 1,879,488
MAX: 1,880,127 | AVG: 83,825,209
MIN: 83,797,728
MAX: 83,857,763 | AVG: 78,145,476
MIN: 78,137,727
MAX: 78,153,192 | +| mirith_hypercube_Ib_fast (10 executions) | ref | AVG: 2,514,929
MIN: 2,514,917
MAX: 2,514,959 | AVG: 205,510,181
MIN: 205,497,961
MAX: 205,547,801 | AVG: 199,772,762
MIN: 199,769,009
MAX: 199,782,994 | +| mirith_hypercube_Ib_short (10 executions) | ref | AVG: 2,514,920
MIN: 2,514,920
MAX: 2,514,923 | AVG: 447,351,952
MIN: 447,351,902
MAX: 447,351,992 | AVG: 440,279,587
MIN: 440,278,101
MAX: 440,281,382 | +| mirith_hypercube_Va_fast (10 executions) | ref | AVG: 6,254,896
MIN: 6,254,886
MAX: 6,254,922 | AVG: 808,070,687
MIN: 808,007,911
MAX: 808,157,180 | AVG: 792,058,628
MIN: 792,006,360
MAX: 792,098,565 | +| mirith_hypercube_Vb_fast (10 executions) | ref | AVG: 8,807,565
MIN: 8,807,542
MAX: 8,807,583 | AVG: 1,134,272,446
MIN: 1,134,201,632
MAX: 1,134,368,110 | AVG: 1,117,085,816
MIN: 1,117,059,819
MAX: 1,117,104,354 | +| mqom_cat1_gf251_fast (10 executions) | ref | AVG: 7,780,082
MIN: 7,761,398
MAX: 7,795,766 | AVG: 149,063,790
MIN: 149,045,955
MAX: 149,079,787 | AVG: 136,742,778
MIN: 136,613,266
MAX: 136,821,602 | +| mqom_cat1_gf31_fast (10 executions) | ref | AVG: 8,472,628
MIN: 8,471,619
MAX: 8,473,585 | AVG: 243,796,920
MIN: 243,782,136
MAX: 243,811,088 | AVG: 244,346,110
MIN: 244,239,828
MAX: 244,424,317 | +| ov-Ip (10 executions) | m4f | AVG: 139,186,121
MIN: 139,186,115
MAX: 139,186,154 | AVG: 2,465,106
MIN: 2,465,096
MAX: 2,465,133 | AVG: 993,538
MIN: 979,943
MAX: 997,098 | +| ov-Ip (10 executions) | ref | AVG: 350,783,613
MIN: 350,783,583
MAX: 350,783,641 | AVG: 6,479,343
MIN: 6,479,329
MAX: 6,479,364 | AVG: 1,301,328
MIN: 1,301,328
MAX: 1,301,329 | +| ov-Ip-pkc (10 executions) | m4fspeed | AVG: 175,417,340
MIN: 175,417,323
MAX: 175,417,366 | AVG: 2,484,348
MIN: 2,484,345
MAX: 2,484,383 | AVG: 11,197,952
MIN: 11,185,489
MAX: 11,202,816 | +| ov-Ip-pkc (10 executions) | m4fstack | AVG: 175,417,332
MIN: 175,417,319
MAX: 175,417,363 | AVG: 2,484,355
MIN: 2,484,351
MAX: 2,484,391 | AVG: 12,047,546
MIN: 12,033,622
MAX: 12,049,099 | +| ov-Ip-pkc (10 executions) | ref | AVG: 375,129,899
MIN: 375,129,876
MAX: 375,129,925 | AVG: 6,924,383
MIN: 6,924,364
MAX: 6,924,403 | AVG: 11,429,702
MIN: 11,429,685
MAX: 11,429,720 | +| ov-Ip-pkc-skc (10 executions) | m4fspeed | AVG: 175,417,478
MIN: 175,417,464
MAX: 175,417,508 | AVG: 89,193,259
MIN: 89,193,250
MAX: 89,193,291 | AVG: 11,987,533
MIN: 11,972,791
MAX: 11,991,175 | +| ov-Ip-pkc-skc (10 executions) | m4fstack | AVG: 175,417,481
MIN: 175,417,467
MAX: 175,417,513 | AVG: 89,193,257
MIN: 89,193,252
MAX: 89,193,294 | AVG: 12,046,865
MIN: 12,036,910
MAX: 12,049,102 | +| ov-Ip-pkc-skc (10 executions) | ref | AVG: 375,129,970
MIN: 375,129,961
MAX: 375,129,979 | AVG: 241,521,035
MIN: 241,521,010
MAX: 241,521,062 | AVG: 12,160,652
MIN: 12,160,649
MAX: 12,160,655 | +| perk-128-fast-3 (10 executions) | m4 | AVG: 600,370
MIN: 588,589
MAX: 617,172 | AVG: 176,603,058
MIN: 172,398,218
MAX: 179,515,947 | AVG: 80,954,403
MIN: 80,639,115
MAX: 81,369,755 | +| perk-128-fast-3 (10 executions) | ref | AVG: 704,259
MIN: 693,368
MAX: 736,117 | AVG: 217,778,838
MIN: 217,461,187
MAX: 218,268,228 | AVG: 96,466,250
MIN: 96,183,326
MAX: 96,888,788 | +| perk-128-fast-5 (10 executions) | m4 | AVG: 731,441
MIN: 731,364
MAX: 731,540 | AVG: 169,489,946
MIN: 165,666,000
MAX: 172,125,278 | AVG: 78,073,374
MIN: 77,727,738
MAX: 78,357,997 | +| perk-128-fast-5 (10 executions) | ref | AVG: 913,665
MIN: 909,095
MAX: 954,075 | AVG: 215,313,534
MIN: 214,778,346
MAX: 215,586,755 | AVG: 93,670,132
MIN: 93,146,285
MAX: 93,977,473 | +| perk-128-short-3 (10 executions) | m4 | AVG: 590,902
MIN: 588,605
MAX: 599,700 | AVG: 953,694,810
MIN: 909,659,772
MAX: 990,039,092 | AVG: 460,190,199
MIN: 458,863,203
MAX: 461,050,669 | +| perk-128-short-5 (10 executions) | m4 | AVG: 731,445
MIN: 731,335
MAX: 731,531 | AVG: 897,819,203
MIN: 874,104,462
MAX: 910,961,959 | AVG: 428,108,291
MIN: 426,956,727
MAX: 428,829,873 | +| perk-192-fast-3 (10 executions) | m4 | AVG: 1,417,042
MIN: 1,416,960
MAX: 1,417,171 | AVG: 417,178,570
MIN: 409,941,430
MAX: 430,893,116 | AVG: 194,559,724
MIN: 193,854,854
MAX: 195,157,065 | +| perk-192-fast-5 (10 executions) | m4 | AVG: 1,674,275
MIN: 1,664,390
MAX: 1,675,499 | AVG: 398,534,166
MIN: 393,310,316
MAX: 407,792,875 | AVG: 186,556,828
MIN: 185,719,616
MAX: 187,993,601 | +| perk-192-short-3 (10 executions) | m4 | AVG: 1,421,844
MIN: 1,416,962
MAX: 1,464,701 | AVG: 2,361,914,331
MIN: 2,294,967,247
MAX: 2,446,192,375 | AVG: 1,177,027,799
MIN: 1,172,107,658
MAX: 1,180,352,563 | +| perk-192-short-5 (10 executions) | m4 | AVG: 1,675,264
MIN: 1,674,747
MAX: 1,675,426 | AVG: 2,199,500,885
MIN: 2,155,317,947
MAX: 2,244,259,412 | AVG: 1,098,396,172
MIN: 1,096,382,473
MAX: 1,100,817,952 | +| perk-256-fast-3 (10 executions) | m4 | AVG: 2,473,015
MIN: 2,472,888
MAX: 2,473,216 | AVG: 878,427,616
MIN: 863,486,856
MAX: 896,605,165 | AVG: 418,401,493
MIN: 416,315,010
MAX: 421,403,946 | +| perk-256-fast-5 (10 executions) | m4 | AVG: 2,885,058
MIN: 2,878,858
MAX: 2,939,569 | AVG: 826,739,240
MIN: 816,655,441
MAX: 839,215,281 | AVG: 397,855,320
MIN: 396,898,494
MAX: 398,693,053 | +| perk-256-short-3 (10 executions) | m4 | AVG: 2,478,803
MIN: 2,472,893
MAX: 2,531,188 | AVG: 5,056,839,759
MIN: 5,015,570,985
MAX: 5,098,913,929 | AVG: 2,638,814,692
MIN: 2,626,576,274
MAX: 2,645,713,279 | +| perk-256-short-5 (10 executions) | m4 | AVG: 2,889,949
MIN: 2,878,822
MAX: 2,988,248 | AVG: 4,678,162,399
MIN: 4,520,673,553
MAX: 4,740,505,898 | AVG: 2,453,866,153
MIN: 2,446,870,524
MAX: 2,460,260,204 | +| snova-24-5-16-4-esk (10 executions) | ref | AVG: 24,840,838
MIN: 24,840,391
MAX: 24,841,191 | AVG: 139,251,354
MIN: 139,235,721
MAX: 139,274,512 | AVG: 88,454,046
MIN: 88,453,528
MAX: 88,454,429 | +| snova-24-5-16-4-ssk (10 executions) | ref | AVG: 24,772,323
MIN: 24,771,821
MAX: 24,772,994 | AVG: 174,094,748
MIN: 160,180,156
MAX: 299,202,162 | AVG: 88,453,756
MIN: 88,453,293
MAX: 88,454,408 | +| snova-25-8-16-3-esk (10 executions) | ref | AVG: 35,280,792
MIN: 35,280,693
MAX: 35,280,867 | AVG: 71,674,196
MIN: 65,171,606
MAX: 130,098,735 | AVG: 42,542,485
MIN: 42,542,403
MAX: 42,542,553 | +| snova-25-8-16-3-ssk (10 executions) | ref | AVG: 35,195,324
MIN: 35,195,216
MAX: 35,195,579 | AVG: 112,654,217
MIN: 93,165,980
MAX: 158,103,540 | AVG: 42,542,507
MIN: 42,542,396
MAX: 42,542,732 | +| snova-28-17-16-2-esk (10 executions) | ref | AVG: 51,177,590
MIN: 51,177,548
MAX: 51,177,647 | AVG: 23,387,139
MIN: 21,270,788
MAX: 42,311,786 | AVG: 19,180,389
MIN: 19,180,360
MAX: 19,180,440 | +| snova-28-17-16-2-ssk (10 executions) | ref | AVG: 51,065,038
MIN: 51,064,999
MAX: 51,065,086 | AVG: 52,865,514
MIN: 50,757,388
MAX: 71,788,606 | AVG: 19,180,379
MIN: 19,180,357
MAX: 19,180,425 | +| snova-37-8-16-4-ssk (10 executions) | ref | AVG: 122,023,801
MIN: 122,023,399
MAX: 122,024,216 | AVG: 533,063,912
MIN: 533,033,960
MAX: 533,090,127 | AVG: 335,806,349
MIN: 335,805,890
MAX: 335,806,820 | +| sphincs-a-sha2-128f (10 executions) | ref | AVG: 30,278,936
MIN: 30,278,762
MAX: 30,279,211 | AVG: 382,270,810
MIN: 382,269,421
MAX: 382,271,497 | AVG: 35,695,646
MIN: 35,693,840
MAX: 35,698,828 | +| sphincs-a-sha2-128s (10 executions) | ref | AVG: 814,836,852
MIN: 814,834,574
MAX: 814,838,039 | AVG: 6,981,930,727
MIN: 6,981,924,687
MAX: 6,981,936,443 | AVG: 187,090,082
MIN: 187,087,928
MAX: 187,093,600 | +| sphincs-a-sha2-192f (10 executions) | ref | AVG: 45,930,664
MIN: 45,930,481
MAX: 45,930,983 | AVG: 634,374,072
MIN: 634,373,011
MAX: 634,375,225 | AVG: 35,145,783
MIN: 35,144,266
MAX: 35,146,607 | +| sphincs-a-shake-128f (10 executions) | ref | AVG: 61,578,406
MIN: 61,578,107
MAX: 61,578,885 | AVG: 1,188,147,363
MIN: 1,188,146,489
MAX: 1,188,148,063 | AVG: 76,330,135
MIN: 76,328,602
MAX: 76,331,478 | +| sphincs-a-shake-128s (10 executions) | ref | AVG: 2,342,298,427
MIN: 2,342,296,403
MAX: 2,342,299,607 | AVG: 22,926,754,899
MIN: 22,926,752,978
MAX: 22,926,758,555 | AVG: 241,835,141
MIN: 241,830,735
MAX: 241,838,908 | +| sphincs-a-shake-192f (10 executions) | ref | AVG: 110,027,677
MIN: 110,027,323
MAX: 110,027,950 | AVG: 1,814,954,350
MIN: 1,814,953,585
MAX: 1,814,955,913 | AVG: 64,022,276
MIN: 64,020,853
MAX: 64,023,988 | +| sphincs-sha2-128f-simple (10 executions) | clean | AVG: 15,742,990
MIN: 15,742,958
MAX: 15,742,996 | AVG: 368,575,228
MIN: 368,575,193
MAX: 368,575,246 | AVG: 21,923,628
MIN: 21,369,867
MAX: 22,456,717 | +| sphincs-sha2-128s-simple (10 executions) | clean | AVG: 1,007,731,522
MIN: 1,007,731,504
MAX: 1,007,731,551 | AVG: 7,657,558,168
MIN: 7,657,558,117
MAX: 7,657,558,212 | AVG: 7,471,794
MIN: 7,228,491
MAX: 7,797,915 | +| sphincs-sha2-192f-simple (10 executions) | clean | AVG: 23,570,224
MIN: 23,570,214
MAX: 23,570,257 | AVG: 666,398,438
MIN: 666,398,401
MAX: 666,398,468 | AVG: 35,457,937
MIN: 35,087,854
MAX: 35,973,969 | +| sphincs-sha2-192s-simple (10 executions) | clean | AVG: 1,509,654,951
MIN: 1,509,654,914
MAX: 1,509,654,968 | AVG: 15,452,089,990
MIN: 15,452,089,934
MAX: 15,452,090,071 | AVG: 13,494,855
MIN: 12,947,211
MAX: 14,303,224 | +| sphincs-sha2-256f-simple (10 executions) | clean | AVG: 62,583,556
MIN: 62,583,533
MAX: 62,583,577 | AVG: 1,377,768,608
MIN: 1,377,768,561
MAX: 1,377,768,713 | AVG: 37,302,611
MIN: 36,599,268
MAX: 38,058,007 | +| sphincs-sha2-256s-simple (10 executions) | clean | AVG: 1,001,040,810
MIN: 1,001,040,779
MAX: 1,001,040,845 | AVG: 14,326,202,444
MIN: 14,326,202,404
MAX: 14,326,202,506 | AVG: 19,637,153
MIN: 18,985,943
MAX: 20,132,079 | +| sphincs-shake-128f-simple (10 executions) | clean | AVG: 50,505,025
MIN: 50,505,022
MAX: 50,505,030 | AVG: 1,182,422,563
MIN: 1,182,422,491
MAX: 1,182,422,621 | AVG: 70,501,834
MIN: 68,595,319
MAX: 71,605,565 | +| sphincs-shake-128s-simple (10 executions) | clean | AVG: 3,231,401,965
MIN: 3,231,401,936
MAX: 3,231,402,005 | AVG: 24,553,696,412
MIN: 24,553,696,311
MAX: 24,553,696,516 | AVG: 24,366,771
MIN: 22,962,144
MAX: 25,470,425 | +| sphincs-shake-192f-simple (10 executions) | clean | AVG: 74,890,591
MIN: 74,890,566
MAX: 74,890,617 | AVG: 1,937,690,056
MIN: 1,937,690,000
MAX: 1,937,690,169 | AVG: 103,305,801
MIN: 101,234,011
MAX: 104,969,964 | +| sphincs-shake-192s-simple (10 executions) | clean | AVG: 4,793,551,013
MIN: 4,793,550,980
MAX: 4,793,551,045 | AVG: 43,114,327,277
MIN: 43,114,327,182
MAX: 43,114,327,407 | AVG: 35,026,412
MIN: 33,413,152
MAX: 36,300,013 | +| sphincs-shake-256f-simple (10 executions) | clean | AVG: 200,110,912
MIN: 200,110,878
MAX: 200,110,926 | AVG: 4,026,533,198
MIN: 4,026,533,128
MAX: 4,026,533,250 | AVG: 108,394,619
MIN: 106,138,946
MAX: 111,648,895 | +| sphincs-shake-256s-simple (10 executions) | clean | AVG: 3,201,898,694
MIN: 3,201,898,656
MAX: 3,201,898,741 | AVG: 38,175,697,620
MIN: 38,175,697,525
MAX: 38,175,697,766 | AVG: 52,912,174
MIN: 51,224,772
MAX: 53,979,746 | # Memory Evaluation ## Key Encapsulation Schemes | Scheme | Implementation | Key Generation [bytes] | Encapsulation [bytes] | Decapsulation [bytes] | | ------ | -------------- | ---------------------- | --------------------- | --------------------- | -| bikel1 | m4f | 44,084 | 32,132 | 91,384 | -| bikel1 | opt | 36,000 | 25,908 | 78,588 | -| hqc-rmrs-128 | clean | 48,852 | 64,436 | 71,172 | -| kyber1024 | clean | 15,100 | 18,772 | 20,348 | -| kyber1024 | m4fspeed | 6,400 | 7,496 | 7,512 | -| kyber1024 | m4fstack | 3,296 | 3,368 | 3,392 | -| kyber1024-90s | clean | 15,364 | 19,044 | 20,620 | -| kyber1024-90s | m4fspeed | 7,156 | 8,252 | 8,268 | -| kyber1024-90s | m4fstack | 4,060 | 4,132 | 4,156 | -| kyber512 | clean | 6,116 | 8,780 | 9,556 | -| kyber512 | m4fspeed | 4,320 | 5,424 | 5,432 | -| kyber512 | m4fstack | 2,248 | 2,336 | 2,352 | -| kyber512-90s | clean | 6,572 | 9,236 | 10,012 | -| kyber512-90s | m4fspeed | 5,076 | 6,180 | 6,188 | -| kyber512-90s | m4fstack | 3,012 | 3,100 | 3,116 | -| kyber768 | clean | 10,212 | 13,380 | 14,476 | -| kyber768 | m4fspeed | 5,344 | 6,456 | 6,472 | -| kyber768 | m4fstack | 2,784 | 2,856 | 2,872 | -| kyber768-90s | clean | 10,676 | 13,844 | 14,940 | -| kyber768-90s | m4fspeed | 6,108 | 7,220 | 7,236 | -| kyber768-90s | m4fstack | 3,540 | 3,612 | 3,628 | +| bikel1 | m4f | 43,976 | 32,192 | 91,372 | +| bikel1 | opt | 35,748 | 25,836 | 78,540 | +| bikel3 | m4f | 85,744 | 62,944 | 175,128 | +| bikel3 | opt | 69,444 | 50,556 | 155,388 | +| hqc-128 | clean | 33,644 | 51,428 | 55,892 | +| hqc-192 | clean | 65,668 | 101,636 | 110,660 | +| hqc-256 | clean | 103,756 | 161,508 | 175,972 | +| kyber1024 | clean | 15,136 | 18,784 | 20,360 | +| kyber1024 | m4fspeed | 6,436 | 7,500 | 9,076 | +| kyber1024 | m4fstack | 3,332 | 3,372 | 4,948 | +| kyber512 | clean | 6,168 | 8,800 | 9,576 | +| kyber512 | m4fspeed | 4,364 | 5,436 | 6,212 | +| kyber512 | m4fstack | 2,292 | 2,348 | 3,124 | +| kyber768 | clean | 10,272 | 13,408 | 14,504 | +| kyber768 | m4fspeed | 5,396 | 6,468 | 7,564 | +| kyber768 | m4fstack | 2,820 | 2,860 | 3,956 | ## Signature Schemes | Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | | ------ | -------------- | ---------------------- | ------------ | -------------- | -| dilithium2 | clean | 38,308 | 51,932 | 36,220 | -| dilithium2 | m4f | 38,408 | 49,380 | 36,212 | -| dilithium2aes | clean | 39,776 | 53,400 | 37,688 | -| dilithium3 | clean | 60,844 | 79,588 | 57,732 | -| dilithium3 | m4f | 60,836 | 68,836 | 57,724 | -| dilithium3aes | clean | 62,312 | 81,056 | 59,200 | -| dilithium5 | m4f | 97,692 | 115,932 | 92,788 | -| falcon-1024 | clean | 36,296 | 82,532 | 8,820 | -| falcon-1024 | m4-ct | 1,400 | 2,644 | 412 | -| falcon-1024 | opt-ct | 1,384 | 2,644 | 520 | -| falcon-1024 | opt-leaktime | 1,368 | 2,716 | 412 | -| falcon-512 | clean | 18,416 | 42,508 | 4,724 | -| falcon-512 | m4-ct | 1,312 | 2,556 | 412 | -| falcon-512 | opt-ct | 1,344 | 2,556 | 412 | -| falcon-512 | opt-leaktime | 1,296 | 2,620 | 412 | -| falcon-512-tree | m4-ct | 1,408 | 2,796 | 412 | -| falcon-512-tree | opt-ct | 1,384 | 2,796 | 412 | -| falcon-512-tree | opt-leaktime | 1,344 | 2,804 | 412 | -| sphincs-haraka-128f-robust | clean | 3,636 | 3,728 | 4,188 | -| sphincs-haraka-128f-simple | clean | 3,628 | 3,720 | 4,180 | -| sphincs-haraka-128s-robust | clean | 3,960 | 3,920 | 3,492 | -| sphincs-haraka-128s-simple | clean | 3,872 | 3,912 | 3,484 | -| sphincs-haraka-192f-robust | clean | 5,044 | 5,192 | 5,412 | -| sphincs-haraka-192f-simple | clean | 5,064 | 5,184 | 5,404 | -| sphincs-haraka-192s-robust | clean | 5,392 | 5,352 | 4,748 | -| sphincs-haraka-192s-simple | clean | 5,456 | 5,344 | 4,740 | -| sphincs-haraka-256f-robust | clean | 7,044 | 7,120 | 7,020 | -| sphincs-haraka-256f-simple | clean | 7,036 | 7,032 | 7,012 | -| sphincs-haraka-256s-robust | clean | 7,424 | 7,264 | 6,640 | -| sphincs-haraka-256s-simple | clean | 7,416 | 7,256 | 6,632 | -| sphincs-sha256-128f-robust | clean | 2,276 | 2,340 | 2,828 | -| sphincs-sha256-128f-simple | clean | 2,124 | 2,188 | 2,676 | -| sphincs-sha256-128s-robust | clean | 2,492 | 2,560 | 2,132 | -| sphincs-sha256-128s-simple | clean | 2,340 | 2,408 | 1,980 | -| sphincs-sha256-192f-robust | clean | 3,692 | 3,840 | 4,060 | -| sphincs-sha256-192f-simple | clean | 3,532 | 3,680 | 3,900 | -| sphincs-sha256-192s-robust | clean | 4,004 | 4,000 | 3,396 | -| sphincs-sha256-192s-simple | clean | 3,952 | 3,840 | 3,236 | -| sphincs-sha256-256f-robust | clean | 5,700 | 5,776 | 5,676 | -| sphincs-sha256-256f-simple | clean | 5,532 | 5,500 | 5,508 | -| sphincs-sha256-256s-robust | clean | 6,080 | 5,920 | 5,268 | -| sphincs-sha256-256s-simple | clean | 5,804 | 5,752 | 5,100 | -| sphincs-shake256-128f-robust | clean | 2,036 | 2,200 | 2,580 | -| sphincs-shake256-128f-simple | clean | 2,036 | 2,092 | 2,580 | -| sphincs-shake256-128s-robust | clean | 2,360 | 2,312 | 1,896 | -| sphincs-shake256-128s-simple | clean | 2,360 | 2,312 | 1,884 | -| sphincs-shake256-192f-robust | clean | 3,452 | 3,592 | 3,812 | -| sphincs-shake256-192f-simple | clean | 3,452 | 3,484 | 3,812 | -| sphincs-shake256-192s-robust | clean | 3,872 | 3,752 | 3,148 | -| sphincs-shake256-192s-simple | clean | 3,872 | 3,752 | 3,148 | -| sphincs-shake256-256f-robust | clean | 5,460 | 5,528 | 5,428 | -| sphincs-shake256-256f-simple | clean | 5,460 | 5,528 | 5,428 | -| sphincs-shake256-256s-robust | clean | 5,840 | 5,672 | 5,020 | -| sphincs-shake256-256s-simple | clean | 5,840 | 5,672 | 5,020 | +| aimer-l1-param1 | ref | 10,952 | 187,724 | 196,728 | +| aimer-l1-param2 | ref | 10,952 | 442,668 | 451,672 | +| aimer-l3-param1 | ref | 23,864 | 413,940 | 435,640 | +| ascon-sign-128f-robust | ref | 3,260 | 2,772 | 2,992 | +| ascon-sign-128f-simple | ref | 2,632 | 2,144 | 2,448 | +| ascon-sign-128s-robust | ref | 3,452 | 2,916 | 2,240 | +| ascon-sign-128s-simple | ref | 2,824 | 2,268 | 1,752 | +| ascon-sign-192f-robust | ref | 6,092 | 4,924 | 4,504 | +| ascon-sign-192f-simple | ref | 4,808 | 3,640 | 3,704 | +| ascon-sign-192s-robust | ref | 6,380 | 5,116 | 4,332 | +| ascon-sign-192s-simple | ref | 5,096 | 3,812 | 3,048 | +| biscuit128f | ref | 600 | 137,348 | 14,560 | +| biscuit192f | ref | 640 | 265,964 | 20,796 | +| biscuit256f | ref | 720 | 477,468 | 33,108 | +| cross-sha2-r-sdp-1-fast | ref | 5,200 | 218,304 | 105,604 | +| cross-sha2-r-sdp-3-fast | ref | 9,920 | 324,764 | 158,132 | +| cross-sha2-r-sdpg-1-fast | ref | 2,760 | 130,824 | 69,536 | +| cross-sha2-r-sdpg-1-small | ref | 2,760 | 466,288 | 245,480 | +| cross-sha2-r-sdpg-3-fast | ref | 4,536 | 205,148 | 108,452 | +| cross-sha2-r-sdpg-5-fast | ref | 7,408 | 398,612 | 213,684 | +| cross-sha3-r-sdp-1-fast | ref | 4,672 | 218,400 | 105,576 | +| cross-sha3-r-sdp-3-fast | ref | 9,336 | 324,688 | 157,792 | +| cross-sha3-r-sdpg-1-fast | ref | 2,328 | 130,928 | 69,560 | +| cross-sha3-r-sdpg-1-small | ref | 2,328 | 466,400 | 245,512 | +| cross-sha3-r-sdpg-3-fast | ref | 4,032 | 205,080 | 108,236 | +| cross-sha3-r-sdpg-5-fast | ref | 6,824 | 398,600 | 213,436 | +| dilithium2 | clean | 38,304 | 51,968 | 36,192 | +| dilithium2 | m4f | 38,296 | 49,416 | 36,184 | +| dilithium3 | clean | 60,832 | 79,616 | 57,728 | +| dilithium3 | m4f | 60,824 | 68,864 | 57,720 | +| dilithium5 | clean | 97,696 | 122,724 | 92,940 | +| dilithium5 | m4f | 97,688 | 116,076 | 92,824 | +| falcon-1024 | clean | 34,988 | 84,604 | 8,784 | +| falcon-1024 | m4-ct | 1,156 | 2,508 | 376 | +| falcon-1024 | opt-ct | 1,156 | 2,508 | 376 | +| falcon-1024 | opt-leaktime | 1,212 | 2,580 | 376 | +| falcon-1024-tree | opt-ct | 1,252 | 2,772 | 376 | +| falcon-1024-tree | opt-leaktime | 1,212 | 2,988 | 376 | +| falcon-512 | clean | 18,092 | 43,548 | 4,688 | +| falcon-512 | m4-ct | 1,156 | 2,428 | 376 | +| falcon-512 | opt-ct | 1,156 | 2,428 | 376 | +| falcon-512 | opt-leaktime | 1,156 | 2,492 | 376 | +| falcon-512-tree | m4-ct | 1,212 | 2,636 | 376 | +| falcon-512-tree | opt-ct | 1,156 | 2,636 | 376 | +| falcon-512-tree | opt-leaktime | 1,212 | 2,828 | 376 | +| haetae2 | m4f | 19,756 | 55,568 | 23,296 | +| haetae2 | ref | 26,092 | 54,444 | 29,696 | +| haetae3 | m4f | 29,596 | 83,420 | 31,784 | +| haetae3 | ref | 43,492 | 80,428 | 48,424 | +| haetae5 | m4f | 34,084 | 103,964 | 37,300 | +| haetae5 | ref | 54,868 | 100,228 | 62,024 | +| hawk1024 | ref | 27,972 | 7,980 | 11,468 | +| hawk256 | ref | 7,900 | 3,320 | 3,712 | +| hawk512 | ref | 14,580 | 4,856 | 6,272 | +| mayo1 | m4f | 74,444 | 113,468 | 440,676 | +| mayo1 | ref | 74,444 | 218,644 | 399,348 | +| mayo2 | m4f | 111,532 | 124,644 | 278,444 | +| mayo2 | ref | 111,532 | 238,324 | 270,260 | +| mayo3 | m4f | 244,748 | 340,668 | 469,780 | +| meds13220 | ref | 44,000 | 180,404 | 47,716 | +| meds55604 | ref | 162,196 | 392,852 | 160,324 | +| mirith_IIIa_fast | ref | 21,832 | 266,480 | 46,156 | +| mirith_IIIb_fast | ref | 32,872 | 298,208 | 59,172 | +| mirith_Ia_fast | ref | 10,208 | 122,424 | 22,836 | +| mirith_Ib_fast | ref | 19,064 | 151,016 | 33,764 | +| mirith_Va_fast | ref | 45,000 | 484,464 | 85,252 | +| mirith_Vb_fast | ref | 62,864 | 535,176 | 106,004 | +| mirith_hypercube_IIIa_fast | ref | 21,832 | 167,024 | 42,692 | +| mirith_hypercube_IIIa_short | ref | 21,832 | 486,448 | 56,596 | +| mirith_hypercube_IIIb_fast | ref | 32,872 | 189,520 | 55,244 | +| mirith_hypercube_IIIb_short | ref | 32,872 | 509,056 | 68,632 | +| mirith_hypercube_Ia_fast | opt | 10,216 | 76,944 | 20,864 | +| mirith_hypercube_Ia_fast | ref | 10,208 | 76,944 | 20,864 | +| mirith_hypercube_Ia_short | ref | 10,208 | 217,624 | 31,212 | +| mirith_hypercube_Ib_fast | opt | 19,072 | 96,928 | 31,316 | +| mirith_hypercube_Ib_fast | ref | 19,064 | 96,928 | 31,316 | +| mirith_hypercube_Ib_short | ref | 19,064 | 237,408 | 41,220 | +| mirith_hypercube_Va_fast | ref | 45,000 | 308,440 | 81,056 | +| mirith_hypercube_Vb_fast | ref | 62,864 | 344,832 | 101,220 | +| mqom_cat1_gf251_fast | ref | 184,356 | 399,396 | 252,684 | +| mqom_cat1_gf31_fast | ref | 262,888 | 612,816 | 421,596 | +| ov-Ip | m4f | 15,676 | 5,216 | 2,512 | +| ov-Ip | ref | 15,724 | 12,728 | 6,236 | +| ov-Ip-pkc | m4fspeed | 142,244 | 5,216 | 280,944 | +| ov-Ip-pkc | m4fstack | 142,244 | 5,216 | 6,548 | +| ov-Ip-pkc | ref | 15,724 | 12,728 | 284,560 | +| ov-Ip-pkc-skc | m4fspeed | 380,164 | 243,128 | 281,028 | +| ov-Ip-pkc-skc | m4fstack | 380,164 | 243,128 | 6,548 | +| ov-Ip-pkc-skc | ref | 253,628 | 253,580 | 284,560 | +| perk-128-fast-3 | m4 | 7,696 | 24,020 | 20,684 | +| perk-128-fast-3 | ref | 7,728 | 313,412 | 313,284 | +| perk-128-fast-5 | m4 | 9,032 | 25,160 | 21,752 | +| perk-128-fast-5 | ref | 9,032 | 305,688 | 305,480 | +| perk-128-short-3 | m4 | 7,696 | 27,780 | 25,228 | +| perk-128-short-5 | m4 | 9,032 | 28,616 | 26,056 | +| perk-192-fast-3 | m4 | 14,952 | 47,720 | 41,352 | +| perk-192-fast-5 | m4 | 16,864 | 48,776 | 42,416 | +| perk-192-short-3 | m4 | 14,952 | 51,344 | 46,656 | +| perk-192-short-5 | m4 | 16,864 | 51,888 | 47,256 | +| perk-256-fast-3 | m4 | 25,504 | 80,304 | 69,912 | +| perk-256-fast-5 | m4 | 28,064 | 80,896 | 70,640 | +| perk-256-short-3 | m4 | 25,504 | 82,264 | 74,784 | +| perk-256-short-5 | m4 | 28,064 | 82,056 | 74,808 | +| snova-24-5-16-4-esk | ref | 169,008 | 89,984 | 118,152 | +| snova-24-5-16-4-ssk | ref | 169,008 | 169,104 | 118,152 | +| snova-25-8-16-3-esk | ref | 190,696 | 87,400 | 122,656 | +| snova-25-8-16-3-ssk | ref | 190,696 | 190,836 | 122,656 | +| snova-28-17-16-2-esk | ref | 309,216 | 127,232 | 199,684 | +| snova-28-17-16-2-ssk | ref | 309,216 | 309,356 | 199,684 | +| snova-37-8-16-4-ssk | ref | 640,324 | 640,428 | 411,516 | +| sphincs-a-sha2-128f | ref | 281,168 | 280,772 | 280,656 | +| sphincs-a-sha2-128s | ref | 585,984 | 585,732 | 585,396 | +| sphincs-a-sha2-192f | ref | 504,084 | 502,636 | 502,356 | +| sphincs-a-shake-128f | ref | 281,072 | 280,676 | 280,560 | +| sphincs-a-shake-128s | ref | 585,888 | 585,636 | 585,264 | +| sphincs-a-shake-192f | ref | 503,544 | 502,092 | 501,816 | +| sphincs-sha2-128f-simple | clean | 2,856 | 2,468 | 2,664 | +| sphincs-sha2-128s-simple | clean | 3,084 | 2,556 | 1,968 | +| sphincs-sha2-192f-simple | clean | 5,468 | 4,404 | 4,356 | +| sphincs-sha2-192s-simple | clean | 5,796 | 4,540 | 3,700 | +| sphincs-sha2-256f-simple | clean | 8,460 | 6,412 | 5,980 | +| sphincs-sha2-256s-simple | clean | 8,756 | 6,540 | 5,580 | +| sphincs-shake-128f-simple | clean | 2,760 | 2,372 | 2,568 | +| sphincs-shake-128s-simple | clean | 2,988 | 2,460 | 1,872 | +| sphincs-shake-192f-simple | clean | 4,928 | 3,860 | 3,816 | +| sphincs-shake-192s-simple | clean | 5,252 | 3,996 | 3,160 | +| sphincs-shake-256f-simple | clean | 7,928 | 5,876 | 5,448 | +| sphincs-shake-256s-simple | clean | 8,220 | 6,004 | 5,048 | +| tuov_v | ref | 503,544 | 502,092 | 501,816 | # Hashing Evaluation ## Key Encapsulation Schemes | Scheme | Implementation | Key Generation [%] | Encapsulation [%] | Decapsulation [%] | | ------ | -------------- | ------------------ | ----------------- | ----------------- | -| bikel1 | m4f | 0.7% | 15.1% | 1.0% | -| bikel1 | opt | 0.3% | 10.1% | 0.4% | -| hqc-rmrs-128 | clean | 54.7% | 42.3% | 33.8% | -| kyber1024 | clean | 54.0% | 53.6% | 42.5% | -| kyber1024 | m4fspeed | 79.1% | 81.9% | 75.6% | -| kyber1024 | m4fstack | 78.8% | 81.4% | 75.0% | -| kyber1024-90s | clean | 73.6% | 70.4% | 63.8% | -| kyber1024-90s | m4fspeed | 70.7% | 72.9% | 67.5% | -| kyber1024-90s | m4fstack | 70.2% | 72.2% | 66.8% | -| kyber512 | clean | 54.3% | 51.6% | 36.9% | -| kyber512 | m4fspeed | 79.4% | 82.0% | 72.7% | -| kyber512 | m4fstack | 79.4% | 81.7% | 72.4% | -| kyber512-90s | clean | 68.4% | 62.6% | 52.5% | -| kyber512-90s | m4fspeed | 72.2% | 74.2% | 66.2% | -| kyber512-90s | m4fstack | 72.1% | 73.8% | 65.7% | -| kyber768 | clean | 52.4% | 52.3% | 39.5% | -| kyber768 | m4fspeed | 78.4% | 81.8% | 74.0% | -| kyber768 | m4fstack | 78.3% | 81.3% | 73.5% | -| kyber768-90s | clean | 71.2% | 67.3% | 59.3% | -| kyber768-90s | m4fspeed | 70.6% | 73.1% | 66.5% | -| kyber768-90s | m4fstack | 70.3% | 72.5% | 65.9% | +| bikel1 | m4f | 0.2% | 15.9% | 0.9% | +| bikel1 | opt | 0.1% | 10.1% | 0.4% | +| bikel3 | m4f | 0.1% | 12.2% | 0.7% | +| bikel3 | opt | 0.0% | 6.3% | 0.2% | +| hqc-128 | clean | 0.4% | 0.8% | 0.5% | +| hqc-192 | clean | 0.3% | 0.5% | 0.3% | +| hqc-256 | clean | 0.2% | 0.4% | 0.3% | +| kyber1024 | clean | 49.9% | 45.7% | 38.6% | +| kyber1024 | m4fspeed | 76.1% | 75.9% | 71.0% | +| kyber1024 | m4fstack | 75.8% | 75.2% | 70.4% | +| kyber512 | clean | 49.8% | 41.4% | 32.6% | +| kyber512 | m4fspeed | 76.5% | 74.4% | 67.3% | +| kyber512 | m4fstack | 76.6% | 74.0% | 67.0% | +| kyber768 | clean | 48.4% | 43.2% | 35.4% | +| kyber768 | m4fspeed | 75.4% | 74.9% | 69.1% | +| kyber768 | m4fstack | 75.3% | 74.3% | 68.6% | ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | -| dilithium2 | clean | 68.2% | 38.8% | 61.4% | -| dilithium2 | m4f | 82.8% | 65.5% | 80.5% | -| dilithium2aes | clean | 2.8% | 3.6% | 5.2% | -| dilithium3 | clean | 71.6% | 38.7% | 64.9% | -| dilithium3 | m4f | 85.0% | 64.8% | 82.6% | -| dilithium3aes | clean | 2.3% | 2.4% | 3.7% | -| dilithium5 | m4f | 86.0% | 69.2% | 84.5% | -| falcon-1024 | clean | 8.2% | 0.3% | 26.9% | -| falcon-1024 | m4-ct | 11.0% | 0.5% | 34.0% | -| falcon-1024 | opt-ct | 11.0% | 0.5% | 34.0% | -| falcon-1024 | opt-leaktime | 12.8% | 0.5% | 34.0% | -| falcon-512 | clean | 13.1% | 0.4% | 29.3% | -| falcon-512 | m4-ct | 18.3% | 0.5% | 35.7% | -| falcon-512 | opt-ct | 18.3% | 0.5% | 35.7% | -| falcon-512 | opt-leaktime | 19.6% | 0.6% | 35.8% | -| falcon-512-tree | m4-ct | 15.9% | 1.2% | 35.7% | -| falcon-512-tree | opt-ct | 16.2% | 1.2% | 35.6% | -| falcon-512-tree | opt-leaktime | 16.8% | 1.1% | 35.9% | -| sphincs-haraka-128f-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-128f-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-128s-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-128s-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-192f-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-192f-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-192s-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-192s-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-256f-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-256f-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-256s-robust | clean | 0.0% | 0.0% | 0.0% | -| sphincs-haraka-256s-simple | clean | 0.0% | 0.0% | 0.0% | -| sphincs-sha256-128f-robust | clean | 87.7% | 87.7% | 87.8% | -| sphincs-sha256-128f-simple | clean | 85.3% | 85.2% | 85.1% | -| sphincs-sha256-128s-robust | clean | 87.7% | 87.6% | 87.7% | -| sphincs-sha256-128s-simple | clean | 85.3% | 85.1% | 85.0% | -| sphincs-sha256-192f-robust | clean | 87.2% | 87.4% | 87.6% | -| sphincs-sha256-192f-simple | clean | 84.9% | 85.1% | 85.1% | -| sphincs-sha256-192s-robust | clean | 87.3% | 87.5% | 87.9% | -| sphincs-sha256-192s-simple | clean | 84.9% | 85.2% | 85.6% | -| sphincs-sha256-256f-robust | clean | 90.9% | 91.0% | 91.3% | -| sphincs-sha256-256f-simple | clean | 84.6% | 84.8% | 84.9% | -| sphincs-sha256-256s-robust | clean | 91.1% | 91.1% | 91.6% | -| sphincs-sha256-256s-simple | clean | 84.9% | 85.4% | 85.6% | -| sphincs-shake256-128f-robust | clean | 97.4% | 97.4% | 97.5% | -| sphincs-shake256-128f-simple | clean | 95.7% | 95.7% | 95.7% | -| sphincs-shake256-128s-robust | clean | 97.5% | 97.4% | 97.4% | -| sphincs-shake256-128s-simple | clean | 95.7% | 95.7% | 95.6% | -| sphincs-shake256-192f-robust | clean | 97.4% | 97.3% | 97.4% | -| sphincs-shake256-192f-simple | clean | 95.7% | 95.6% | 95.6% | -| sphincs-shake256-192s-robust | clean | 97.4% | 97.3% | 97.4% | -| sphincs-shake256-192s-simple | clean | 95.7% | 95.6% | 95.6% | -| sphincs-shake256-256f-robust | clean | 97.4% | 97.3% | 97.4% | -| sphincs-shake256-256f-simple | clean | 95.6% | 95.6% | 95.6% | -| sphincs-shake256-256s-robust | clean | 97.4% | 97.2% | 97.4% | -| sphincs-shake256-256s-simple | clean | 95.7% | 95.6% | 95.6% | +| aimer-l1-param1 | ref | 72.0% | 47.2% | 46.7% | +| aimer-l1-param2 | ref | 72.0% | 48.7% | 48.7% | +| aimer-l3-param1 | ref | 77.4% | 41.7% | 41.6% | +| ascon-sign-128f-robust | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-128f-simple | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-128s-robust | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-128s-simple | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-192f-robust | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-192f-simple | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-192s-robust | ref | 0.0% | 0.0% | 0.0% | +| ascon-sign-192s-simple | ref | 0.0% | 0.0% | 0.0% | +| biscuit128f | ref | 54.3% | 9.7% | 8.9% | +| biscuit192f | ref | 54.0% | 6.0% | 5.5% | +| biscuit256f | ref | 54.0% | 4.4% | 4.2% | +| cross-sha2-r-sdp-1-fast | ref | 90.2% | 86.3% | 91.0% | +| cross-sha2-r-sdp-3-fast | ref | 86.5% | 79.8% | 81.7% | +| cross-sha2-r-sdpg-1-fast | ref | 92.9% | 90.9% | 92.1% | +| cross-sha2-r-sdpg-1-small | ref | 92.9% | 90.6% | 92.9% | +| cross-sha2-r-sdpg-3-fast | ref | 90.5% | 87.2% | 86.9% | +| cross-sha2-r-sdpg-5-fast | ref | 88.0% | 83.0% | 82.4% | +| cross-sha3-r-sdp-1-fast | ref | 67.1% | 61.2% | 72.0% | +| cross-sha3-r-sdp-3-fast | ref | 67.7% | 57.5% | 62.4% | +| cross-sha3-r-sdpg-1-fast | ref | 71.8% | 74.8% | 77.1% | +| cross-sha3-r-sdpg-1-small | ref | 71.8% | 74.7% | 78.4% | +| cross-sha3-r-sdpg-3-fast | ref | 71.7% | 68.2% | 68.7% | +| cross-sha3-r-sdpg-5-fast | ref | 71.1% | 66.1% | 66.8% | +| dilithium2 | clean | 60.9% | 30.2% | 52.9% | +| dilithium2 | m4f | 79.9% | 62.2% | 76.8% | +| dilithium3 | clean | 64.7% | 33.8% | 56.8% | +| dilithium3 | m4f | 82.3% | 57.9% | 79.4% | +| dilithium5 | clean | 67.0% | 38.4% | 61.1% | +| dilithium5 | m4f | 83.4% | 63.5% | 81.7% | +| falcon-1024 | clean | 6.5% | 0.3% | 23.7% | +| falcon-1024 | m4-ct | 7.4% | 0.4% | 32.4% | +| falcon-1024 | opt-ct | 11.7% | 0.4% | 32.2% | +| falcon-1024 | opt-leaktime | 12.3% | 0.5% | 32.4% | +| falcon-1024-tree | opt-ct | 5.2% | 0.9% | 32.3% | +| falcon-1024-tree | opt-leaktime | 11.9% | 0.9% | 32.4% | +| falcon-512 | clean | 10.9% | 0.4% | 26.0% | +| falcon-512 | m4-ct | 15.3% | 0.5% | 34.3% | +| falcon-512 | opt-ct | 17.2% | 0.5% | 33.6% | +| falcon-512 | opt-leaktime | 16.0% | 0.5% | 33.8% | +| falcon-512-tree | m4-ct | 18.4% | 1.1% | 33.9% | +| falcon-512-tree | opt-ct | 14.5% | 1.1% | 33.9% | +| falcon-512-tree | opt-leaktime | 18.7% | 1.0% | 33.9% | +| haetae2 | m4f | 12.4% | 56.7% | 54.1% | +| haetae2 | ref | 10.6% | 42.4% | 45.1% | +| haetae3 | m4f | 14.6% | 56.6% | 57.1% | +| haetae3 | ref | 14.4% | 42.4% | 50.3% | +| haetae5 | m4f | 15.7% | 56.6% | 57.5% | +| haetae5 | ref | 15.7% | 42.8% | 54.3% | +| hawk1024 | ref | 1.7% | 49.3% | 8.3% | +| hawk256 | ref | 32.8% | 54.6% | 10.7% | +| hawk512 | ref | 2.6% | 48.7% | 8.6% | +| mayo1 | m4f | 59.5% | 35.0% | 63.0% | +| mayo1 | ref | 39.1% | 17.7% | 49.6% | +| mayo2 | m4f | 35.2% | 35.5% | 81.2% | +| mayo2 | ref | 22.8% | 18.1% | 75.8% | +| mayo3 | m4f | 55.4% | 32.6% | 62.2% | +| meds13220 | ref | 2.5% | 5.1% | 4.8% | +| meds55604 | ref | 1.6% | 3.0% | 2.9% | +| mirith_IIIa_fast | ref | 64.3% | 6.7% | 6.5% | +| mirith_IIIb_fast | ref | 64.5% | 4.7% | 4.6% | +| mirith_Ia_fast | ref | 61.4% | 10.1% | 9.7% | +| mirith_Ib_fast | ref | 61.2% | 6.6% | 6.4% | +| mirith_Va_fast | ref | 64.8% | 4.3% | 4.4% | +| mirith_Vb_fast | ref | 64.5% | 3.1% | 3.2% | +| mirith_hypercube_IIIa_fast | ref | 64.3% | 18.7% | 17.1% | +| mirith_hypercube_IIIa_short | ref | 64.3% | 54.7% | 56.1% | +| mirith_hypercube_IIIb_fast | ref | 64.5% | 13.7% | 12.4% | +| mirith_hypercube_IIIb_short | ref | 64.5% | 47.3% | 48.4% | +| mirith_hypercube_Ia_fast | opt | 78.1% | 51.5% | 49.1% | +| mirith_hypercube_Ia_fast | ref | 61.4% | 26.7% | 24.3% | +| mirith_hypercube_Ia_short | ref | 61.4% | 66.7% | 67.1% | +| mirith_hypercube_Ib_fast | opt | 79.5% | 44.8% | 42.3% | +| mirith_hypercube_Ib_fast | ref | 61.2% | 18.7% | 17.0% | +| mirith_hypercube_Ib_short | ref | 61.2% | 56.6% | 56.8% | +| mirith_hypercube_Va_fast | ref | 64.8% | 13.4% | 12.3% | +| mirith_hypercube_Vb_fast | ref | 64.5% | 11.0% | 10.1% | +| mqom_cat1_gf251_fast | ref | 73.5% | 33.0% | 33.1% | +| mqom_cat1_gf31_fast | ref | 64.6% | 19.8% | 19.2% | +| ov-Ip | m4f | 7.5% | 0.9% | 1.1% | +| ov-Ip | ref | 3.0% | 0.3% | 0.9% | +| ov-Ip-pkc | m4fspeed | 6.4% | 0.9% | 81.5% | +| ov-Ip-pkc | m4fstack | 6.4% | 0.9% | 81.4% | +| ov-Ip-pkc | ref | 3.0% | 0.3% | 80.0% | +| ov-Ip-pkc-skc | m4fspeed | 6.4% | 12.5% | 81.7% | +| ov-Ip-pkc-skc | m4fstack | 6.4% | 12.5% | 81.4% | +| ov-Ip-pkc-skc | ref | 3.0% | 4.7% | 80.7% | +| perk-128-fast-3 | m4 | 68.9% | 67.0% | 71.6% | +| perk-128-fast-3 | ref | 58.8% | 28.4% | 61.5% | +| perk-128-fast-5 | m4 | 62.8% | 65.8% | 70.6% | +| perk-128-fast-5 | ref | 50.5% | 27.2% | 60.1% | +| perk-128-short-3 | m4 | 68.8% | 65.7% | 69.8% | +| perk-128-short-5 | m4 | 62.7% | 64.6% | 68.6% | +| perk-192-fast-3 | m4 | 73.2% | 67.4% | 72.2% | +| perk-192-fast-5 | m4 | 67.7% | 66.5% | 71.3% | +| perk-192-short-3 | m4 | 73.3% | 64.3% | 66.1% | +| perk-192-short-5 | m4 | 67.5% | 63.3% | 64.8% | +| perk-256-fast-3 | m4 | 74.4% | 69.9% | 74.9% | +| perk-256-fast-5 | m4 | 68.2% | 69.1% | 74.1% | +| perk-256-short-3 | m4 | 74.1% | 65.0% | 65.5% | +| perk-256-short-5 | m4 | 68.3% | 63.7% | 64.0% | +| snova-24-5-16-4-esk | ref | 12.2% | 0.0% | 3.4% | +| snova-24-5-16-4-ssk | ref | 12.2% | 1.9% | 3.4% | +| snova-25-8-16-3-esk | ref | 9.6% | 0.1% | 8.0% | +| snova-25-8-16-3-ssk | ref | 9.7% | 3.5% | 8.0% | +| snova-28-17-16-2-esk | ref | 10.6% | 0.2% | 28.1% | +| snova-28-17-16-2-ssk | ref | 10.6% | 10.7% | 28.1% | +| snova-37-8-16-4-ssk | ref | 8.8% | 2.0% | 3.4% | +| sphincs-a-sha2-128f | ref | 43.3% | 86.6% | 48.2% | +| sphincs-a-sha2-128s | ref | 72.9% | 88.3% | 11.7% | +| sphincs-a-sha2-192f | ref | 57.5% | 88.3% | 46.0% | +| sphincs-a-shake-128f | ref | 72.3% | 96.2% | 76.0% | +| sphincs-a-shake-128s | ref | 90.9% | 96.9% | 31.8% | +| sphincs-a-shake-192f | ref | 82.6% | 96.5% | 70.7% | +| sphincs-sha2-128f-simple | clean | 90.8% | 90.7% | 90.6% | +| sphincs-sha2-128s-simple | clean | 90.8% | 90.7% | 90.4% | +| sphincs-sha2-192f-simple | clean | 90.2% | 90.8% | 90.7% | +| sphincs-sha2-192s-simple | clean | 90.3% | 91.1% | 91.5% | +| sphincs-sha2-256f-simple | clean | 90.2% | 90.7% | 90.9% | +| sphincs-sha2-256s-simple | clean | 90.2% | 91.3% | 91.3% | +| sphincs-shake-128f-simple | clean | 97.6% | 97.6% | 97.5% | +| sphincs-shake-128s-simple | clean | 97.6% | 97.6% | 97.5% | +| sphincs-shake-192f-simple | clean | 97.5% | 97.4% | 97.4% | +| sphincs-shake-192s-simple | clean | 97.5% | 97.4% | 97.4% | +| sphincs-shake-256f-simple | clean | 97.5% | 97.4% | 97.4% | +| sphincs-shake-256s-simple | clean | 97.5% | 97.3% | 97.4% | # Size Evaluation ## Key Encapsulation Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | -| bikel1 | m4f | 177,664 | 24 | 49 | 177,737 | -| bikel1 | opt | 34,947 | 24 | 1 | 34,972 | -| hqc-rmrs-128 | clean | 17,116 | 0 | 0 | 17,116 | -| kyber1024 | clean | 6,068 | 0 | 0 | 6,068 | -| kyber1024 | m4fspeed | 16,496 | 0 | 0 | 16,496 | -| kyber1024 | m4fstack | 13,752 | 0 | 0 | 13,752 | -| kyber1024-90s | clean | 6,424 | 0 | 0 | 6,424 | -| kyber1024-90s | m4fspeed | 16,948 | 0 | 0 | 16,948 | -| kyber1024-90s | m4fstack | 13,996 | 0 | 0 | 13,996 | -| kyber512 | clean | 4,872 | 0 | 0 | 4,872 | -| kyber512 | m4fspeed | 15,332 | 0 | 0 | 15,332 | -| kyber512 | m4fstack | 12,820 | 0 | 0 | 12,820 | -| kyber512-90s | clean | 5,088 | 0 | 0 | 5,088 | -| kyber512-90s | m4fspeed | 15,784 | 0 | 0 | 15,784 | -| kyber512-90s | m4fstack | 13,052 | 0 | 0 | 13,052 | -| kyber768 | clean | 4,888 | 0 | 0 | 4,888 | -| kyber768 | m4fspeed | 15,540 | 0 | 0 | 15,540 | -| kyber768 | m4fstack | 12,836 | 0 | 0 | 12,836 | -| kyber768-90s | clean | 5,120 | 0 | 0 | 5,120 | -| kyber768-90s | m4fspeed | 16,000 | 0 | 0 | 16,000 | -| kyber768-90s | m4fstack | 13,068 | 0 | 0 | 13,068 | +| bikel1 | m4f | 181,088 | 24 | 49 | 181,161 | +| bikel1 | opt | 34,451 | 24 | 1 | 34,476 | +| bikel3 | m4f | 198,034 | 24 | 49 | 198,107 | +| bikel3 | opt | 43,091 | 24 | 1 | 43,116 | +| hqc-128 | clean | 18,628 | 0 | 0 | 18,628 | +| hqc-192 | clean | 21,104 | 0 | 0 | 21,104 | +| hqc-256 | clean | 26,260 | 0 | 0 | 26,260 | +| kyber1024 | clean | 6,296 | 0 | 0 | 6,296 | +| kyber1024 | m4fspeed | 16,928 | 0 | 0 | 16,928 | +| kyber1024 | m4fstack | 14,136 | 0 | 0 | 14,136 | +| kyber512 | clean | 5,164 | 0 | 0 | 5,164 | +| kyber512 | m4fspeed | 15,840 | 0 | 0 | 15,840 | +| kyber512 | m4fstack | 13,324 | 0 | 0 | 13,324 | +| kyber768 | clean | 5,168 | 0 | 0 | 5,168 | +| kyber768 | m4fspeed | 16,008 | 0 | 0 | 16,008 | +| kyber768 | m4fstack | 13,332 | 0 | 0 | 13,332 | ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | -| dilithium2 | clean | 7,888 | 0 | 0 | 7,888 | -| dilithium2 | m4f | 18,480 | 0 | 0 | 18,480 | -| dilithium2aes | clean | 14,954 | 0 | 0 | 14,954 | -| dilithium3 | clean | 7,384 | 0 | 0 | 7,384 | -| dilithium3 | m4f | 19,924 | 0 | 0 | 19,924 | -| dilithium3aes | clean | 14,442 | 0 | 0 | 14,442 | -| dilithium5 | m4f | 18,248 | 0 | 0 | 18,248 | -| falcon-1024 | clean | 82,281 | 0 | 0 | 82,281 | -| falcon-1024 | m4-ct | 83,069 | 0 | 79,872 | 162,941 | -| falcon-1024 | opt-ct | 83,069 | 0 | 79,872 | 162,941 | -| falcon-1024 | opt-leaktime | 76,261 | 0 | 79,872 | 156,133 | -| falcon-512 | clean | 82,249 | 0 | 0 | 82,249 | -| falcon-512 | m4-ct | 83,069 | 0 | 39,936 | 123,005 | -| falcon-512 | opt-ct | 83,069 | 0 | 39,936 | 123,005 | -| falcon-512 | opt-leaktime | 76,261 | 0 | 39,936 | 116,197 | -| falcon-512-tree | m4-ct | 82,821 | 0 | 27,648 | 110,469 | -| falcon-512-tree | opt-ct | 82,821 | 0 | 27,648 | 110,469 | -| falcon-512-tree | opt-leaktime | 76,013 | 0 | 27,648 | 103,661 | -| sphincs-haraka-128f-robust | clean | 16,428 | 0 | 0 | 16,428 | -| sphincs-haraka-128f-simple | clean | 16,276 | 0 | 0 | 16,276 | -| sphincs-haraka-128s-robust | clean | 16,700 | 0 | 0 | 16,700 | -| sphincs-haraka-128s-simple | clean | 16,552 | 0 | 0 | 16,552 | -| sphincs-haraka-192f-robust | clean | 16,484 | 0 | 0 | 16,484 | -| sphincs-haraka-192f-simple | clean | 16,300 | 0 | 0 | 16,300 | -| sphincs-haraka-192s-robust | clean | 17,020 | 0 | 0 | 17,020 | -| sphincs-haraka-192s-simple | clean | 16,836 | 0 | 0 | 16,836 | -| sphincs-haraka-256f-robust | clean | 16,868 | 0 | 0 | 16,868 | -| sphincs-haraka-256f-simple | clean | 16,624 | 0 | 0 | 16,624 | -| sphincs-haraka-256s-robust | clean | 17,196 | 0 | 0 | 17,196 | -| sphincs-haraka-256s-simple | clean | 16,952 | 0 | 0 | 16,952 | -| sphincs-sha256-128f-robust | clean | 4,740 | 0 | 0 | 4,740 | -| sphincs-sha256-128f-simple | clean | 4,504 | 0 | 0 | 4,504 | -| sphincs-sha256-128s-robust | clean | 5,012 | 0 | 0 | 5,012 | -| sphincs-sha256-128s-simple | clean | 4,776 | 0 | 0 | 4,776 | -| sphincs-sha256-192f-robust | clean | 5,020 | 0 | 0 | 5,020 | -| sphincs-sha256-192f-simple | clean | 4,668 | 0 | 0 | 4,668 | -| sphincs-sha256-192s-robust | clean | 5,564 | 0 | 0 | 5,564 | -| sphincs-sha256-192s-simple | clean | 5,208 | 0 | 0 | 5,208 | -| sphincs-sha256-256f-robust | clean | 5,488 | 0 | 0 | 5,488 | -| sphincs-sha256-256f-simple | clean | 5,048 | 0 | 0 | 5,048 | -| sphincs-sha256-256s-robust | clean | 5,812 | 0 | 0 | 5,812 | -| sphincs-sha256-256s-simple | clean | 5,368 | 0 | 0 | 5,368 | -| sphincs-shake256-128f-robust | clean | 4,024 | 0 | 0 | 4,024 | -| sphincs-shake256-128f-simple | clean | 3,884 | 0 | 0 | 3,884 | -| sphincs-shake256-128s-robust | clean | 4,296 | 0 | 0 | 4,296 | -| sphincs-shake256-128s-simple | clean | 4,152 | 0 | 0 | 4,152 | -| sphincs-shake256-192f-robust | clean | 4,124 | 0 | 0 | 4,124 | -| sphincs-shake256-192f-simple | clean | 3,952 | 0 | 0 | 3,952 | -| sphincs-shake256-192s-robust | clean | 4,660 | 0 | 0 | 4,660 | -| sphincs-shake256-192s-simple | clean | 4,488 | 0 | 0 | 4,488 | -| sphincs-shake256-256f-robust | clean | 4,520 | 0 | 0 | 4,520 | -| sphincs-shake256-256f-simple | clean | 4,308 | 0 | 0 | 4,308 | -| sphincs-shake256-256s-robust | clean | 4,844 | 0 | 0 | 4,844 | -| sphincs-shake256-256s-simple | clean | 4,636 | 0 | 0 | 4,636 | +| aimer-l1-param1 | ref | 19,302 | 468 | 0 | 19,770 | +| aimer-l1-param2 | ref | 19,894 | 468 | 0 | 20,362 | +| aimer-l3-param1 | ref | 23,398 | 468 | 0 | 23,866 | +| ascon-sign-128f-robust | ref | 17,664 | 0 | 0 | 17,664 | +| ascon-sign-128f-simple | ref | 17,596 | 0 | 0 | 17,596 | +| ascon-sign-128s-robust | ref | 17,972 | 0 | 0 | 17,972 | +| ascon-sign-128s-simple | ref | 17,904 | 0 | 0 | 17,904 | +| ascon-sign-192f-robust | ref | 17,960 | 0 | 0 | 17,960 | +| ascon-sign-192f-simple | ref | 17,912 | 0 | 0 | 17,912 | +| ascon-sign-192s-robust | ref | 18,472 | 0 | 0 | 18,472 | +| ascon-sign-192s-simple | ref | 18,424 | 0 | 0 | 18,424 | +| biscuit128f | ref | 7,580 | 0 | 0 | 7,580 | +| biscuit192f | ref | 7,780 | 0 | 0 | 7,780 | +| biscuit256f | ref | 8,216 | 0 | 0 | 8,216 | +| cross-sha2-r-sdp-1-fast | ref | 14,244 | 0 | 104 | 14,348 | +| cross-sha2-r-sdp-3-fast | ref | 14,744 | 0 | 128 | 14,872 | +| cross-sha2-r-sdpg-1-fast | ref | 18,409 | 0 | 104 | 18,513 | +| cross-sha2-r-sdpg-1-small | ref | 18,674 | 0 | 104 | 18,778 | +| cross-sha2-r-sdpg-3-fast | ref | 19,609 | 0 | 128 | 19,737 | +| cross-sha2-r-sdpg-5-fast | ref | 18,669 | 0 | 152 | 18,821 | +| cross-sha3-r-sdp-1-fast | ref | 14,472 | 0 | 208 | 14,680 | +| cross-sha3-r-sdp-3-fast | ref | 14,884 | 0 | 208 | 15,092 | +| cross-sha3-r-sdpg-1-fast | ref | 18,605 | 0 | 208 | 18,813 | +| cross-sha3-r-sdpg-1-small | ref | 18,846 | 0 | 208 | 19,054 | +| cross-sha3-r-sdpg-3-fast | ref | 19,689 | 0 | 208 | 19,897 | +| cross-sha3-r-sdpg-5-fast | ref | 18,593 | 0 | 208 | 18,801 | +| dilithium2 | clean | 8,064 | 0 | 0 | 8,064 | +| dilithium2 | m4f | 18,596 | 0 | 0 | 18,596 | +| dilithium3 | clean | 7,580 | 0 | 0 | 7,580 | +| dilithium3 | m4f | 20,108 | 0 | 0 | 20,108 | +| dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | +| dilithium5 | m4f | 18,468 | 0 | 0 | 18,468 | +| falcon-1024 | clean | 82,647 | 0 | 0 | 82,647 | +| falcon-1024 | m4-ct | 81,825 | 0 | 79,872 | 161,697 | +| falcon-1024 | opt-ct | 81,825 | 0 | 79,872 | 161,697 | +| falcon-1024 | opt-leaktime | 75,429 | 0 | 79,872 | 155,301 | +| falcon-1024-tree | opt-ct | 81,569 | 0 | 55,296 | 136,865 | +| falcon-1024-tree | opt-leaktime | 75,173 | 0 | 55,296 | 130,469 | +| falcon-512 | clean | 82,611 | 0 | 0 | 82,611 | +| falcon-512 | m4-ct | 81,825 | 0 | 39,936 | 121,761 | +| falcon-512 | opt-ct | 81,825 | 0 | 39,936 | 121,761 | +| falcon-512 | opt-leaktime | 75,429 | 0 | 39,936 | 115,365 | +| falcon-512-tree | m4-ct | 81,569 | 0 | 27,648 | 109,217 | +| falcon-512-tree | opt-ct | 81,569 | 0 | 27,648 | 109,217 | +| falcon-512-tree | opt-leaktime | 75,173 | 0 | 27,648 | 102,821 | +| haetae2 | m4f | 35,708 | 0 | 0 | 35,708 | +| haetae2 | ref | 25,568 | 0 | 0 | 25,568 | +| haetae3 | m4f | 35,936 | 0 | 0 | 35,936 | +| haetae3 | ref | 25,980 | 0 | 0 | 25,980 | +| haetae5 | m4f | 35,692 | 0 | 0 | 35,692 | +| haetae5 | ref | 25,688 | 0 | 0 | 25,688 | +| hawk1024 | ref | 102,031 | 0 | 0 | 102,031 | +| hawk256 | ref | 102,015 | 0 | 0 | 102,015 | +| hawk512 | ref | 102,027 | 0 | 0 | 102,027 | +| mayo1 | m4f | 19,300 | 8 | 0 | 19,308 | +| mayo1 | ref | 26,436 | 8 | 0 | 26,444 | +| mayo2 | m4f | 17,292 | 8 | 0 | 17,300 | +| mayo2 | ref | 24,404 | 8 | 0 | 24,412 | +| mayo3 | m4f | 23,612 | 8 | 0 | 23,620 | +| meds13220 | ref | 16,844 | 0 | 0 | 16,844 | +| meds55604 | ref | 9,012 | 0 | 0 | 9,012 | +| mirith_IIIa_fast | ref | 7,720 | 256 | 0 | 7,976 | +| mirith_IIIb_fast | ref | 7,760 | 256 | 0 | 8,016 | +| mirith_Ia_fast | ref | 7,610 | 256 | 0 | 7,866 | +| mirith_Ib_fast | ref | 7,602 | 256 | 0 | 7,858 | +| mirith_Va_fast | ref | 7,890 | 256 | 0 | 8,146 | +| mirith_Vb_fast | ref | 7,914 | 256 | 0 | 8,170 | +| mirith_hypercube_IIIa_fast | ref | 8,966 | 256 | 0 | 9,222 | +| mirith_hypercube_IIIa_short | ref | 9,139 | 256 | 0 | 9,395 | +| mirith_hypercube_IIIb_fast | ref | 9,002 | 256 | 0 | 9,258 | +| mirith_hypercube_IIIb_short | ref | 9,159 | 256 | 0 | 9,415 | +| mirith_hypercube_Ia_fast | opt | 10,932 | 0 | 0 | 10,932 | +| mirith_hypercube_Ia_fast | ref | 8,844 | 256 | 0 | 9,100 | +| mirith_hypercube_Ia_short | ref | 8,781 | 256 | 0 | 9,037 | +| mirith_hypercube_Ib_fast | opt | 10,908 | 0 | 0 | 10,908 | +| mirith_hypercube_Ib_fast | ref | 8,820 | 256 | 0 | 9,076 | +| mirith_hypercube_Ib_short | ref | 8,825 | 256 | 0 | 9,081 | +| mirith_hypercube_Va_fast | ref | 9,140 | 256 | 0 | 9,396 | +| mirith_hypercube_Vb_fast | ref | 9,160 | 256 | 0 | 9,416 | +| mqom_cat1_gf251_fast | ref | 16,865 | 0 | 0 | 16,865 | +| mqom_cat1_gf31_fast | ref | 23,718 | 0 | 0 | 23,718 | +| ov-Ip | m4f | 118,939 | 0 | 0 | 118,939 | +| ov-Ip | ref | 29,215 | 0 | 0 | 29,215 | +| ov-Ip-pkc | m4fspeed | 119,131 | 0 | 0 | 119,131 | +| ov-Ip-pkc | m4fstack | 119,059 | 0 | 0 | 119,059 | +| ov-Ip-pkc | ref | 29,423 | 0 | 0 | 29,423 | +| ov-Ip-pkc-skc | m4fspeed | 119,175 | 0 | 0 | 119,175 | +| ov-Ip-pkc-skc | m4fstack | 119,103 | 0 | 0 | 119,103 | +| ov-Ip-pkc-skc | ref | 29,467 | 0 | 0 | 29,467 | +| perk-128-fast-3 | m4 | 13,421 | 4 | 0 | 13,425 | +| perk-128-fast-3 | ref | 11,053 | 4 | 0 | 11,057 | +| perk-128-fast-5 | m4 | 13,493 | 4 | 0 | 13,497 | +| perk-128-fast-5 | ref | 11,129 | 4 | 0 | 11,133 | +| perk-128-short-3 | m4 | 26,313 | 4 | 0 | 26,317 | +| perk-128-short-5 | m4 | 26,461 | 4 | 0 | 26,465 | +| perk-192-fast-3 | m4 | 12,253 | 4 | 0 | 12,257 | +| perk-192-fast-5 | m4 | 12,277 | 4 | 0 | 12,281 | +| perk-192-short-3 | m4 | 24,189 | 4 | 0 | 24,193 | +| perk-192-short-5 | m4 | 24,913 | 4 | 0 | 24,917 | +| perk-256-fast-3 | m4 | 12,337 | 4 | 0 | 12,341 | +| perk-256-fast-5 | m4 | 12,337 | 4 | 0 | 12,341 | +| perk-256-short-3 | m4 | 31,905 | 4 | 0 | 31,909 | +| perk-256-short-5 | m4 | 32,989 | 4 | 0 | 32,993 | +| snova-24-5-16-4-esk | ref | 52,132 | 0 | 336 | 52,468 | +| snova-24-5-16-4-ssk | ref | 52,132 | 0 | 336 | 52,468 | +| snova-25-8-16-3-esk | ref | 28,240 | 0 | 299 | 28,539 | +| snova-25-8-16-3-ssk | ref | 28,240 | 0 | 299 | 28,539 | +| snova-28-17-16-2-esk | ref | 16,436 | 0 | 280 | 16,716 | +| snova-28-17-16-2-ssk | ref | 16,436 | 0 | 280 | 16,716 | +| snova-37-8-16-4-ssk | ref | 52,440 | 0 | 336 | 52,776 | +| sphincs-a-sha2-128f | ref | 6,343 | 0 | 0 | 6,343 | +| sphincs-a-sha2-128s | ref | 6,899 | 0 | 0 | 6,899 | +| sphincs-a-sha2-192f | ref | 6,867 | 0 | 0 | 6,867 | +| sphincs-a-shake-128f | ref | 5,552 | 0 | 0 | 5,552 | +| sphincs-a-shake-128s | ref | 6,108 | 0 | 0 | 6,108 | +| sphincs-a-shake-192f | ref | 5,916 | 0 | 0 | 5,916 | +| sphincs-sha2-128f-simple | clean | 4,956 | 0 | 0 | 4,956 | +| sphincs-sha2-128s-simple | clean | 5,264 | 0 | 0 | 5,264 | +| sphincs-sha2-192f-simple | clean | 5,444 | 0 | 0 | 5,444 | +| sphincs-sha2-192s-simple | clean | 5,968 | 0 | 0 | 5,968 | +| sphincs-sha2-256f-simple | clean | 5,728 | 0 | 0 | 5,728 | +| sphincs-sha2-256s-simple | clean | 6,084 | 0 | 0 | 6,084 | +| sphincs-shake-128f-simple | clean | 4,184 | 0 | 0 | 4,184 | +| sphincs-shake-128s-simple | clean | 4,492 | 0 | 0 | 4,492 | +| sphincs-shake-192f-simple | clean | 4,472 | 0 | 0 | 4,472 | +| sphincs-shake-192s-simple | clean | 4,984 | 0 | 0 | 4,984 | +| sphincs-shake-256f-simple | clean | 4,720 | 0 | 0 | 4,720 | +| sphincs-shake-256s-simple | clean | 5,076 | 0 | 0 | 5,076 | From 5d0fe862d26b1726c1c986fb612e027195486007 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 20 Mar 2024 11:13:23 +0800 Subject: [PATCH 082/107] Adds Apache-2.0 license in addition to CC0 To enable re-use in https://github.com/pq-code-package/mlkem-c-embedded. This is applied only to the sources of pqm4 itself that are to a vast degree written by the pqm4 maintainers. The scheme implementations plus symmetric primitives have other licenses. --- Makefile | 1 + README.md | 3 ++- benchmarks.py | 1 + build_everything.py | 1 + common/aes.c | 1 + common/aes.h | 1 + common/hal-mps2.c | 1 + common/hal-opencm3.c | 1 + common/keccaktest.c | 1 + common/randombytes.c | 1 + common/test.c | 1 + convert_benchmarks.py | 1 + interface.py | 1 + mk/config.mk | 1 + mk/crypto.mk | 1 + mk/cw308t-stm32f3.mk | 1 + mk/cw308t-stm32f415.mk | 1 + mk/mps2-an386.mk | 1 + mk/nucleo-l476rg.mk | 1 + mk/nucleo-l4r5zi.mk | 1 + mk/opencm3.mk | 1 + mk/stm32f4discovery.mk | 1 + mk/tests.mk | 1 + mupq | 2 +- st_nucleo_l4r5.cfg | 2 ++ test.py | 1 + testvectors.py | 1 + 27 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2a321c01..a3f49c35 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 .PHONY: all all: tests tests-bin diff --git a/README.md b/README.md index 082dce55..3fff71bf 100644 --- a/README.md +++ b/README.md @@ -406,5 +406,6 @@ Each subdirectory containing implementations contains a LICENSE or COPYING file under what license that specific implementation is released. The files in common contain licensing information at the top of the file (and are currently either public domain or MIT). -All other code in this repository is released under the conditions of [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +All other code in this repository is dual-licensed under [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) and under the conditions of [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/benchmarks.py b/benchmarks.py index 5895fc0e..f1b91181 100755 --- a/benchmarks.py +++ b/benchmarks.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 from mupq import mupq from interface import parse_arguments, get_platform import sys diff --git a/build_everything.py b/build_everything.py index 16bae738..21947895 100755 --- a/build_everything.py +++ b/build_everything.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 """ Builds all of the binaries without flashing them. """ diff --git a/common/aes.c b/common/aes.c index aab280eb..ff84540c 100644 --- a/common/aes.c +++ b/common/aes.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include #include #include "aes.h" diff --git a/common/aes.h b/common/aes.h index f4586589..49e9433b 100644 --- a/common/aes.h +++ b/common/aes.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #ifndef AES_H #define AES_H diff --git a/common/hal-mps2.c b/common/hal-mps2.c index eefa6440..62e1924b 100644 --- a/common/hal-mps2.c +++ b/common/hal-mps2.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include #include diff --git a/common/hal-opencm3.c b/common/hal-opencm3.c index ec80ad01..05d7377a 100644 --- a/common/hal-opencm3.c +++ b/common/hal-opencm3.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include "hal.h" #include diff --git a/common/keccaktest.c b/common/keccaktest.c index 05d13381..389bb9cf 100644 --- a/common/keccaktest.c +++ b/common/keccaktest.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include "randombytes.h" #include #include diff --git a/common/randombytes.c b/common/randombytes.c index 386059d9..ba60a120 100644 --- a/common/randombytes.c +++ b/common/randombytes.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include "randombytes.h" #if defined(STM32F2) || defined(STM32F4) || defined(STM32L4R5ZI) && !defined(MPS2_AN386) diff --git a/common/test.c b/common/test.c index 987d12d2..1a24c275 100644 --- a/common/test.c +++ b/common/test.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 or CC0-1.0 #include #include #include diff --git a/convert_benchmarks.py b/convert_benchmarks.py index 13e7a038..6d9667f3 100755 --- a/convert_benchmarks.py +++ b/convert_benchmarks.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 import sys from mupq import mupq diff --git a/interface.py b/interface.py index 2b386caf..76d4e7af 100644 --- a/interface.py +++ b/interface.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 import argparse from mupq import mupq diff --git a/mk/config.mk b/mk/config.mk index 53740a84..85fc9145 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 CPPFLAGS += \ -DPQM4 diff --git a/mk/crypto.mk b/mk/crypto.mk index 4c6904b3..7aae6b10 100644 --- a/mk/crypto.mk +++ b/mk/crypto.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 SYMCRYPTO_SRC = \ mupq/common/fips202.c \ mupq/common/sp800-185.c \ diff --git a/mk/cw308t-stm32f3.mk b/mk/cw308t-stm32f3.mk index 7aa3d846..5cb9a678 100644 --- a/mk/cw308t-stm32f3.mk +++ b/mk/cw308t-stm32f3.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 DEVICE=stm32f303rct7 OPENCM3_TARGET=lib/stm32/f3 diff --git a/mk/cw308t-stm32f415.mk b/mk/cw308t-stm32f415.mk index c148f5c0..aeb98deb 100644 --- a/mk/cw308t-stm32f415.mk +++ b/mk/cw308t-stm32f415.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 DEVICE=stm32f415rgt6 OPENCM3_TARGET=lib/stm32/f4 diff --git a/mk/mps2-an386.mk b/mk/mps2-an386.mk index 48914751..0412d861 100644 --- a/mk/mps2-an386.mk +++ b/mk/mps2-an386.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 EXCLUDED_SCHEMES = \ mupq/crypto_sign/tuov_v/ref% diff --git a/mk/nucleo-l476rg.mk b/mk/nucleo-l476rg.mk index 62349b53..9cdebc35 100644 --- a/mk/nucleo-l476rg.mk +++ b/mk/nucleo-l476rg.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 DEVICE=stm32l476rg OPENCM3_TARGET=lib/stm32/l4 diff --git a/mk/nucleo-l4r5zi.mk b/mk/nucleo-l4r5zi.mk index b0d30fea..b41cc24a 100644 --- a/mk/nucleo-l4r5zi.mk +++ b/mk/nucleo-l4r5zi.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 DEVICE=stm32l4r5zi OPENCM3_TARGET=lib/stm32/l4 diff --git a/mk/opencm3.mk b/mk/opencm3.mk index fbcd2428..6e07c71c 100644 --- a/mk/opencm3.mk +++ b/mk/opencm3.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 LIBHAL_SRC := \ common/hal-opencm3.c \ common/randombytes.c diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 2b10ef4b..76426d99 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 DEVICE=stm32f407vg OPENCM3_TARGET=lib/stm32/f4 diff --git a/mk/tests.mk b/mk/tests.mk index 40923ab8..8b6aab8a 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 ifeq ($(AIO),1) elf/boardtest.elf: common/test.c $(LINKDEPS) $(CONFIG) $(compiletest) diff --git a/mupq b/mupq index 66102a0c..a165f5d4 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 66102a0c237849e7c88adb88cfa4934b398a3a0b +Subproject commit a165f5d48c011e2647065ec7ad84cec3314b3375 diff --git a/st_nucleo_l4r5.cfg b/st_nucleo_l4r5.cfg index 830c1659..be4fffd5 100644 --- a/st_nucleo_l4r5.cfg +++ b/st_nucleo_l4r5.cfg @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 + # This is for STM32L4R5 Nucleo Dev Boards. source [find interface/stlink-dap.cfg] diff --git a/test.py b/test.py index 2d6686af..969282b5 100755 --- a/test.py +++ b/test.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 from mupq import mupq from interface import parse_arguments, get_platform diff --git a/testvectors.py b/testvectors.py index 2424a483..a08c1510 100755 --- a/testvectors.py +++ b/testvectors.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 or CC0-1.0 from mupq import mupq from interface import parse_arguments, get_platform import sys From 82c6d7aea48b511b7e0ac10523cadcc0aa6a1676 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 25 Mar 2024 15:59:12 -0400 Subject: [PATCH 083/107] add uov to exluded schemes on nucleo_l446rg.mk --- mk/nucleo-l476rg.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mk/nucleo-l476rg.mk b/mk/nucleo-l476rg.mk index 62349b53..680fb8b1 100644 --- a/mk/nucleo-l476rg.mk +++ b/mk/nucleo-l476rg.mk @@ -3,6 +3,7 @@ OPENCM3_TARGET=lib/stm32/l4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ - mupq/crypto_sign/falcon-1024-tree% + mupq/crypto_sign/falcon-1024-tree% \ + crypto_sign/ov-Ip% include mk/opencm3.mk From 0c1277737aaae5cfadfab4d8e4e2214bd42e0d6b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 26 Mar 2024 09:32:23 -0400 Subject: [PATCH 084/107] more CI --- .github/workflows/main.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5824dfbe..4fc8b0c5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,5 +16,15 @@ jobs: uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 with: release: 13.2.Rel1 - - name: Build All - run: make PLATFORM=mps2-an386 -j2 + - name: Build All (stm32f4discovery) + run: make PLATFORM=stm32f4discovery -j2 + - name: Build All (nucleo-l476rg) + run: make PLATFORM=nucleo-l476rg -j2 + - name: Build All (nucleo-l4r5zi) + run: make PLATFORM=nucleo-l4r5zi -j2 + - name: Build All (cw308t-stm32f3) + run: make PLATFORM=cw308t-stm32f3 -j2 + - name: Build All (cw308t-stm32f415) + run: make PLATFORM=cw308t-stm32f415 -j2 + - name: Build All (mps2-an386) + run: make PLATFORM=mps2-an386 -j2 \ No newline at end of file From c83565b36f613777bb21201b6b0ecf4441e4e3f2 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 26 Mar 2024 09:42:01 -0400 Subject: [PATCH 085/107] more CI --- .github/workflows/cw308t-stm32f3.yml | 21 ++++++++++++++++++ .github/workflows/cw308t-stm32f415.yml | 21 ++++++++++++++++++ .github/workflows/main.yml | 30 -------------------------- .github/workflows/mps2-an386.yml | 21 ++++++++++++++++++ .github/workflows/nucleo-l476rg.yml | 21 ++++++++++++++++++ .github/workflows/nucleo-l4r5zi.yml | 21 ++++++++++++++++++ .github/workflows/stm32f4discovery.yml | 21 ++++++++++++++++++ 7 files changed, 126 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/cw308t-stm32f3.yml create mode 100644 .github/workflows/cw308t-stm32f415.yml delete mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/mps2-an386.yml create mode 100644 .github/workflows/nucleo-l476rg.yml create mode 100644 .github/workflows/nucleo-l4r5zi.yml create mode 100644 .github/workflows/stm32f4discovery.yml diff --git a/.github/workflows/cw308t-stm32f3.yml b/.github/workflows/cw308t-stm32f3.yml new file mode 100644 index 00000000..a084d441 --- /dev/null +++ b/.github/workflows/cw308t-stm32f3.yml @@ -0,0 +1,21 @@ +name: cw308t-stm32f3 build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (cw308t-stm32f3) + run: make PLATFORM=cw308t-stm32f3 -j2 diff --git a/.github/workflows/cw308t-stm32f415.yml b/.github/workflows/cw308t-stm32f415.yml new file mode 100644 index 00000000..17180c87 --- /dev/null +++ b/.github/workflows/cw308t-stm32f415.yml @@ -0,0 +1,21 @@ +name: cw308t-stm32f415 build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (cw308t-stm32f415) + run: make PLATFORM=cw308t-stm32f415 -j2 \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 4fc8b0c5..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,30 +0,0 @@ -on: - push: - branches: - - master - pull_request: - types: [review_requested] -jobs: - build-all: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Install Toolchain - uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 - with: - release: 13.2.Rel1 - - name: Build All (stm32f4discovery) - run: make PLATFORM=stm32f4discovery -j2 - - name: Build All (nucleo-l476rg) - run: make PLATFORM=nucleo-l476rg -j2 - - name: Build All (nucleo-l4r5zi) - run: make PLATFORM=nucleo-l4r5zi -j2 - - name: Build All (cw308t-stm32f3) - run: make PLATFORM=cw308t-stm32f3 -j2 - - name: Build All (cw308t-stm32f415) - run: make PLATFORM=cw308t-stm32f415 -j2 - - name: Build All (mps2-an386) - run: make PLATFORM=mps2-an386 -j2 \ No newline at end of file diff --git a/.github/workflows/mps2-an386.yml b/.github/workflows/mps2-an386.yml new file mode 100644 index 00000000..c1ce929c --- /dev/null +++ b/.github/workflows/mps2-an386.yml @@ -0,0 +1,21 @@ +name: mps2-an386 build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (mps2-an386) + run: make PLATFORM=mps2-an386 -j2 \ No newline at end of file diff --git a/.github/workflows/nucleo-l476rg.yml b/.github/workflows/nucleo-l476rg.yml new file mode 100644 index 00000000..0c284a24 --- /dev/null +++ b/.github/workflows/nucleo-l476rg.yml @@ -0,0 +1,21 @@ +name: nucleo-l476rg build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (nucleo-l476rg) + run: make PLATFORM=nucleo-l476rg -j2 \ No newline at end of file diff --git a/.github/workflows/nucleo-l4r5zi.yml b/.github/workflows/nucleo-l4r5zi.yml new file mode 100644 index 00000000..7af21121 --- /dev/null +++ b/.github/workflows/nucleo-l4r5zi.yml @@ -0,0 +1,21 @@ +name: nucleo-l4r5zi build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (nucleo-l4r5zi) + run: make PLATFORM=nucleo-l4r5zi -j2 \ No newline at end of file diff --git a/.github/workflows/stm32f4discovery.yml b/.github/workflows/stm32f4discovery.yml new file mode 100644 index 00000000..6a5030b1 --- /dev/null +++ b/.github/workflows/stm32f4discovery.yml @@ -0,0 +1,21 @@ +name: stm32f4discovery build +on: + push: + branches: + - master + pull_request: + branches: [ "master" ] +jobs: + build-all: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install Toolchain + uses: carlosperate/arm-none-eabi-gcc-action@v1.8.0 + with: + release: 13.2.Rel1 + - name: Build All (stm32f4discovery) + run: make PLATFORM=stm32f4discovery -j2 \ No newline at end of file From c33fab9dc0498f9a6583c509192b26759b3694cd Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 26 Mar 2024 09:56:42 -0400 Subject: [PATCH 086/107] fix nucleo-l476rg build --- mk/nucleo-l476rg.mk | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mk/nucleo-l476rg.mk b/mk/nucleo-l476rg.mk index 680fb8b1..8f07c804 100644 --- a/mk/nucleo-l476rg.mk +++ b/mk/nucleo-l476rg.mk @@ -3,7 +3,18 @@ OPENCM3_TARGET=lib/stm32/l4 EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ + mupq/crypto_sign/ov-Ip% \ mupq/crypto_sign/falcon-1024-tree% \ - crypto_sign/ov-Ip% - + mupq/crypto_sign/snova-43-25-16-2-esk% \ + mupq/crypto_sign/snova-61-33-16-2-esk% \ + mupq/crypto_sign/snova-60-10-16-4-esk% \ + mupq/crypto_sign/snova-66-15-16-3-esk% \ + mupq/crypto_sign/snova-49-11-16-3-esk% \ + mupq/crypto_sign/snova-37-8-16-4-esk% \ + mupq/crypto_sign/meds55604% \ + mupq/crypto_sign/meds167717% \ + mupq/crypto_sign/meds134180% \ + mupq/crypto_sign/tuov% \ + crypto_sign/ov-Ip% \ + include mk/opencm3.mk From cc3481a10e1205c2a879bd9944cf809344630a86 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 26 Mar 2024 17:09:22 -0400 Subject: [PATCH 087/107] fix build for other platforms --- mk/cw308t-stm32f3.mk | 32 ++++++++++++++++++++++++++++---- mk/cw308t-stm32f415.mk | 4 ++++ mk/stm32f4discovery.mk | 9 +++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/mk/cw308t-stm32f3.mk b/mk/cw308t-stm32f3.mk index 7aa3d846..db6444f6 100644 --- a/mk/cw308t-stm32f3.mk +++ b/mk/cw308t-stm32f3.mk @@ -2,13 +2,37 @@ DEVICE=stm32f303rct7 OPENCM3_TARGET=lib/stm32/f3 EXCLUDED_SCHEMES = \ - mupq/pqclean/crypto_sign/sphincs-haraka-256f% \ - mupq/pqclean/crypto_sign/sphincs-shake256-256f% \ - mupq/pqclean/crypto_sign/sphincs-sha256-256f% \ + mupq/pqclean/crypto_sign/sphincs-shake-256f% \ + mupq/pqclean/crypto_sign/sphincs-sha2-256f% \ mupq/pqclean/crypto_kem/mceliece% \ mupq/crypto_sign/falcon-1024% \ mupq/crypto_sign/falcon-512% \ + mupq/crypto_sign/tuov_is% \ + mupq/crypto_sign/tuov_ip% \ + mupq/crypto_sign/tuov_iii% \ + mupq/crypto_sign/tuov_v% \ + mupq/crypto_sign/snova-43-25-16-2% \ + mupq/crypto_sign/snova-61-33-16-2% \ + mupq/crypto_sign/snova-25-8-16-3% \ + mupq/crypto_sign/snova-60-10-16-4% \ + mupq/crypto_sign/snova-66-15-16-3% \ + mupq/crypto_sign/snova-49-11-16-3% \ + mupq/crypto_sign/snova-28-17-16-2% \ + mupq/crypto_sign/snova-37-8-16-4% \ + mupq/crypto_sign/sphincs-a-sha2-256f% \ + mupq/crypto_sign/sphincs-a-shake-256f% \ + mupq/crypto_sign/ov-Ip% \ + mupq/crypto_sign/cross-sha2-r-sdp-5-small% \ + mupq/crypto_sign/cross-sha3-r-sdp-5-small% \ + mupq/crypto_sign/cross-sha2-r-sdp-5-fast% \ + mupq/crypto_sign/cross-sha3-r-sdp-5-fast% \ + mupq/crypto_sign/meds55604% \ + mupq/crypto_sign/meds41711% \ + mupq/crypto_sign/meds167717% \ + mupq/crypto_sign/meds134180% \ + mupq/crypto_sign/mirith_hypercube_Ia% \ crypto_sign/falcon-1024% \ - crypto_sign/falcon-512% + crypto_sign/falcon-512% \ + crypto_sign/ov-Ip% \ include mk/opencm3.mk diff --git a/mk/cw308t-stm32f415.mk b/mk/cw308t-stm32f415.mk index c148f5c0..fddb05a7 100644 --- a/mk/cw308t-stm32f415.mk +++ b/mk/cw308t-stm32f415.mk @@ -7,6 +7,10 @@ EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_sign/sphincs-shake256-256f% \ mupq/pqclean/crypto_sign/sphincs-sha256-256f% \ mupq/crypto_sign/ov-Ip% \ + mupq/crypto_sign/tuov_is% \ + mupq/crypto_sign/tuov_ip% \ + mupq/crypto_sign/tuov_iii% \ + mupq/crypto_sign/tuov_v% \ crypto_sign/ov-Ip% \ mupq/crypto_sign/falcon-1024% \ mupq/crypto_sign/falcon-512% \ diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index 2b10ef4b..375b9217 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -5,6 +5,15 @@ EXCLUDED_SCHEMES = \ mupq/pqclean/crypto_kem/mceliece% \ mupq/crypto_sign/tuov% \ mupq/crypto_sign/ov-Ip% \ + mupq/crypto_sign/snova-43-25-16-2-esk% \ + mupq/crypto_sign/snova-61-33-16-2-esk% \ + mupq/crypto_sign/snova-60-10-16-4-esk% \ + mupq/crypto_sign/snova-66-15-16-3-esk% \ + mupq/crypto_sign/snova-49-11-16-3-esk% \ + mupq/crypto_sign/snova-37-8-16-4-esk% \ + mupq/crypto_sign/meds55604% \ + mupq/crypto_sign/meds167717% \ + mupq/crypto_sign/meds134180% \ crypto_sign/ov-Ip% \ mupq/crypto_sign/falcon-1024-tree% From 9c2bc412b0b2537437cd56ff3dc5a29c7a048480 Mon Sep 17 00:00:00 2001 From: Huang Junhao <1561868283@qq.com> Date: Mon, 15 Apr 2024 15:30:22 +0800 Subject: [PATCH 088/107] Revisiting Keccak and Dilithium Implementations on ARMv7-M (#338) * Use Plantard arithmetic for NTT_769 in Dilithium * rm old smallntt.S * update benchmarks --------- Co-authored-by: Matthias J. Kannwischer --- benchmarks.csv | 10 +- benchmarks.md | 10 +- crypto_sign/dilithium3/m4f/macros_fnt.i | 1 - crypto_sign/dilithium3/m4f/macros_smallntt.i | 98 +++ crypto_sign/dilithium3/m4f/smallntt.S | 837 ------------------- crypto_sign/dilithium3/m4f/smallntt.h | 85 +- crypto_sign/dilithium3/m4f/smallntt_769.S | 681 +++++++++++++++ 7 files changed, 829 insertions(+), 893 deletions(-) delete mode 120000 crypto_sign/dilithium3/m4f/macros_fnt.i create mode 100644 crypto_sign/dilithium3/m4f/macros_smallntt.i delete mode 100644 crypto_sign/dilithium3/m4f/smallntt.S create mode 100644 crypto_sign/dilithium3/m4f/smallntt_769.S diff --git a/benchmarks.csv b/benchmarks.csv index 9270fca8..981accb6 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -44,8 +44,8 @@ cross-sha3-r-sdpg-3-fast (10 executions),ref,627948,625525,637639,43573841,43565 cross-sha3-r-sdpg-5-fast (10 executions),ref,1146280,1142409,1153794,93557878,93547167,93566329,59948216,59857434,60043852 dilithium2 (90 executions),clean,1873447,1838554,1903845,7846622,3321671,28761609,2062804,2062332,2063181 dilithium2 (100 executions),m4f,1427684,1390524,1466437,4219137,1813668,12587382,1417706,1417251,1418128 -dilithium3 (90 executions),clean,3205542,3204354,3206592,12108503,5097440,50759276,3377010,3376729,3377395 -dilithium3 (100 executions),m4f,2515970,2514894,2516922,5896583,2935265,23718896,2411234,2410948,2411551 +dilithium3 (1000 executions),clean,3205551,3204090,3207411,12696585,5097364,74392293,3376992,3376581,3377393 +dilithium3 (1000 executions),m4f,2515969,2514498,2517634,5884832,2917322,25268693,2411257,2410858,2411717 dilithium5 (90 executions),clean,5346066,5287239,5395626,15205929,7953360,49173429,5609664,5609137,5610119 dilithium5 (100 executions),m4f,4273211,4210308,4329697,8062110,4882708,18398575,4185407,4184878,4185954 falcon-1024 (10 executions),m4-ct,354880005,284902033,635131652,87741288,87506676,87922628,991320,982548,997219 @@ -341,8 +341,8 @@ cross-sha3-r-sdpg-3-fast,ref,71.7,68.2,68.7,,,,,, cross-sha3-r-sdpg-5-fast,ref,71.1,66.1,66.8,,,,,, dilithium2,clean,60.9,30.2,52.9,,,,,, dilithium2,m4f,79.9,62.2,76.8,,,,,, -dilithium3,clean,64.7,33.8,56.8,,,,,, -dilithium3,m4f,82.3,57.9,79.4,,,,,, +dilithium3,clean,64.7,31.3,56.8,,,,,, +dilithium3,m4f,82.3,60.3,79.4,,,,,, dilithium5,clean,67.0,38.4,61.1,,,,,, dilithium5,m4f,83.4,63.5,81.7,,,,,, falcon-1024,clean,6.5,0.3,23.7,,,,,, @@ -491,7 +491,7 @@ cross-sha3-r-sdpg-5-fast,ref,18593,0,208,18801,,,,, dilithium2,clean,8064,0,0,8064,,,,, dilithium2,m4f,18596,0,0,18596,,,,, dilithium3,clean,7580,0,0,7580,,,,, -dilithium3,m4f,20108,0,0,20108,,,,, +dilithium3,m4f,18588,0,0,18588,,,,, dilithium5,clean,7808,0,0,7808,,,,, dilithium5,m4f,18468,0,0,18468,,,,, falcon-1024,clean,82647,0,0,82647,,,,, diff --git a/benchmarks.md b/benchmarks.md index e2b4a4e3..5574fe2c 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -46,8 +46,8 @@ | cross-sha3-r-sdpg-5-fast (10 executions) | ref | AVG: 1,146,280
MIN: 1,142,409
MAX: 1,153,794 | AVG: 93,557,878
MIN: 93,547,167
MAX: 93,566,329 | AVG: 59,948,216
MIN: 59,857,434
MAX: 60,043,852 | | dilithium2 (90 executions) | clean | AVG: 1,873,447
MIN: 1,838,554
MAX: 1,903,845 | AVG: 7,846,622
MIN: 3,321,671
MAX: 28,761,609 | AVG: 2,062,804
MIN: 2,062,332
MAX: 2,063,181 | | dilithium2 (100 executions) | m4f | AVG: 1,427,684
MIN: 1,390,524
MAX: 1,466,437 | AVG: 4,219,137
MIN: 1,813,668
MAX: 12,587,382 | AVG: 1,417,706
MIN: 1,417,251
MAX: 1,418,128 | -| dilithium3 (90 executions) | clean | AVG: 3,205,542
MIN: 3,204,354
MAX: 3,206,592 | AVG: 12,108,503
MIN: 5,097,440
MAX: 50,759,276 | AVG: 3,377,010
MIN: 3,376,729
MAX: 3,377,395 | -| dilithium3 (100 executions) | m4f | AVG: 2,515,970
MIN: 2,514,894
MAX: 2,516,922 | AVG: 5,896,583
MIN: 2,935,265
MAX: 23,718,896 | AVG: 2,411,234
MIN: 2,410,948
MAX: 2,411,551 | +| dilithium3 (1000 executions) | clean | AVG: 3,205,551
MIN: 3,204,090
MAX: 3,207,411 | AVG: 12,696,585
MIN: 5,097,364
MAX: 74,392,293 | AVG: 3,376,992
MIN: 3,376,581
MAX: 3,377,393 | +| dilithium3 (1000 executions) | m4f | AVG: 2,515,969
MIN: 2,514,498
MAX: 2,517,634 | AVG: 5,884,832
MIN: 2,917,322
MAX: 25,268,693 | AVG: 2,411,257
MIN: 2,410,858
MAX: 2,411,717 | | dilithium5 (90 executions) | clean | AVG: 5,346,066
MIN: 5,287,239
MAX: 5,395,626 | AVG: 15,205,929
MIN: 7,953,360
MAX: 49,173,429 | AVG: 5,609,664
MIN: 5,609,137
MAX: 5,610,119 | | dilithium5 (100 executions) | m4f | AVG: 4,273,211
MIN: 4,210,308
MAX: 4,329,697 | AVG: 8,062,110
MIN: 4,882,708
MAX: 18,398,575 | AVG: 4,185,407
MIN: 4,184,878
MAX: 4,185,954 | | falcon-1024 (10 executions) | m4-ct | AVG: 354,880,005
MIN: 284,902,033
MAX: 635,131,652 | AVG: 87,741,288
MIN: 87,506,676
MAX: 87,922,628 | AVG: 991,320
MIN: 982,548
MAX: 997,219 | @@ -347,8 +347,8 @@ | cross-sha3-r-sdpg-5-fast | ref | 71.1% | 66.1% | 66.8% | | dilithium2 | clean | 60.9% | 30.2% | 52.9% | | dilithium2 | m4f | 79.9% | 62.2% | 76.8% | -| dilithium3 | clean | 64.7% | 33.8% | 56.8% | -| dilithium3 | m4f | 82.3% | 57.9% | 79.4% | +| dilithium3 | clean | 64.7% | 31.3% | 56.8% | +| dilithium3 | m4f | 82.3% | 60.3% | 79.4% | | dilithium5 | clean | 67.0% | 38.4% | 61.1% | | dilithium5 | m4f | 83.4% | 63.5% | 81.7% | | falcon-1024 | clean | 6.5% | 0.3% | 23.7% | @@ -499,7 +499,7 @@ | dilithium2 | clean | 8,064 | 0 | 0 | 8,064 | | dilithium2 | m4f | 18,596 | 0 | 0 | 18,596 | | dilithium3 | clean | 7,580 | 0 | 0 | 7,580 | -| dilithium3 | m4f | 20,108 | 0 | 0 | 20,108 | +| dilithium3 | m4f | 18,588 | 0 | 0 | 18,588 | | dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | | dilithium5 | m4f | 18,468 | 0 | 0 | 18,468 | | falcon-1024 | clean | 82,647 | 0 | 0 | 82,647 | diff --git a/crypto_sign/dilithium3/m4f/macros_fnt.i b/crypto_sign/dilithium3/m4f/macros_fnt.i deleted file mode 120000 index 1abff093..00000000 --- a/crypto_sign/dilithium3/m4f/macros_fnt.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros_fnt.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/macros_smallntt.i b/crypto_sign/dilithium3/m4f/macros_smallntt.i new file mode 100644 index 00000000..61b63241 --- /dev/null +++ b/crypto_sign/dilithium3/m4f/macros_smallntt.i @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MACROS_SMALLNTT_I +#define MACROS_SMALLNTT_I + +// general macros +.macro load a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + ldr.w \a0, [\a, \mem0] + ldr.w \a1, [\a, \mem1] + ldr.w \a2, [\a, \mem2] + ldr.w \a3, [\a, \mem3] +.endm + +.macro store a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + str.w \a0, [\a, \mem0] + str.w \a1, [\a, \mem1] + str.w \a2, [\a, \mem2] + str.w \a3, [\a, \mem3] +.endm + +.macro doubleplant a, tmp, q, qa, plantconst + smulwb \tmp, \plantconst, \a + smulwt \a, \plantconst, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebarrett a, tmp, tmp2, q, barrettconst + smulbb \tmp, \a, \barrettconst + smultb \tmp2, \a, \barrettconst + asr \tmp, \tmp, #26 + asr \tmp2, \tmp2, #26 + smulbb \tmp, \tmp, \q + smulbb \tmp2, \tmp2, \q + pkhbt \tmp, \tmp, \tmp2, lsl#16 + usub16 \a, \a, \tmp +.endm + +// q locate in the top half of the register +.macro plant_red q, qa, qinv, tmp + mul \tmp, \tmp, \qinv + //tmp*qinv mod 2^2n/ 2^n; in high half + smlatt \tmp, \tmp, \q, \qa + // result in high half +.endm + +.macro mul_twiddle_plant a, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a + smulwt \a, \twiddle, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebutterfly_plant a0, a1, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a1 + smulwt \a1, \twiddle, \a1 + smlabt \tmp, \tmp, \q, \qa + smlabt \a1, \a1, \q, \qa + pkhtb \tmp, \a1, \tmp, asr#16 + usub16 \a1, \a0, \tmp + uadd16 \a0, \a0, \tmp +.endm + +.macro two_doublebutterfly_plant a0, a1, a2, a3, twiddle0, twiddle1, tmp, q, qa + doublebutterfly_plant \a0, \a1, \twiddle0, \tmp, \q, \qa + doublebutterfly_plant \a2, \a3, \twiddle1, \tmp, \q, \qa +.endm + +//For 3329 +.macro fullplant a0, a1, a2, a3, a4, a5, a6, a7, tmp, q, qa, plantconst + movw \plantconst, #44984 + movt \plantconst, #19 + doubleplant \a0, \tmp, \q, \qa, \plantconst + doubleplant \a1, \tmp, \q, \qa, \plantconst + doubleplant \a2, \tmp, \q, \qa, \plantconst + doubleplant \a3, \tmp, \q, \qa, \plantconst + doubleplant \a4, \tmp, \q, \qa, \plantconst + doubleplant \a5, \tmp, \q, \qa, \plantconst + doubleplant \a6, \tmp, \q, \qa, \plantconst + doubleplant \a7, \tmp, \q, \qa, \plantconst +.endm + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/smallntt.S b/crypto_sign/dilithium3/m4f/smallntt.S deleted file mode 100644 index 747c111c..00000000 --- a/crypto_sign/dilithium3/m4f/smallntt.S +++ /dev/null @@ -1,837 +0,0 @@ -#include "macros.i" - -.syntax unified -.cpu cortex-m4 -.thumb - -// general macros -.macro load a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 - ldr.w \a0, [\a, \mem0] - ldr.w \a1, [\a, \mem1] - ldr.w \a2, [\a, \mem2] - ldr.w \a3, [\a, \mem3] -.endm - -.macro store a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 - str.w \a0, [\a, \mem0] - str.w \a1, [\a, \mem1] - str.w \a2, [\a, \mem2] - str.w \a3, [\a, \mem3] -.endm - -.macro montgomery q, qinv, a, tmp - smulbt \tmp, \a, \qinv - smlabb \tmp, \q, \tmp, \a -.endm - -.macro montgomery_inplace q, qinv, a, tmp - smulbt \tmp, \a, \qinv - smlabb \a, \q, \tmp, \a -.endm - -.macro doublemontgomery a, tmp, tmp2, q, qinv, montconst - smulbb \tmp2, \a, \montconst - montgomery \q, \qinv, \tmp2, \tmp - smultb \a, \a, \montconst - montgomery \q, \qinv, \a, \tmp2 - pkhtb \a, \tmp2, \tmp, asr#16 -.endm - -// ####### -// ####### -// # NTT # -// ####### -// ####### - -.macro mul_twiddle tb, a, twiddle, tmp, tmp2, q, qinv - smulb\tb \tmp, \a, \twiddle - smult\tb \a, \a, \twiddle - montgomery \q, \qinv, \tmp, \tmp2 // reduce -> result in tmp2 - montgomery \q, \qinv, \a, \tmp // reduce -> result in tmp2 - pkhtb \a, \tmp, \tmp2, asr#16 // combine results from above in one register as 16bit halves -.endm - -.macro doublebutterfly tb, a0, a1, twiddle, tmp, tmp2, q, qinv - smulb\tb \tmp, \a1, \twiddle // a1_b * twiddle_tb - smult\tb \a1, \a1, \twiddle // a1_t * twiddle_tb - montgomery \q, \qinv, \tmp, \tmp2 // reduce -> result in tmp2 - montgomery \q, \qinv, \a1, \tmp // reduce -> result in tmp - pkhtb \tmp2, \tmp, \tmp2, asr#16 // combine results from above in one register as 16bit halves - usub16 \a1, \a0, \tmp2 // a0 - a1 * twiddle (a0, a1 contain 2 coeffs) - uadd16 \a0, \a0, \tmp2 // a0 + a1 * twiddle (a0, a1 contain 2 coeffs) -.endm - -.macro two_doublebutterfly tb1, tb2, a0, a1, a2, a3, twiddle, tmp, tmp2, q, qinv - doublebutterfly \tb1, \a0, \a1, \twiddle, \tmp, \tmp2, \q, \qinv - doublebutterfly \tb2, \a2, \a3, \twiddle, \tmp, \tmp2, \q, \qinv -.endm - -.macro _3_layer_double_CT_16 c0, c1, c2, c3, c4, c5, c6, c7, twiddle, twiddle_ptr, Qprime, Q, tmp, tmp2 - // layer 3 - ldrh.w \twiddle, [\twiddle_ptr], #2 - two_doublebutterfly b, b, \c0, \c4, \c1, \c5, \twiddle, \tmp, \tmp2, \Q, \Qprime - two_doublebutterfly b, b, \c2, \c6, \c3, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 2 - ldr.w \twiddle, [\twiddle_ptr], #4 - two_doublebutterfly b, b, \c0, \c2, \c1, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - - two_doublebutterfly t, t, \c4, \c6, \c5, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 1 - ldr.w \twiddle, [\twiddle_ptr], #4 - two_doublebutterfly b, t, \c0, \c1, \c2, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - - ldr.w \twiddle, [\twiddle_ptr], #4 - two_doublebutterfly b, t, \c4, \c5, \c6, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime -.endm - -.macro _3_layer_double_CT_16_fp c0, c1, c2, c3, c4, c5, c6, c7, xi01, xi23, xi45, xi67, twiddle, Qprime, Q, tmp, tmp2 - // layer 3 - vmov \twiddle, \xi01 - two_doublebutterfly t, t, \c0, \c4, \c1, \c5, \twiddle, \tmp, \tmp2, \Q, \Qprime - two_doublebutterfly t, t, \c2, \c6, \c3, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 2 - vmov \twiddle, \xi23 - two_doublebutterfly b, b, \c0, \c2, \c1, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - - two_doublebutterfly t, t, \c4, \c6, \c5, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 1 - vmov \twiddle, \xi45 - two_doublebutterfly b, t, \c0, \c1, \c2, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - - vmov \twiddle, \xi67 - two_doublebutterfly b, t, \c4, \c5, \c6, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime -.endm - -.global small_ntt_asm -.type small_ntt_asm, %function -.align 2 -small_ntt_asm: - push {r4-r11, r14} - vpush.w {s16} - - poly .req r0 - twiddle_ptr .req r1 - poly0 .req r2 - poly1 .req r3 - poly2 .req r4 - poly3 .req r5 - poly4 .req r6 - poly5 .req r7 - poly6 .req r8 - poly7 .req r9 - twiddle .req r10 - qinv .req r11 - q .req r11 - tmp .req r12 - tmp2 .req r14 - - movw q, #769 - movt qinv, #767 - - ### LAYER 7+6+5+4 - .equ distance, 256 - .equ offset, 32 - .equ strincr, 4 - // pre-load twiddle factors to FPU registers - vldm twiddle_ptr!, {s8-s15} - - - add tmp, poly, #strincr*8 - vmov s16, tmp - 1: - // load a1, a3, ..., a15 - load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset - load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset - - // 8-NTT on a1, a3, ..., a15 - _3_layer_double_CT_16_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, twiddle, qinv, q, tmp, tmp2 - - // multiply coeffs by layer 4 twiddles for later use - vmov twiddle, s12 - mul_twiddle b, poly0, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly1, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s13 - mul_twiddle b, poly2, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly3, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s14 - mul_twiddle b, poly4, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly5, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s15 - mul_twiddle b, poly6, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly7, twiddle, tmp, tmp2, q, qinv - - vmov s0, poly0 // a1 - vmov s1, poly1 // a3 - vmov s2, poly2 // a5 - vmov s3, poly3 // a7 - vmov s4, poly4 // a9 - vmov s5, poly5 // a11 - vmov s6, poly6 // a13 - vmov s7, poly7 // a15 - - // ---------- - - // load a0, a2, ..., a14 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - // 8-NTT on a0, a2, ..., a14 - _3_layer_double_CT_16_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, twiddle, qinv, q, tmp, tmp2 - - // layer 4 - 1 - // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) - vmov tmp2, s1 // load a3 - vmov s1, poly0 // preserve a0 - uadd16 poly0, poly1, tmp2 - usub16 poly1, poly1, tmp2 - - vmov tmp2, s3 // load a7 - vmov s3, poly2 // preserve a4 - uadd16 poly2, poly3, tmp2 - usub16 poly3, poly3, tmp2 - - vmov tmp2, s5 // load a11 - vmov s5, poly4 // preserve a8 - uadd16 poly4, poly5, tmp2 - usub16 poly5, poly5, tmp2 - - vmov tmp2, s7 // load a15 - vmov s7, poly6 // preserve a12 - uadd16 poly6, poly7, tmp2 - usub16 poly7, poly7, tmp2 - - str.w poly0, [poly, #1*distance/4] - str.w poly1, [poly, #1*distance/4+offset] - str.w poly2, [poly, #3*distance/4] - str.w poly3, [poly, #3*distance/4+offset] - str.w poly4, [poly, #5*distance/4] - str.w poly5, [poly, #5*distance/4+offset] - str.w poly6, [poly, #7*distance/4] - str.w poly7, [poly, #7*distance/4+offset] - - // layer 4 - 2 - // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) - vmov tmp2, s1 // load a0 - vmov poly1, s0 // load a1 - uadd16 poly0, tmp2, poly1 - usub16 poly1, tmp2, poly1 - - vmov tmp2, s3 // load a4 - vmov poly3, s2 // load a5 - uadd16 poly2, tmp2, poly3 - usub16 poly3, tmp2, poly3 - - vmov tmp2, s5 // load a8 - vmov poly5, s4 // load a9 - uadd16 poly4, tmp2, poly5 - usub16 poly5, tmp2, poly5 - - vmov tmp2, s7 // load a12 - vmov poly7, s6 // load a13 - uadd16 poly6, tmp2, poly7 - usub16 poly7, tmp2, poly7 - - str.w poly1, [poly, #offset] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #2*distance/4+offset] - str.w poly4, [poly, #4*distance/4] - str.w poly5, [poly, #4*distance/4+offset] - str.w poly6, [poly, #6*distance/4] - str.w poly7, [poly, #6*distance/4+offset] - str.w poly0, [poly], #4 - - vmov tmp, s16 - cmp.w poly, tmp - bne.w 1b - - sub.w poly, #8*strincr - - ### LAYER 3+2+1 - - .equ distance, distance/16 - .equ strincr, 32 - - add.w tmp, poly, #strincr*16 - vmov s13, tmp - - 2: - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - _3_layer_double_CT_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, qinv, q, tmp, tmp2 - - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #strincr - - vmov tmp, s13 - cmp.w poly, tmp - bne.w 2b - - vpop.w {s16} - pop {r4-r11, pc} - - -.unreq poly -.unreq twiddle_ptr -.unreq poly0 -.unreq poly1 -.unreq poly2 -.unreq poly3 -.unreq poly4 -.unreq poly5 -.unreq poly6 -.unreq poly7 -.unreq twiddle -.unreq qinv -.unreq q -.unreq tmp -.unreq tmp2 - -// ######## -// ######## -// # INTT # -// ######## -// ######## - -.macro doublebutterfly_light a0, a1, tmp, tmp2, q, qinv - uadd16 \tmp, \a0, \a1 - usub16 \a1, \a0, \a1 - mov.w \a0, \tmp -.endm - -.macro two_doublebutterfly_light a0, a1, a2, a3, tmp, tmp2, q, qinv - doublebutterfly_light \a0, \a1, \tmp, \tmp2, \q, \qinv - doublebutterfly_light \a2, \a3, \tmp, \tmp2, \q, \qinv -.endm - -.macro _3_layer_double_inv_CT_16_light c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi12, xi34, xi56, twiddle, q, qinv, tmp, tmp2 - - // layer 1 - sadd16.w \tmp, \c0, \c1 // c0, c1 - ssub16.w \c1, \c0, \c1 - sadd16.w \tmp2, \c2, \c3 // c2, c3 - ssub16.w \c3, \c2, \c3 - - sadd16.w \c0, \c4, \c5 // c4, c5 - ssub16.w \c5, \c4, \c5 - sadd16.w \c2, \c6, \c7 // c6, c7 - ssub16.w \c7, \c6, \c7 - // c4, c6 are free at this point - - // layer 2 - sadd16.w \c6, \tmp, \tmp2 // c0, c2 - ssub16.w \tmp2, \tmp, \tmp2 - sadd16.w \c4, \c0, \c2 // c4, c6 - ssub16.w \c2, \c0, \c2 - - vmov.w \twiddle, \xi12 - doublebutterfly t, \c1, \c3, \twiddle, \tmp, \c0, \q, \qinv // c0 has been used and c6 still free - doublebutterfly t, \c5, \c7, \twiddle, \tmp, \c0, \q, \qinv - // c0, c6 are free at this point - - // layer 3 - sadd16.w \c0, \c6, \c4 // c0, c4 - ssub16.w \c4, \c6, \c4 - - vmov.w \twiddle, \xi34 - doublebutterfly t, \c1, \c5, \twiddle, \tmp, \c6, \q, \qinv - - vmov.w \twiddle, \xi56 - // this block is one doublebutterfly - smulbb \tmp, \c2, \twiddle // c2, c6 - smultb \c2, \c2, \twiddle - montgomery_inplace \q, \qinv, \tmp, \c6 - montgomery_inplace \q, \qinv, \c2, \c6 - pkhtb \tmp, \c2, \tmp, asr #16 - ssub16.w \c6, \tmp2, \tmp - sadd16.w \c2, \tmp2, \tmp - - doublebutterfly t, \c3, \c7, \twiddle, \tmp, \tmp2, \q, \qinv - -.endm - -.macro _3_layer_double_inv_CT_16_light_reduce c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi12, xi34, xi56, twiddle, q, qinv, tmp, tmp2 - - // layer 1 - sadd16.w \tmp, \c0, \c1 // c0, c1 - ssub16.w \c1, \c0, \c1 - sadd16.w \tmp2, \c2, \c3 // c2, c3 - ssub16.w \c3, \c2, \c3 - - sadd16.w \c0, \c4, \c5 // c4, c5 - ssub16.w \c5, \c4, \c5 - sadd16.w \c2, \c6, \c7 // c6, c7 - ssub16.w \c7, \c6, \c7 - // c4, c6 are free at this point - - mov.w \c6, \tmp - mov.w \c4, \c0 - - // layer 2 - vmov.w \twiddle, \xi12 - doublebutterfly b, \c6, \tmp2, \twiddle, \tmp, \c0, \q, \qinv - doublebutterfly b, \c4, \c2, \twiddle, \tmp, \c0, \q, \qinv - doublebutterfly t, \c1, \c3, \twiddle, \tmp, \c0, \q, \qinv // c0 has been used and c6 still free - doublebutterfly t, \c5, \c7, \twiddle, \tmp, \c0, \q, \qinv - // c0, c6 are free at this point - - // layer 3 - sadd16.w \c0, \c6, \c4 // c0, c4 - ssub16.w \c4, \c6, \c4 - - vmov.w \twiddle, \xi34 - doublebutterfly t, \c1, \c5, \twiddle, \tmp, \c6, \q, \qinv - - vmov.w \twiddle, \xi56 - // this block is one doublebutterfly - smulbb \tmp, \c2, \twiddle // c2, c6 - smultb \c2, \c2, \twiddle - montgomery_inplace \q, \qinv, \tmp, \c6 - montgomery_inplace \q, \qinv, \c2, \c6 - pkhtb \tmp, \c2, \tmp, asr #16 - ssub16.w \c6, \tmp2, \tmp - sadd16.w \c2, \tmp2, \tmp - - doublebutterfly t, \c3, \c7, \twiddle, \tmp, \tmp2, \q, \qinv - -.endm - -.macro _3_layer_double_inv_CT_16 c0, c1, c2, c3, c4, c5, c6, c7, twiddle, twiddle_ptr, Qprime, Q, tmp, tmp2 - // layer 3 - ldrh.w twiddle, [twiddle_ptr], #2 - two_doublebutterfly b, b, \c0, \c1, \c2, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - two_doublebutterfly b, b, \c4, \c5, \c6, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 2 - ldr.w twiddle, [twiddle_ptr], #4 - two_doublebutterfly b, t, \c0, \c2, \c1, \c3, \twiddle, \tmp, \tmp2, \Q, \Qprime - - two_doublebutterfly b, t, \c4, \c6, \c5, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime - - // layer 1 - ldr.w twiddle, [twiddle_ptr], #4 - two_doublebutterfly b, t, \c0, \c4, \c1, \c5, \twiddle, \tmp, \tmp2, \Q, \Qprime - - ldr.w twiddle, [twiddle_ptr], #4 - two_doublebutterfly b, t, \c2, \c6, \c3, \c7, \twiddle, \tmp, \tmp2, \Q, \Qprime -.endm - -.macro mul_twiddle_barrett_32 tb a, twiddle, Qbar, Q, tmp, tmp2 - smulb\tb \tmp, \a, \twiddle - smmulr.w \tmp2, \tmp, \Qbar - mls.w \tmp, \tmp2, \Q, \tmp - smult\tb \a, \a, \twiddle - smmulr.w \tmp2, \a, \Qbar - mls.w \a, \tmp2, \Q, \a - pkhbt \a, \tmp, \a, lsl #16 -.endm - -.macro _3_layer_double_inv_twist_16 c0, c1, c2, c3, c4, c5, c6, c7, twiddle, twiddle_ptr, Qbar, Q, tmp, tmp2 - - movt \Q, #0 - - ldr.w \twiddle, [\twiddle_ptr], #4 - - mul_twiddle_barrett_32 b, \c0, \twiddle, \Qbar, \Q, \tmp, \tmp2 - mul_twiddle_barrett_32 t, \c1, \twiddle, \Qbar, \Q, \tmp, \tmp2 - - ldr.w \twiddle, [\twiddle_ptr], #4 - - mul_twiddle_barrett_32 b, \c2, \twiddle, \Qbar, \Q, \tmp, \tmp2 - mul_twiddle_barrett_32 t, \c3, \twiddle, \Qbar, \Q, \tmp, \tmp2 - - ldr.w \twiddle, [\twiddle_ptr], #4 - - mul_twiddle_barrett_32 b, \c4, \twiddle, \Qbar, \Q, \tmp, \tmp2 - mul_twiddle_barrett_32 t, \c5, \twiddle, \Qbar, \Q, \tmp, \tmp2 - - ldr.w \twiddle, [\twiddle_ptr], #4 - - mul_twiddle_barrett_32 b, \c6, \twiddle, \Qbar, \Q, \tmp, \tmp2 - mul_twiddle_barrett_32 t, \c7, \twiddle, \Qbar, \Q, \tmp, \tmp2 - - movt \Q, #767 - -.endm - -.global small_invntt_tomont_asm -.type small_invntt_tomont_asm, %function -.align 2 -small_invntt_tomont_asm: - push {r4-r11, r14} - - poly .req r0 - twiddle_ptr .req r1 - poly0 .req r2 - poly1 .req r3 - poly2 .req r4 - poly3 .req r5 - poly4 .req r6 - poly5 .req r7 - poly6 .req r8 - poly7 .req r9 - twiddle .req r10 - qinv .req r11 - q .req r11 - tmp .req r12 - tmp2 .req r14 - - movw q, #769 - movt qinv, #767 - - ### LAYER 7+6+5+4 - .equ distance, 16 - .equ offset, 32 - .equ strincr, 64 - - // pre-load twiddle factors to FPU registers - vldm twiddle_ptr!, {s8-s15} - - add.w tmp, poly, #8*strincr - vmov s8, tmp - 1: - // load a1, a3, ..., a15 - load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset - load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset - - // NTT on a1, a3, ..., a15 - _3_layer_double_inv_CT_16_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, twiddle, q, qinv, tmp, tmp2 - - // multiply coeffs by layer 4 twiddles for later use - vmov twiddle, s12 - mul_twiddle b, poly0, twiddle, tmp, tmp2, q, qinv // could be omitted but kept for reduction only - mul_twiddle t, poly1, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s13 - mul_twiddle b, poly2, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly3, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s14 - mul_twiddle b, poly4, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly5, twiddle, tmp, tmp2, q, qinv - - vmov twiddle, s15 - mul_twiddle b, poly6, twiddle, tmp, tmp2, q, qinv - mul_twiddle t, poly7, twiddle, tmp, tmp2, q, qinv - - vmov s0, poly0 // a1 - vmov s1, poly1 // a3 - vmov s2, poly2 // a5 - vmov s3, poly3 // a7 - vmov s4, poly4 // a9 - vmov s5, poly5 // a11 - vmov s6, poly6 // a13 - vmov s7, poly7 // a15 - - // ---------- - - // load a0, a2, ..., a14 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - // NTT on a0, a2, ..., a14 - _3_layer_double_inv_CT_16_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, twiddle, q, qinv, tmp, tmp2 - - // layer 4 - 1 - // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) - vmov tmp2, s1 // load a3 - vmov s1, poly0 // preserve a0 - uadd16 poly0, poly1, tmp2 - usub16 poly1, poly1, tmp2 - - vmov tmp2, s3 // load a7 - vmov s3, poly2 // preserve a4 - uadd16 poly2, poly3, tmp2 - usub16 poly3, poly3, tmp2 - - vmov tmp2, s5 // load a11 - vmov s5, poly4 // preserve a8 - uadd16 poly4, poly5, tmp2 - usub16 poly5, poly5, tmp2 - - vmov tmp2, s7 // load a15 - vmov s7, poly6 // preserve a12 - uadd16 poly6, poly7, tmp2 - usub16 poly7, poly7, tmp2 - - str.w poly0, [poly, #1*distance/4] - str.w poly1, [poly, #1*distance/4+offset] - str.w poly2, [poly, #3*distance/4] - str.w poly3, [poly, #3*distance/4+offset] - str.w poly4, [poly, #5*distance/4] - str.w poly5, [poly, #5*distance/4+offset] - str.w poly6, [poly, #7*distance/4] - str.w poly7, [poly, #7*distance/4+offset] - - // layer 4 - 2 - // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) - vmov tmp2, s1 // load a0 - vmov poly1, s0 // load a1 - uadd16 poly0, tmp2, poly1 - usub16 poly1, tmp2, poly1 - - vmov tmp2, s3 // load a4 - vmov poly3, s2 // load a5 - uadd16 poly2, tmp2, poly3 - usub16 poly3, tmp2, poly3 - - vmov tmp2, s5 // load a8 - vmov poly5, s4 // load a9 - uadd16 poly4, tmp2, poly5 - usub16 poly5, tmp2, poly5 - - vmov tmp2, s7 // load a12 - vmov poly7, s6 // load a13 - uadd16 poly6, tmp2, poly7 - usub16 poly7, tmp2, poly7 - - str.w poly1, [poly, #offset] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #2*distance/4+offset] - str.w poly4, [poly, #4*distance/4] - str.w poly5, [poly, #4*distance/4+offset] - str.w poly6, [poly, #6*distance/4] - str.w poly7, [poly, #6*distance/4+offset] - str.w poly0, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) - - vmov tmp, s8 - cmp.w poly, tmp - bne.w 1b - - sub.w poly, #8*strincr - - ### LAYER 3+2+1 - .equ distance, distance*16 - .equ strincr, 4 - - // ITER 0 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - vldm twiddle_ptr!, {s5-s7} - - _3_layer_double_inv_CT_16_light_reduce poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s5, s5, s6, s7, twiddle, q, qinv, tmp, tmp2 - - vmov.w s2, poly - movw poly, #:lower16:5585133 - movt poly, #:upper16:5585133 - - // twisting - _3_layer_double_inv_twist_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, poly, q, tmp, tmp2 - - vmov.w poly, s2 - - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - // ITER 1-12 - add.w tmp, poly, #strincr*3*(3+1) - vmov s14, tmp - 3: - add.w tmp, poly, #strincr*3 - vmov s13, tmp - 2: - // polys upto 6q - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - - _3_layer_double_inv_CT_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, qinv, q, tmp, tmp2 - - vmov.w s2, poly - movw poly, #:lower16:5585133 - movt poly, #:upper16:5585133 - - // twisting - _3_layer_double_inv_twist_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, poly, q, tmp, tmp2 - - vmov.w poly, s2 - - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - vmov tmp, s13 - cmp.w poly, tmp - bne.w 2b - - // polys upto 9q - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - _3_layer_double_inv_CT_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, qinv, q, tmp, tmp2 - - vmov.w s2, poly - movw poly, #:lower16:5585133 - movt poly, #:upper16:5585133 - - // twisting - _3_layer_double_inv_twist_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, poly, q, tmp, tmp2 - - vmov.w poly, s2 - - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - vmov tmp, s14 - cmp.w poly, tmp - bne.w 3b - - // ITER 13-15 - add tmp, poly, #3*strincr - vmov s13, tmp - 2: - // polys upto 6q - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - _3_layer_double_inv_CT_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, qinv, q, tmp, tmp2 - - vmov.w s2, poly - movw poly, #:lower16:5585133 - movt poly, #:upper16:5585133 - - // twisting - _3_layer_double_inv_twist_16 poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle, twiddle_ptr, poly, q, tmp, tmp2 - - vmov.w poly, s2 - - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #strincr - - vmov tmp, s13 - cmp.w poly, tmp - bne.w 2b - - pop {r4-r11, pc} - -.unreq poly -.unreq twiddle_ptr -.unreq poly0 -.unreq poly1 -.unreq poly2 -.unreq poly3 -.unreq poly4 -.unreq poly5 -.unreq poly6 -.unreq poly7 -.unreq twiddle -.unreq qinv -.unreq q -.unreq tmp -.unreq tmp2 - -.align 2 -.global small_pointmul_asm -.type small_pointmul_asm, %function -small_pointmul_asm: - push.w {r4-r11, lr} - - movw r14, #769 - movt r14, #767 - - .equ width, 4 - - add.w r12, r2, #64*2 - _point_mul_16_loop: - - ldr.w r7, [r1, #2*width] - ldr.w r8, [r1, #3*width] - ldrsh.w r9, [r2, #1*2] - ldr.w r5, [r1, #1*width] - ldr.w r4, [r1], #4*width - ldrsh.w r6, [r2], #2*2 - - smultb r10, r4, r6 - montgomery r14, r14, r10, r11 - pkhbt r4, r4, r11 - - - neg.w r6, r6 - - smultb r10, r5, r6 - montgomery r14, r14, r10, r11 - pkhbt r5, r5, r11 - - str.w r5, [r0, #1*width] - str.w r4, [r0], #2*width - - smultb r10, r7, r9 - montgomery r14, r14, r10, r11 - pkhbt r7, r7, r11 - - neg.w r9, r9 - - smultb r10, r8, r9 - montgomery r14, r14, r10, r11 - pkhbt r8, r8, r11 - - str.w r8, [r0, #1*width] - str.w r7, [r0], #2*width - - cmp.w r2, r12 - bne.w _point_mul_16_loop - - pop.w {r4-r11, pc} - - .align 2 -.global small_asymmetric_mul_asm -.type small_asymmetric_mul_asm, %function -small_asymmetric_mul_asm: - push.w {r4-r11, lr} - - movw r14, #769 - movt r14, #767 - .equ width, 4 - add.w r12, r0, #256*2 - _asymmetric_mul_16_loop: - ldr.w r7, [r1, #width] - ldr.w r4, [r1], #2*width - ldr.w r8, [r2, #width] - ldr.w r5, [r2], #2*width - ldr.w r9, [r3, #width] - ldr.w r6, [r3], #2*width - - smuad r10, r4, r6 - montgomery r14, r14, r10, r6 - smuadx r11, r4, r5 - montgomery r14, r14, r11, r10 - - pkhtb r10, r10, r6, asr#16 - - str.w r10, [r0], #width - - smuad r10, r7, r9 - montgomery r14, r14, r10, r6 - smuadx r11, r7, r8 - montgomery r14, r14, r11, r10 - - pkhtb r10, r10, r6, asr#16 - str.w r10, [r0], #width - - - cmp.w r0, r12 - bne.w _asymmetric_mul_16_loop - - pop.w {r4-r11, pc} \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/smallntt.h b/crypto_sign/dilithium3/m4f/smallntt.h index 0aa0ce9b..2927ff4d 100644 --- a/crypto_sign/dilithium3/m4f/smallntt.h +++ b/crypto_sign/dilithium3/m4f/smallntt.h @@ -1,53 +1,48 @@ +/** + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef SMALLNTT_H #define SMALLNTT_H #include #include "params.h" -static const int16_t zetas[64] = { --23, 112, -151, -134, -52, -148, 227, 232, --71, 212, 236, 21, 341, 379, -202, -220, -352, 292, 238, 145, 194, -276, 70, -274, -117, 333, 66, 247, -237, -83, -252, -244, -331, -241, 167, 357, -355, 291, -358, 105, -115, -209, 14, 99, -260, 29, 366, -378, -318, 278, 353, 354, -184, 127, 330, -303, 222, -78, -348, -44, 201, 158, 350, 168 -}; - -static const int16_t zetas_asm[128] = { -0, -164, -81, 361, 186, -3, -250, -120, -308, 129, -16, -223, -362, -143, 131, -337, --76, 147, -114, -23, 112, -151, -134, --98, -272, 54, -52, -148, 227, 232, -36, -2, -124, -71, 212, 236, 21, --75, -80, -346, 341, 379, -202, -220, --339, 86, -51, 352, 292, 238, 145, --255, 364, 267, 194, -276, 70, -274, -282, 161, -15, 117, 333, 66, 247, --203, 288, 169, -237, -83, -252, -244, --34, 191, 307, 331, -241, 167, 357, -199, -50, -24, -355, 291, -358, 105, -178, -170, 226, -115, -209, 14, 99, -270, 121, -188, -260, 29, 366, -378, --10, -380, 279, -318, 278, 353, 354, -149, 180, -375, -184, 127, 330, -303, -369, -157, 263, 222, -78, -348, -44, --192, -128, -246, 201, 158, 350, 168 -}; - -static const int16_t zetas_inv_CT_asm[256] = { -0, 171, 171, 164, 171, -361, 164, 81, 171, 120, -361, 3, 164, 250, 81, -186, -171, 164, 171, -361, 164, 81, -257, 49, -141, -18, -215, 38, 283, 347, 337, 192, -369, 246, -263, 128, 157, 239, -264, 179, 301, -207, 219, -332, -206, 120, 337, -131, 192, -149, -369, 10, 62, 57, 40, 136, 1, 311, -173, 27, 223, 203, -282, -169, 15, -288, -161, 74, -56, 271, -309, 26, -373, 116, -67, -361, 120, 250, 337, 143, -131, 362, -383, 82, 125, -344, -93, 299, -60, -204, 143, -270, -178, 188, -226, -121, 170, 39, -175, 174, 284, -111, 84, -22, 79, 3, 223, 16, 203, 255, -282, 339, 245, 64, -90, -306, 190, -123, 197, -253, -129, 75, -36, 346, 124, 80, 2, 218, 126, -33, -266, 326, -122, -261, 343, 164, -361, 81, 120, 3, 250, -186, 285, 200, -89, 5, 17, -96, 135, -310, -131, -149, 10, 375, -279, -180, 380, -280, -183, -7, 130, -327, -189, -335, -370, 250, 143, 362, -270, -199, -178, 34, -359, -144, -182, 304, -43, -300, -251, 377, 16, 255, 339, -267, 51, -364, -86, -106, 101, -118, 214, -349, -110, -374, -195, 81, 3, -186, 223, -129, 16, 308, 320, 319, 8, 181, 154, 216, 273, 313, 362, -199, 34, 24, -307, 50, -191, -139, -165, 208, 92, 159, 233, 177, -321, -186, -129, 308, 75, 98, -36, 76, 231, 324, 25, 85, 289, -94, -12, 113, 308, 98, 76, -54, 114, 272, -147, -146, -35, -119, -97, -176, -137, -312, -138, -}; - - -#define SMALL_Q 769 - -void small_ntt_asm(int16_t a[N], const int16_t * zetas); -void small_invntt_tomont_asm(int16_t a[N], const int16_t * zetas); -void small_pointmul_asm(int16_t out[N], const int16_t in[N], const int16_t *zetas); -void small_asymmetric_mul_asm(int16_t c[256], const int16_t a[256], const int16_t b[256], const int16_t b_prime[256]); - -#define small_ntt(a) small_ntt_asm(a, zetas_asm) -#define small_invntt_tomont(a) small_invntt_tomont_asm(a, zetas_inv_CT_asm) -#define small_point_mul(out, in) small_pointmul_asm(out, in, zetas) -#define small_asymmetric_mul(c, a, b, b_prime) small_asymmetric_mul_asm(c, a, b, b_prime); +#define SMALL_Q 769 + +static const int32_t zetas_769[64] = { + 3138844760, 1334846793, 999738812, 1854264165, 1681125041, 1150537404, 2820492178, 3071823164, 726067294, 2066499220, 3272887953, 1055590142, 4255871365, 1871019564, 2731130050, 1826338500, 513832239, 1792827701, 3373420347, 2993631302, 1161707670, 3306398751, 3518633806, 3406931146, 1586177780, 3853741788, 3317569017, 3825816122, 971813147, 122872927, 217820188, 619949766, 3753209393, 770748358, 4099487641, 765163225, 3630336467, 1742561504, 3479537875, 982983413, 2809321912, 2379266669, 703726762, 681386230, 4110657907, 1457719720, 1217559000, 2474213930, 1195218468, 1089100940, 564098436, 614364633, 3635921600, 2088839752, 3702943196, 1949211426, 2569161192, 374203913, 3982199847, 2083254619, 1513571050, 3647091866, 413299844, 4149753838}; + +static const int32_t zetas_asm_769[128] = { + 346278248, 223405321, 966228013, 759578091, -150798592, 318352582, -1736976371, 1697880440, -2105595150, -804259156, 1675539907, -1016494210, 1401868389, -2005062756, 240160720, 474736307, -1200803600, -1435379187, -1156122536, 1334846793, 999738811, 1854264164, -631120032, -787503756, -1580592646, 1681125040, 1150537403, -1474475119, -1223144132, 1809583100, -100532394, -1938041160, 726067293, 2066499219, -1022079344, 1055590142, 525002504, 273671518, -212235055, -39095931, 1871019563, -1563837247, 1826338499, 139628326, 27925665, 1731391238, 513832238, 1792827701, -921546949, -1301335995, 67021596, 1117026605, 536172770, 1161707669, -988568545, -776333490, -888036151, 1290165729, -497076839, -753992958, 1586177779, -441225509, -977398279, -469151174, -1614103444, 1591762912, -94947261, 971813146, 122872927, 217820188, 619949766, -1709050706, 1010909077, -1748146637, -541757903, 770748357, -195479656, 765163224, 1413038655, 1781657435, -1206388733, -664630830, 1742561504, -815429422, 982983412, 357448514, 44681064, -1524741316, -1485645385, -1915700627, 703726761, 681386229, 686971362, 1787242568, -860110486, -184309390, 1457719719, 1217558999, -1820753366, -502661972, -1921285760, 1139367137, 1195218467, 1089100940, 564098435, 614364633, -1100271206, 457980908, -1669954774, -659045697, 2088839751, -592024101, 1949211426, 1368357591, 698141628, 335107981, -1725806105, 374203913, -312767449, 2083254618, -1061175275, -2139105948, 519417371, 1513571050, -647875431, 413299844, -145213459, 0}; + +// INTT with CT butterfly +static const int32_t zetas_inv_asm_769[256] = { + 5585134, 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 5585134, 1736976371, -966228013, 150798592, -346278248, -318352582, -223405321, -759578091, + // removed first "2285" + LAYER 3+2+1 - 1 - butterfly + 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 636705165, 446810642, 1519156183, 11170266, -821014555, -1932456027, 301597183, -692556495, -240160720, 1061175275, -1368357591, -519417371, -335107981, 2139105948, -698141628, -625534899, -1267825197, 843355087, 290426917, 128458060, 1295750862, -748407825, -826599688, 1736976371, -240160720, 2005062756, 1061175275, 1100271206, -1368357591, 502661972, 915961816, 1396283256, 452395775, -1038834743, -955057747, -670215963, 2016233022, -16755399, -1675539907, 1614103444, -1290165729, 94947261, 753992958, -1591762912, 497076839, -1954796559, 1943626293, -1122611738, -1239899531, 938302348, -245745853, 882451018, -435640376, -966228013, 1736976371, -318352582, -240160720, -1401868389, 2005062756, 1016494210, 714897027, -1005323944, 876865885, 2122350549, -1373942724, -2094424884, 1468889985, 1558252114, -1401868389, -686971362, -357448514, 860110486, 1524741316, -1787242568, -44681064, 1407453522, -368618780, 1323676527, -653460564, -1362772458, 1379527857, -463566041, 1859849297, 150798592, -1675539907, 804259156, 1614103444, -67021596, -1290165729, -139628326, -2060914086, -994153678, 55851330, 189894523, -1072345541, 1507985917, 832184821, 1111441472, 2105595150, -525002504, -1809583100, 212235055, 1938041160, -273671518, 100532394, -2044158687, -78191862, 1452134586, 642290298, -2111180283, 552928169, 161968858, -1167292802, -346278248, -966228013, -223405321, 1736976371, 150798592, -318352582, -759578091, -1608518311, -2032988421, -899206417, -480321440, 943887481, 1491230518, -83776995, -284841784, 2005062756, 1100271206, 502661972, 1669954774, -1139367137, -457980908, 1921285760, 1128196871, -1318091394, -1904530361, 396544445, -1228729265, 117287794, 2116765416, 1184048201, -318352582, -1401868389, 1016494210, -686971362, -1413038655, -357448514, 1709050706, -731652426, 89362128, 2021818155, 1720220972, -1882189829, -1245484665, -798674023, 720482160, 804259156, -67021596, -139628326, -536172770, -1731391238, -1117026605, -27925665, -1843093898, -1971551958, 1027664477, 1776072302, -1692295306, 1977137091, 709311894, 1552666981, -223405321, 150798592, -759578091, -1675539907, 2105595150, 804259156, -1697880440, -675801096, 279256651, 949472614, -1066760408, -1050005009, -134043193, 1262240064, 1714635839, 1016494210, -1413038655, 1709050706, 1206388733, 1748146637, -1781657435, -1010909077, -390959312, -1329261660, -1083515807, -1965966825, -1530326449, 809844289, -1541496715, 1630858843, -759578091, 2105595150, -1697880440, -525002504, 631120032, -1809583100, -474736307, -1575007513, -201064789, 1893360095, 424470110, -1133782004, -418884977, -1424208921, -547343036, -1697880440, 631120032, -474736307, 1580592646, 1435379187, 787503756, 1200803600, 1999477623, -932717215, 1982722224, -1848679031, 586438968, 1993892490, 1625273710, -1346017059, 0}; + +// Q1=769 +void small_ntt_asm_769(int16_t a[N], const int32_t *zetas); +void small_invntt_asm_769(int16_t a[N], const int32_t *zetas); +void small_pointmul_asm_769(int16_t out[N], const int16_t in[N], const int32_t *zetas); +void small_asymmetric_mul_asm_769(int16_t c[N], const int16_t a[N], const int16_t b[N], const int16_t b_prime[N]); + +// small NTT for computing cs0 and cs1; default use 769 as modulus. +#define small_ntt(a) small_ntt_asm_769(a, zetas_asm_769) +#define small_invntt_tomont(a) small_invntt_asm_769(a, zetas_inv_asm_769) +#define small_point_mul(out, in) small_pointmul_asm_769(out, in, zetas_769) +#define small_asymmetric_mul(c, a, b, b_prime) small_asymmetric_mul_asm_769(c, a, b, b_prime); #endif diff --git a/crypto_sign/dilithium3/m4f/smallntt_769.S b/crypto_sign/dilithium3/m4f/smallntt_769.S new file mode 100644 index 00000000..97c60f03 --- /dev/null +++ b/crypto_sign/dilithium3/m4f/smallntt_769.S @@ -0,0 +1,681 @@ +/** + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "macros.i" + +.syntax unified +.cpu cortex-m4 +.thumb + +#include "macros_smallntt.i" +// ####### +// ####### +// # NTT # +// ####### +// ####### + +.macro _3_layer_double_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_CT_16_plant_fp c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle1, twiddle2, q, qa, tmp + // layer 3 + vmov \twiddle1, \xi0 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + vmov \twiddle1, \xi1 + vmov \twiddle2, \xi2 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + vmov \twiddle1, \xi3 + vmov \twiddle2, \xi4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + vmov \twiddle1, \xi5 + vmov \twiddle2, \xi6 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.global small_ntt_asm_769 +.type small_ntt_asm_769, %function +.align 2 +small_ntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s24} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + ### qinv .req r11 ### q^-1 mod 2^2n; n=16 + q .req r12 + ### at the top of r12 + qa .req r0 + ### qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + // movw qa, #24608 + // Why movt? Because we initially placed qa at the bottom of the same register as q; + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 256 + .equ offset, 32 + .equ strincr, 4 + // pre-load 15 twiddle factors to 15 FPU registers + // s0-s7 used to temporary store 16 16-bit polys. + vldm twiddle_ptr!, {s8-s22} + + add tmp, poly, #strincr*8 + // s23: poly addr + // s24: tmp + vmov s24, tmp + 1: + // load a1, a3, ..., a15 + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // 8-NTT on a1, a3, ..., a15 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // s15, s16, s17, s18, s19, s20, s21, s22 left + // multiply coeffs by layer 8 twiddles for later use + vmov twiddle1, s15 + vmov twiddle2, s16 + mul_twiddle_plant poly0, twiddle1, tmp, q, qa + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + + vmov poly, s23 + + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // 8-NTT on a0, a2, ..., a14 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle1, s1 // load a3 + uadd16 tmp, poly1, twiddle1 + usub16 poly1, poly1, twiddle1 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle1, s3 // load a7 + uadd16 tmp, poly3, twiddle1 + usub16 poly3, poly3, twiddle1 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle1, s5 // load a11 + uadd16 tmp, poly5, twiddle1 + usub16 poly5, poly5, twiddle1 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle1, s7 // load a15 + uadd16 tmp, poly7, twiddle1 + usub16 poly7, poly7, twiddle1 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle1, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle1, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle1, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle1, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle1, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle1, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle1, poly0, poly1 + str.w twiddle1, [poly, #offset] + str.w tmp, [poly], #4 + + vmov tmp, s24 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance/16 + .equ strincr, 32 + + add.w tmp, poly, #strincr*16 + vmov s13, tmp + 2: + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s23 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #strincr + + vmov tmp, s13 + cmp.w poly, tmp + bne.w 2b + vpop.w {s16-s24} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + + +// ######## +// ######## +// # INTT # +// ######## +// ######## + +// input: 0.5/1q +.macro _3_layer_double_inv_CT_16_plant_light c0, c1, c2, c3, c4, c5, c6, c7, xi2, xi4, xi5, xi6, twiddle1, tmp2, q, qa, tmp + + // layer 1 + sadd16.w \tmp, \c0, \c1 // c0, c1 + ssub16.w \c1, \c0, \c1 + sadd16.w \tmp2, \c2, \c3 // c2, c3 + ssub16.w \c3, \c2, \c3 + // tmp, c1, tmp2, c3: 1q maximum + sadd16.w \c0, \c4, \c5 // c4, c5 + ssub16.w \c5, \c4, \c5 + sadd16.w \c2, \c6, \c7 // c6, c7 + ssub16.w \c7, \c6, \c7 + // c4, c6 are free at this point + // c0,c5,c2,c7 1q maximum + + // layer 2 + sadd16.w \c6, \tmp, \tmp2 // c0, c2 + ssub16.w \tmp2, \tmp, \tmp2 + sadd16.w \c4, \c0, \c2 // c4, c6 + ssub16.w \c2, \c0, \c2 + // c6, tmp2, c4, c2: 2q maximum + + vmov.w \twiddle1, \xi2 + doublebutterfly_plant \c1, \c3, \twiddle1, \tmp, \q, \qa + doublebutterfly_plant \c5, \c7, \twiddle1, \tmp, \q, \qa + // c1, c3, c7, c5: 1.5q maximum; + + // tmp and c0 are free at this point + // layer 3 + sadd16.w \c0, \c6, \c4 // c0, c4 + ssub16.w \c4, \c6, \c4 + // c0, c4: 4q + // c6 are free at this point + vmov.w \twiddle1, \xi4 + doublebutterfly_plant \c1, \c5, \twiddle1, \tmp, \q, \qa + // c1, c5: 2q maximum + + vmov.w \twiddle1, \xi5 + // this block is one doublebutterfly + smulwb \tmp, \twiddle1, \c2 // c2, c6 + smulwt \c2, \twiddle1, \c2 + smlabt \tmp, \tmp, \q, \qa + smlabt \c2, \c2, \q, \qa + pkhtb \tmp, \c2, \tmp, asr#16 + ssub16.w \c6, \tmp2, \tmp + sadd16.w \c2, \tmp2, \tmp + //c6, c2: 4.5q + vmov.w \twiddle1, \xi6 + doublebutterfly_plant \c3, \c7, \twiddle1, \tmp, \q, \qa + //c3, c7: 2.5q maximum +.endm +.macro _3_layer_double_inv_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_inv_twist_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c0, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c1, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c2, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c3, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c4, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c5, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c6, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c7, \twiddle2, \tmp, \q, \qa +.endm +# input coefficients < 0.5q +.global small_invntt_asm_769 +.type small_invntt_asm_769, %function +.align 2 +small_invntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s23} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + q .req r12 + // at the top of r12 + qa .req r0 + // qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 16 + .equ offset, 32 + .equ strincr, 64 + + // pre-load twiddle factors to FPU registers + vldm twiddle_ptr!, {s8-s22} + + add.w tmp, poly, #8*strincr + vmov s8, tmp + 1: + vmov s23, poly + // load a1, a3, ..., a15 + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // NTT on a1, a3, ..., a15 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // multiply coeffs by layer 4 twiddles for later use + // vmov twiddle1, s15 + vmov twiddle2, s16 + // mul_twiddle_plant poly0, twiddle1, tmp, q, qa // could be omitted but kept for reduction only + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + // 0.5q + // ---------- + + vmov poly, s23 + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // NTT on a0, a2, ..., a14 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + // 1,3,5,7: <5q; 0,2,4,6:<1q + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle2, s1 // load a3 + uadd16 tmp, poly1, twiddle2 + usub16 poly1, poly1, twiddle2 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle2, s3 // load a7 + uadd16 tmp, poly3, twiddle2 + usub16 poly3, poly3, twiddle2 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle2, s5 // load a11 + uadd16 tmp, poly5, twiddle2 + usub16 poly5, poly5, twiddle2 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle2, s7 // load a15 + uadd16 tmp, poly7, twiddle2 + usub16 poly7, poly7, twiddle2 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + //1,3,5,7: < 5.5q + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle2, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle2, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle2, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle2, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle2, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle2, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle2, poly0, poly1 + str.w twiddle2, [poly, #offset] + str.w tmp, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) + //0,2,4,6: < 1.5q + vmov tmp, s8 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance*16 + .equ strincr, 4 + + // ITER 0 + vmov s6, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + vldm twiddle_ptr!, {s0-s5} + movw qa, #24608 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s1, s3, s4, s5, twiddle1, twiddle2, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + // ITER 1-15 + add.w tmp, poly, #strincr*3*(5) + vmov s14, tmp + 2: + vmov s6, poly + // polys upto 5.5q + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_inv_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + vmov tmp, s14 + cmp.w poly, tmp + bne.w 2b + + vpop.w {s16-s23} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + + +################################### +#### small point-multiplication#### +#### r0: out; r1: in; r2: zetas#### +################################### +.align 2 +.global small_pointmul_asm_769 +.type small_pointmul_asm_769, %function +small_pointmul_asm_769: + push.w {r4-r11, lr} + + movw r14, #24608 // qa + movt r12, #769 // q + .equ width, 4 + + + add.w r3, r2, #64*width + _point_mul_16_loop: + + ldr.w r7, [r1, #2*width] + ldr.w r8, [r1, #3*width] + ldr.w r9, [r2, #1*width] + ldr.w r5, [r1, #1*width] + ldr.w r4, [r1], #4*width + ldr.w r6, [r2], #2*width + + smulwt r10, r6, r4 + smlabt r10, r10, r12, r14 + pkhbt r4, r4, r10 + + neg.w r6, r6 + + smulwt r10, r6, r5 + smlabt r10, r10, r12, r14 + pkhbt r5, r5, r10 + + str.w r5, [r0, #1*width] + str.w r4, [r0], #2*width + + smulwt r10, r9, r7 + smlabt r10, r10, r12, r14 + pkhbt r7, r7, r10 + + neg.w r9, r9 + + smulwt r10, r9, r8 + smlabt r10, r10, r12, r14 + pkhbt r8, r8, r10 + + str.w r8, [r0, #1*width] + str.w r7, [r0], #2*width + + cmp.w r2, r3 + bne.w _point_mul_16_loop + + pop.w {r4-r11, pc} + + +#### r0: out; r1: a; r2: b; r3: bprime + .align 2 +.global small_asymmetric_mul_asm_769 +.type small_asymmetric_mul_asm_769, %function +small_asymmetric_mul_asm_769: + push.w {r4-r11, lr} + + movw r14, #24608 // qa + movt r12, #769 // q + movw r11, #64769 + movt r11, #58632 // qinv + .equ width, 4 + add.w r10, r0, #256*2 + _asymmetric_mul_16_loop: + ldr.w r7, [r1, #width] + ldr.w r4, [r1], #2*width + ldr.w r8, [r2, #width] + ldr.w r5, [r2], #2*width + ldr.w r9, [r3, #width] + ldr.w r6, [r3], #2*width + + smuad r6, r4, r6 + plant_red r12, r14, r11, r6 + smuadx r5, r4, r5 + plant_red r12, r14, r11, r5 + + pkhtb r5, r5, r6, asr#16 + str.w r5, [r0], #width + + smuad r6, r7, r9 + plant_red r12, r14, r11, r6 + smuadx r8, r7, r8 + plant_red r12, r14, r11, r8 + + pkhtb r8, r8, r6, asr#16 + str.w r8, [r0], #width + + cmp.w r0, r10 + bne.w _asymmetric_mul_16_loop + + pop.w {r4-r11, pc} \ No newline at end of file From 149bfc7bce5e85abf1a85c177c621fe9173e9257 Mon Sep 17 00:00:00 2001 From: Amin Abdulrahman Date: Tue, 16 Apr 2024 03:00:42 +0200 Subject: [PATCH 089/107] Dilithium/ML-DSA Stack Optimizations (#340) * Init dilithium3 stack optimized variant * Start stack optimization [Passing] * Based on ideas from https://eprint.iacr.org/2022/323.pdf, based on code by Matthias J. Kannwischer * Sample A on-the-fly * Compressed c * Schoolbook mul for ct1 * Compress w * Eliminate z, y * Eliminate cp * Eliminate s1, s2 * Eliminate second poly needed for A*y * Note: Reverts poly_uniform_pointwise_montgomery_polywadd_stack to prior state * Inline sampling uniform and uniform_gamma1 * Inline hint generation * Inline polyw subtraction * Refactor decompose to high/lowbits * Inline Keccak state * Shared buffer for polynomials * rm 257 FFT * Union for small and big poly * Eliminate some smaller buffers * Remove asym small mul * Stack friendly uniform_gamma1 w/o add * Stack optimized Dilithium{2,5} * Switch to Plantard-based 769 NTT * First batch of stack opt for Verify * On-the-fly matrix generation * Schoolbook for ct1 * Challenge compression * On-the-fly unpacking for z, h * Compress w * rm tmp poly, subtract on wcomp * Verify Stack Optimizations * Stack friendly hint decoding * Eliminate second full poly * Remove K-loop from hint unpacking * rm buffers/unionize in Verify * Stack opt key pair * Minor clean up * Overlap buffers * Stack optimized challenge generation * Match 769 Plantard to m4f code * update skiplist * update benchmarks --------- Co-authored-by: Matthias J. Kannwischer --- benchmarks.csv | 32 +- benchmarks.md | 34 +- crypto_sign/dilithium2/m4fstack/api.h | 1 + crypto_sign/dilithium2/m4fstack/config.h | 1 + crypto_sign/dilithium2/m4fstack/macros.i | 1 + .../dilithium2/m4fstack/macros_smallntt.i | 1 + crypto_sign/dilithium2/m4fstack/ntt.S | 1 + crypto_sign/dilithium2/m4fstack/ntt.h | 1 + crypto_sign/dilithium2/m4fstack/packing.c | 1 + crypto_sign/dilithium2/m4fstack/packing.h | 1 + crypto_sign/dilithium2/m4fstack/params.h | 1 + .../dilithium2/m4fstack/pointwise_mont.h | 1 + .../dilithium2/m4fstack/pointwise_mont.s | 1 + crypto_sign/dilithium2/m4fstack/poly.c | 1 + crypto_sign/dilithium2/m4fstack/poly.h | 1 + crypto_sign/dilithium2/m4fstack/polyvec.c | 1 + crypto_sign/dilithium2/m4fstack/polyvec.h | 1 + crypto_sign/dilithium2/m4fstack/reduce.h | 1 + crypto_sign/dilithium2/m4fstack/rounding.c | 1 + crypto_sign/dilithium2/m4fstack/rounding.h | 1 + crypto_sign/dilithium2/m4fstack/sign.c | 1 + crypto_sign/dilithium2/m4fstack/sign.h | 1 + crypto_sign/dilithium2/m4fstack/smallntt.h | 1 + .../dilithium2/m4fstack/smallntt_769.S | 1 + crypto_sign/dilithium2/m4fstack/smallpoly.c | 1 + crypto_sign/dilithium2/m4fstack/smallpoly.h | 1 + crypto_sign/dilithium2/m4fstack/stack.c | 1 + crypto_sign/dilithium2/m4fstack/stack.h | 1 + .../dilithium2/m4fstack/symmetric-shake.c | 1 + crypto_sign/dilithium2/m4fstack/symmetric.h | 1 + crypto_sign/dilithium2/m4fstack/vector.h | 1 + crypto_sign/dilithium2/m4fstack/vector.s | 1 + crypto_sign/dilithium3/m4fstack/api.h | 26 + crypto_sign/dilithium3/m4fstack/config.h | 7 + crypto_sign/dilithium3/m4fstack/macros.i | 191 ++++ .../dilithium3/m4fstack/macros_smallntt.i | 91 ++ crypto_sign/dilithium3/m4fstack/ntt.S | 402 +++++++++ crypto_sign/dilithium3/m4fstack/ntt.h | 13 + crypto_sign/dilithium3/m4fstack/packing.c | 286 ++++++ crypto_sign/dilithium3/m4fstack/packing.h | 55 ++ crypto_sign/dilithium3/m4fstack/params.h | 83 ++ .../dilithium3/m4fstack/pointwise_mont.h | 13 + .../dilithium3/m4fstack/pointwise_mont.s | 128 +++ crypto_sign/dilithium3/m4fstack/poly.c | 851 ++++++++++++++++++ crypto_sign/dilithium3/m4fstack/poly.h | 82 ++ crypto_sign/dilithium3/m4fstack/polyvec.c | 429 +++++++++ crypto_sign/dilithium3/m4fstack/polyvec.h | 99 ++ crypto_sign/dilithium3/m4fstack/reduce.h | 79 ++ crypto_sign/dilithium3/m4fstack/rounding.c | 102 +++ crypto_sign/dilithium3/m4fstack/rounding.h | 19 + crypto_sign/dilithium3/m4fstack/sign.c | 484 ++++++++++ crypto_sign/dilithium3/m4fstack/sign.h | 37 + crypto_sign/dilithium3/m4fstack/smallntt.h | 47 + .../dilithium3/m4fstack/smallntt_769.S | 691 ++++++++++++++ crypto_sign/dilithium3/m4fstack/smallpoly.c | 83 ++ crypto_sign/dilithium3/m4fstack/smallpoly.h | 27 + crypto_sign/dilithium3/m4fstack/stack.c | 715 +++++++++++++++ crypto_sign/dilithium3/m4fstack/stack.h | 69 ++ .../dilithium3/m4fstack/symmetric-shake.c | 28 + crypto_sign/dilithium3/m4fstack/symmetric.h | 65 ++ crypto_sign/dilithium3/m4fstack/vector.h | 20 + crypto_sign/dilithium3/m4fstack/vector.s | 210 +++++ crypto_sign/dilithium5/m4fstack/api.h | 1 + crypto_sign/dilithium5/m4fstack/config.h | 1 + crypto_sign/dilithium5/m4fstack/macros.i | 1 + .../dilithium5/m4fstack/macros_smallntt.i | 1 + crypto_sign/dilithium5/m4fstack/ntt.S | 1 + crypto_sign/dilithium5/m4fstack/ntt.h | 1 + crypto_sign/dilithium5/m4fstack/packing.c | 1 + crypto_sign/dilithium5/m4fstack/packing.h | 1 + crypto_sign/dilithium5/m4fstack/params.h | 1 + .../dilithium5/m4fstack/pointwise_mont.h | 1 + .../dilithium5/m4fstack/pointwise_mont.s | 1 + crypto_sign/dilithium5/m4fstack/poly.c | 1 + crypto_sign/dilithium5/m4fstack/poly.h | 1 + crypto_sign/dilithium5/m4fstack/polyvec.c | 1 + crypto_sign/dilithium5/m4fstack/polyvec.h | 1 + crypto_sign/dilithium5/m4fstack/reduce.h | 1 + crypto_sign/dilithium5/m4fstack/rounding.c | 1 + crypto_sign/dilithium5/m4fstack/rounding.h | 1 + crypto_sign/dilithium5/m4fstack/sign.c | 1 + crypto_sign/dilithium5/m4fstack/sign.h | 1 + crypto_sign/dilithium5/m4fstack/smallntt.h | 1 + .../dilithium5/m4fstack/smallntt_769.S | 1 + crypto_sign/dilithium5/m4fstack/smallpoly.c | 1 + crypto_sign/dilithium5/m4fstack/smallpoly.h | 1 + crypto_sign/dilithium5/m4fstack/stack.c | 1 + crypto_sign/dilithium5/m4fstack/stack.h | 1 + .../dilithium5/m4fstack/symmetric-shake.c | 1 + crypto_sign/dilithium5/m4fstack/symmetric.h | 1 + crypto_sign/dilithium5/m4fstack/vector.h | 1 + crypto_sign/dilithium5/m4fstack/vector.s | 1 + skiplist.py | 3 + 93 files changed, 5540 insertions(+), 21 deletions(-) create mode 120000 crypto_sign/dilithium2/m4fstack/api.h create mode 120000 crypto_sign/dilithium2/m4fstack/config.h create mode 120000 crypto_sign/dilithium2/m4fstack/macros.i create mode 120000 crypto_sign/dilithium2/m4fstack/macros_smallntt.i create mode 120000 crypto_sign/dilithium2/m4fstack/ntt.S create mode 120000 crypto_sign/dilithium2/m4fstack/ntt.h create mode 120000 crypto_sign/dilithium2/m4fstack/packing.c create mode 120000 crypto_sign/dilithium2/m4fstack/packing.h create mode 120000 crypto_sign/dilithium2/m4fstack/params.h create mode 120000 crypto_sign/dilithium2/m4fstack/pointwise_mont.h create mode 120000 crypto_sign/dilithium2/m4fstack/pointwise_mont.s create mode 120000 crypto_sign/dilithium2/m4fstack/poly.c create mode 120000 crypto_sign/dilithium2/m4fstack/poly.h create mode 120000 crypto_sign/dilithium2/m4fstack/polyvec.c create mode 120000 crypto_sign/dilithium2/m4fstack/polyvec.h create mode 120000 crypto_sign/dilithium2/m4fstack/reduce.h create mode 120000 crypto_sign/dilithium2/m4fstack/rounding.c create mode 120000 crypto_sign/dilithium2/m4fstack/rounding.h create mode 120000 crypto_sign/dilithium2/m4fstack/sign.c create mode 120000 crypto_sign/dilithium2/m4fstack/sign.h create mode 120000 crypto_sign/dilithium2/m4fstack/smallntt.h create mode 120000 crypto_sign/dilithium2/m4fstack/smallntt_769.S create mode 120000 crypto_sign/dilithium2/m4fstack/smallpoly.c create mode 120000 crypto_sign/dilithium2/m4fstack/smallpoly.h create mode 120000 crypto_sign/dilithium2/m4fstack/stack.c create mode 120000 crypto_sign/dilithium2/m4fstack/stack.h create mode 120000 crypto_sign/dilithium2/m4fstack/symmetric-shake.c create mode 120000 crypto_sign/dilithium2/m4fstack/symmetric.h create mode 120000 crypto_sign/dilithium2/m4fstack/vector.h create mode 120000 crypto_sign/dilithium2/m4fstack/vector.s create mode 100644 crypto_sign/dilithium3/m4fstack/api.h create mode 100644 crypto_sign/dilithium3/m4fstack/config.h create mode 100644 crypto_sign/dilithium3/m4fstack/macros.i create mode 100644 crypto_sign/dilithium3/m4fstack/macros_smallntt.i create mode 100644 crypto_sign/dilithium3/m4fstack/ntt.S create mode 100644 crypto_sign/dilithium3/m4fstack/ntt.h create mode 100644 crypto_sign/dilithium3/m4fstack/packing.c create mode 100644 crypto_sign/dilithium3/m4fstack/packing.h create mode 100644 crypto_sign/dilithium3/m4fstack/params.h create mode 100644 crypto_sign/dilithium3/m4fstack/pointwise_mont.h create mode 100644 crypto_sign/dilithium3/m4fstack/pointwise_mont.s create mode 100644 crypto_sign/dilithium3/m4fstack/poly.c create mode 100644 crypto_sign/dilithium3/m4fstack/poly.h create mode 100644 crypto_sign/dilithium3/m4fstack/polyvec.c create mode 100644 crypto_sign/dilithium3/m4fstack/polyvec.h create mode 100644 crypto_sign/dilithium3/m4fstack/reduce.h create mode 100644 crypto_sign/dilithium3/m4fstack/rounding.c create mode 100644 crypto_sign/dilithium3/m4fstack/rounding.h create mode 100644 crypto_sign/dilithium3/m4fstack/sign.c create mode 100644 crypto_sign/dilithium3/m4fstack/sign.h create mode 100644 crypto_sign/dilithium3/m4fstack/smallntt.h create mode 100644 crypto_sign/dilithium3/m4fstack/smallntt_769.S create mode 100644 crypto_sign/dilithium3/m4fstack/smallpoly.c create mode 100644 crypto_sign/dilithium3/m4fstack/smallpoly.h create mode 100644 crypto_sign/dilithium3/m4fstack/stack.c create mode 100644 crypto_sign/dilithium3/m4fstack/stack.h create mode 100644 crypto_sign/dilithium3/m4fstack/symmetric-shake.c create mode 100644 crypto_sign/dilithium3/m4fstack/symmetric.h create mode 100644 crypto_sign/dilithium3/m4fstack/vector.h create mode 100644 crypto_sign/dilithium3/m4fstack/vector.s create mode 120000 crypto_sign/dilithium5/m4fstack/api.h create mode 120000 crypto_sign/dilithium5/m4fstack/config.h create mode 120000 crypto_sign/dilithium5/m4fstack/macros.i create mode 120000 crypto_sign/dilithium5/m4fstack/macros_smallntt.i create mode 120000 crypto_sign/dilithium5/m4fstack/ntt.S create mode 120000 crypto_sign/dilithium5/m4fstack/ntt.h create mode 120000 crypto_sign/dilithium5/m4fstack/packing.c create mode 120000 crypto_sign/dilithium5/m4fstack/packing.h create mode 120000 crypto_sign/dilithium5/m4fstack/params.h create mode 120000 crypto_sign/dilithium5/m4fstack/pointwise_mont.h create mode 120000 crypto_sign/dilithium5/m4fstack/pointwise_mont.s create mode 120000 crypto_sign/dilithium5/m4fstack/poly.c create mode 120000 crypto_sign/dilithium5/m4fstack/poly.h create mode 120000 crypto_sign/dilithium5/m4fstack/polyvec.c create mode 120000 crypto_sign/dilithium5/m4fstack/polyvec.h create mode 120000 crypto_sign/dilithium5/m4fstack/reduce.h create mode 120000 crypto_sign/dilithium5/m4fstack/rounding.c create mode 120000 crypto_sign/dilithium5/m4fstack/rounding.h create mode 120000 crypto_sign/dilithium5/m4fstack/sign.c create mode 120000 crypto_sign/dilithium5/m4fstack/sign.h create mode 120000 crypto_sign/dilithium5/m4fstack/smallntt.h create mode 120000 crypto_sign/dilithium5/m4fstack/smallntt_769.S create mode 120000 crypto_sign/dilithium5/m4fstack/smallpoly.c create mode 120000 crypto_sign/dilithium5/m4fstack/smallpoly.h create mode 120000 crypto_sign/dilithium5/m4fstack/stack.c create mode 120000 crypto_sign/dilithium5/m4fstack/stack.h create mode 120000 crypto_sign/dilithium5/m4fstack/symmetric-shake.c create mode 120000 crypto_sign/dilithium5/m4fstack/symmetric.h create mode 120000 crypto_sign/dilithium5/m4fstack/vector.h create mode 120000 crypto_sign/dilithium5/m4fstack/vector.s diff --git a/benchmarks.csv b/benchmarks.csv index 981accb6..e3bb1bbb 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -42,12 +42,15 @@ cross-sha3-r-sdpg-1-fast (10 executions),ref,290136,287742,297758,29963868,29960 cross-sha3-r-sdpg-1-small (10 executions),ref,290135,287741,297757,102853622,102847774,102861948,75137510,75126803,75159685 cross-sha3-r-sdpg-3-fast (10 executions),ref,627948,625525,637639,43573841,43565461,43582933,27513830,27493024,27525746 cross-sha3-r-sdpg-5-fast (10 executions),ref,1146280,1142409,1153794,93557878,93547167,93566329,59948216,59857434,60043852 -dilithium2 (90 executions),clean,1873447,1838554,1903845,7846622,3321671,28761609,2062804,2062332,2063181 -dilithium2 (100 executions),m4f,1427684,1390524,1466437,4219137,1813668,12587382,1417706,1417251,1418128 +dilithium2 (1000 executions),clean,1874167,1827645,1914566,7493877,3321630,40762756,2062795,2062255,2063222 +dilithium2 (1000 executions),m4f,1426036,1379636,1466394,3807970,1813656,18528070,1417745,1417203,1418192 +dilithium2 (1000 executions),m4fstack,1801523,1684895,1902114,12170976,3900911,86281518,3241353,3194028,3281144 dilithium3 (1000 executions),clean,3205551,3204090,3207411,12696585,5097364,74392293,3376992,3376581,3377393 dilithium3 (1000 executions),m4f,2515969,2514498,2517634,5884832,2917322,25268693,2411257,2410858,2411717 -dilithium5 (90 executions),clean,5346066,5287239,5395626,15205929,7953360,49173429,5609664,5609137,5610119 -dilithium5 (100 executions),m4f,4273211,4210308,4329697,8062110,4882708,18398575,4185407,4184878,4185954 +dilithium3 (1000 executions),m4fstack,3412759,3406659,3419247,23673016,6733971,145803146,5733307,5688893,5778120 +dilithium5 (1000 executions),clean,5341477,5286872,5395822,15710371,7953367,75940093,5609679,5609217,5610183 +dilithium5 (1000 executions),m4f,4275029,4210286,4329519,7977781,4882524,25936176,4185417,4184925,4185896 +dilithium5 (1000 executions),m4fstack,5816287,5474236,6115061,33452872,11170780,185259803,9912851,9845789,9981834 falcon-1024 (10 executions),m4-ct,354880005,284902033,635131652,87741288,87506676,87922628,991320,982548,997219 falcon-1024 (10 executions),opt-ct,555202324,284912829,1157528581,87710190,87606677,87841235,993584,983066,997523 falcon-1024 (10 executions),opt-leaktime,438412062,334858742,625013074,80139483,79891200,80551967,994127,984891,997390 @@ -190,11 +193,14 @@ cross-sha3-r-sdpg-1-small,ref,2328,466400,245512,,,,,, cross-sha3-r-sdpg-3-fast,ref,4032,205080,108236,,,,,, cross-sha3-r-sdpg-5-fast,ref,6824,398600,213436,,,,,, dilithium2,clean,38304,51968,36192,,,,,, -dilithium2,m4f,38296,49416,36184,,,,,, +dilithium2,m4f,38296,49416,36220,,,,,, +dilithium2,m4fstack,4408,5072,2704,,,,,, dilithium3,clean,60832,79616,57728,,,,,, dilithium3,m4f,60824,68864,57720,,,,,, +dilithium3,m4fstack,4408,6608,2704,,,,,, dilithium5,clean,97696,122724,92940,,,,,, -dilithium5,m4f,97688,116076,92824,,,,,, +dilithium5,m4f,97688,116076,92932,,,,,, +dilithium5,m4fstack,4408,8136,2712,,,,,, falcon-1024,clean,34988,84604,8784,,,,,, falcon-1024,m4-ct,1156,2508,376,,,,,, falcon-1024,opt-ct,1156,2508,376,,,,,, @@ -339,12 +345,15 @@ cross-sha3-r-sdpg-1-fast,ref,71.8,74.8,77.1,,,,,, cross-sha3-r-sdpg-1-small,ref,71.8,74.7,78.4,,,,,, cross-sha3-r-sdpg-3-fast,ref,71.7,68.2,68.7,,,,,, cross-sha3-r-sdpg-5-fast,ref,71.1,66.1,66.8,,,,,, -dilithium2,clean,60.9,30.2,52.9,,,,,, -dilithium2,m4f,79.9,62.2,76.8,,,,,, +dilithium2,clean,61.0,30.9,52.9,,,,,, +dilithium2,m4f,79.9,60.6,76.8,,,,,, +dilithium2,m4fstack,74.8,55.2,40.8,,,,,, dilithium3,clean,64.7,31.3,56.8,,,,,, dilithium3,m4f,82.3,60.3,79.4,,,,,, -dilithium5,clean,67.0,38.4,61.1,,,,,, -dilithium5,m4f,83.4,63.5,81.7,,,,,, +dilithium3,m4fstack,77.1,54.6,41.0,,,,,, +dilithium5,clean,67.0,35.7,61.1,,,,,, +dilithium5,m4f,83.5,65.0,81.7,,,,,, +dilithium5,m4fstack,76.1,54.5,42.6,,,,,, falcon-1024,clean,6.5,0.3,23.7,,,,,, falcon-1024,m4-ct,7.4,0.4,32.4,,,,,, falcon-1024,opt-ct,11.7,0.4,32.2,,,,,, @@ -490,10 +499,13 @@ cross-sha3-r-sdpg-3-fast,ref,19689,0,208,19897,,,,, cross-sha3-r-sdpg-5-fast,ref,18593,0,208,18801,,,,, dilithium2,clean,8064,0,0,8064,,,,, dilithium2,m4f,18596,0,0,18596,,,,, +dilithium2,m4fstack,24184,0,0,24184,,,,, dilithium3,clean,7580,0,0,7580,,,,, dilithium3,m4f,18588,0,0,18588,,,,, +dilithium3,m4fstack,23448,0,0,23448,,,,, dilithium5,clean,7808,0,0,7808,,,,, dilithium5,m4f,18468,0,0,18468,,,,, +dilithium5,m4fstack,23820,0,0,23820,,,,, falcon-1024,clean,82647,0,0,82647,,,,, falcon-1024,m4-ct,81825,0,79872,161697,,,,, falcon-1024,opt-ct,81825,0,79872,161697,,,,, diff --git a/benchmarks.md b/benchmarks.md index 5574fe2c..5aef4137 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -44,12 +44,15 @@ | cross-sha3-r-sdpg-1-small (10 executions) | ref | AVG: 290,135
MIN: 287,741
MAX: 297,757 | AVG: 102,853,622
MIN: 102,847,774
MAX: 102,861,948 | AVG: 75,137,510
MIN: 75,126,803
MAX: 75,159,685 | | cross-sha3-r-sdpg-3-fast (10 executions) | ref | AVG: 627,948
MIN: 625,525
MAX: 637,639 | AVG: 43,573,841
MIN: 43,565,461
MAX: 43,582,933 | AVG: 27,513,830
MIN: 27,493,024
MAX: 27,525,746 | | cross-sha3-r-sdpg-5-fast (10 executions) | ref | AVG: 1,146,280
MIN: 1,142,409
MAX: 1,153,794 | AVG: 93,557,878
MIN: 93,547,167
MAX: 93,566,329 | AVG: 59,948,216
MIN: 59,857,434
MAX: 60,043,852 | -| dilithium2 (90 executions) | clean | AVG: 1,873,447
MIN: 1,838,554
MAX: 1,903,845 | AVG: 7,846,622
MIN: 3,321,671
MAX: 28,761,609 | AVG: 2,062,804
MIN: 2,062,332
MAX: 2,063,181 | -| dilithium2 (100 executions) | m4f | AVG: 1,427,684
MIN: 1,390,524
MAX: 1,466,437 | AVG: 4,219,137
MIN: 1,813,668
MAX: 12,587,382 | AVG: 1,417,706
MIN: 1,417,251
MAX: 1,418,128 | +| dilithium2 (1000 executions) | clean | AVG: 1,874,167
MIN: 1,827,645
MAX: 1,914,566 | AVG: 7,493,877
MIN: 3,321,630
MAX: 40,762,756 | AVG: 2,062,795
MIN: 2,062,255
MAX: 2,063,222 | +| dilithium2 (1000 executions) | m4f | AVG: 1,426,036
MIN: 1,379,636
MAX: 1,466,394 | AVG: 3,807,970
MIN: 1,813,656
MAX: 18,528,070 | AVG: 1,417,745
MIN: 1,417,203
MAX: 1,418,192 | +| dilithium2 (1000 executions) | m4fstack | AVG: 1,801,523
MIN: 1,684,895
MAX: 1,902,114 | AVG: 12,170,976
MIN: 3,900,911
MAX: 86,281,518 | AVG: 3,241,353
MIN: 3,194,028
MAX: 3,281,144 | | dilithium3 (1000 executions) | clean | AVG: 3,205,551
MIN: 3,204,090
MAX: 3,207,411 | AVG: 12,696,585
MIN: 5,097,364
MAX: 74,392,293 | AVG: 3,376,992
MIN: 3,376,581
MAX: 3,377,393 | | dilithium3 (1000 executions) | m4f | AVG: 2,515,969
MIN: 2,514,498
MAX: 2,517,634 | AVG: 5,884,832
MIN: 2,917,322
MAX: 25,268,693 | AVG: 2,411,257
MIN: 2,410,858
MAX: 2,411,717 | -| dilithium5 (90 executions) | clean | AVG: 5,346,066
MIN: 5,287,239
MAX: 5,395,626 | AVG: 15,205,929
MIN: 7,953,360
MAX: 49,173,429 | AVG: 5,609,664
MIN: 5,609,137
MAX: 5,610,119 | -| dilithium5 (100 executions) | m4f | AVG: 4,273,211
MIN: 4,210,308
MAX: 4,329,697 | AVG: 8,062,110
MIN: 4,882,708
MAX: 18,398,575 | AVG: 4,185,407
MIN: 4,184,878
MAX: 4,185,954 | +| dilithium3 (1000 executions) | m4fstack | AVG: 3,412,759
MIN: 3,406,659
MAX: 3,419,247 | AVG: 23,673,016
MIN: 6,733,971
MAX: 145,803,146 | AVG: 5,733,307
MIN: 5,688,893
MAX: 5,778,120 | +| dilithium5 (1000 executions) | clean | AVG: 5,341,477
MIN: 5,286,872
MAX: 5,395,822 | AVG: 15,710,371
MIN: 7,953,367
MAX: 75,940,093 | AVG: 5,609,679
MIN: 5,609,217
MAX: 5,610,183 | +| dilithium5 (1000 executions) | m4f | AVG: 4,275,029
MIN: 4,210,286
MAX: 4,329,519 | AVG: 7,977,781
MIN: 4,882,524
MAX: 25,936,176 | AVG: 4,185,417
MIN: 4,184,925
MAX: 4,185,896 | +| dilithium5 (1000 executions) | m4fstack | AVG: 5,816,287
MIN: 5,474,236
MAX: 6,115,061 | AVG: 33,452,872
MIN: 11,170,780
MAX: 185,259,803 | AVG: 9,912,851
MIN: 9,845,789
MAX: 9,981,834 | | falcon-1024 (10 executions) | m4-ct | AVG: 354,880,005
MIN: 284,902,033
MAX: 635,131,652 | AVG: 87,741,288
MIN: 87,506,676
MAX: 87,922,628 | AVG: 991,320
MIN: 982,548
MAX: 997,219 | | falcon-1024 (10 executions) | opt-ct | AVG: 555,202,324
MIN: 284,912,829
MAX: 1,157,528,581 | AVG: 87,710,190
MIN: 87,606,677
MAX: 87,841,235 | AVG: 993,584
MIN: 983,066
MAX: 997,523 | | falcon-1024 (10 executions) | opt-leaktime | AVG: 438,412,062
MIN: 334,858,742
MAX: 625,013,074 | AVG: 80,139,483
MIN: 79,891,200
MAX: 80,551,967 | AVG: 994,127
MIN: 984,891
MAX: 997,390 | @@ -194,11 +197,14 @@ | cross-sha3-r-sdpg-3-fast | ref | 4,032 | 205,080 | 108,236 | | cross-sha3-r-sdpg-5-fast | ref | 6,824 | 398,600 | 213,436 | | dilithium2 | clean | 38,304 | 51,968 | 36,192 | -| dilithium2 | m4f | 38,296 | 49,416 | 36,184 | +| dilithium2 | m4f | 38,296 | 49,416 | 36,220 | +| dilithium2 | m4fstack | 4,408 | 5,072 | 2,704 | | dilithium3 | clean | 60,832 | 79,616 | 57,728 | | dilithium3 | m4f | 60,824 | 68,864 | 57,720 | +| dilithium3 | m4fstack | 4,408 | 6,608 | 2,704 | | dilithium5 | clean | 97,696 | 122,724 | 92,940 | -| dilithium5 | m4f | 97,688 | 116,076 | 92,824 | +| dilithium5 | m4f | 97,688 | 116,076 | 92,932 | +| dilithium5 | m4fstack | 4,408 | 8,136 | 2,712 | | falcon-1024 | clean | 34,988 | 84,604 | 8,784 | | falcon-1024 | m4-ct | 1,156 | 2,508 | 376 | | falcon-1024 | opt-ct | 1,156 | 2,508 | 376 | @@ -345,12 +351,15 @@ | cross-sha3-r-sdpg-1-small | ref | 71.8% | 74.7% | 78.4% | | cross-sha3-r-sdpg-3-fast | ref | 71.7% | 68.2% | 68.7% | | cross-sha3-r-sdpg-5-fast | ref | 71.1% | 66.1% | 66.8% | -| dilithium2 | clean | 60.9% | 30.2% | 52.9% | -| dilithium2 | m4f | 79.9% | 62.2% | 76.8% | +| dilithium2 | clean | 61.0% | 30.9% | 52.9% | +| dilithium2 | m4f | 79.9% | 60.6% | 76.8% | +| dilithium2 | m4fstack | 74.8% | 55.2% | 40.8% | | dilithium3 | clean | 64.7% | 31.3% | 56.8% | -| dilithium3 | m4f | 82.3% | 60.3% | 79.4% | -| dilithium5 | clean | 67.0% | 38.4% | 61.1% | -| dilithium5 | m4f | 83.4% | 63.5% | 81.7% | +| dilithium3 | m4f | 82.3% | 61.4% | 79.4% | +| dilithium3 | m4fstack | 77.1% | 54.6% | 41.0% | +| dilithium5 | clean | 67.0% | 35.7% | 61.1% | +| dilithium5 | m4f | 83.5% | 65.0% | 81.7% | +| dilithium5 | m4fstack | 76.1% | 54.5% | 42.6% | | falcon-1024 | clean | 6.5% | 0.3% | 23.7% | | falcon-1024 | m4-ct | 7.4% | 0.4% | 32.4% | | falcon-1024 | opt-ct | 11.7% | 0.4% | 32.2% | @@ -498,10 +507,13 @@ | cross-sha3-r-sdpg-5-fast | ref | 18,593 | 0 | 208 | 18,801 | | dilithium2 | clean | 8,064 | 0 | 0 | 8,064 | | dilithium2 | m4f | 18,596 | 0 | 0 | 18,596 | +| dilithium2 | m4fstack | 24,184 | 0 | 0 | 24,184 | | dilithium3 | clean | 7,580 | 0 | 0 | 7,580 | | dilithium3 | m4f | 18,588 | 0 | 0 | 18,588 | +| dilithium3 | m4fstack | 23,448 | 0 | 0 | 23,448 | | dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | | dilithium5 | m4f | 18,468 | 0 | 0 | 18,468 | +| dilithium5 | m4fstack | 23,820 | 0 | 0 | 23,820 | | falcon-1024 | clean | 82,647 | 0 | 0 | 82,647 | | falcon-1024 | m4-ct | 81,825 | 0 | 79,872 | 161,697 | | falcon-1024 | opt-ct | 81,825 | 0 | 79,872 | 161,697 | diff --git a/crypto_sign/dilithium2/m4fstack/api.h b/crypto_sign/dilithium2/m4fstack/api.h new file mode 120000 index 00000000..d29362d1 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/api.h @@ -0,0 +1 @@ +../m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/config.h b/crypto_sign/dilithium2/m4fstack/config.h new file mode 120000 index 00000000..f3892d90 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/config.h @@ -0,0 +1 @@ +../m4f/config.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/macros.i b/crypto_sign/dilithium2/m4fstack/macros.i new file mode 120000 index 00000000..d615b854 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/macros.i @@ -0,0 +1 @@ +../m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/macros_smallntt.i b/crypto_sign/dilithium2/m4fstack/macros_smallntt.i new file mode 120000 index 00000000..fc731f12 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/macros_smallntt.i @@ -0,0 +1 @@ +../../dilithium3/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/ntt.S b/crypto_sign/dilithium2/m4fstack/ntt.S new file mode 120000 index 00000000..40cd5d40 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/ntt.S @@ -0,0 +1 @@ +../m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/ntt.h b/crypto_sign/dilithium2/m4fstack/ntt.h new file mode 120000 index 00000000..8e99caeb --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/ntt.h @@ -0,0 +1 @@ +../m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/packing.c b/crypto_sign/dilithium2/m4fstack/packing.c new file mode 120000 index 00000000..1052fe26 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/packing.c @@ -0,0 +1 @@ +../m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/packing.h b/crypto_sign/dilithium2/m4fstack/packing.h new file mode 120000 index 00000000..643cc32a --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/packing.h @@ -0,0 +1 @@ +../m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/params.h b/crypto_sign/dilithium2/m4fstack/params.h new file mode 120000 index 00000000..1f91a364 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/params.h @@ -0,0 +1 @@ +../m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/pointwise_mont.h b/crypto_sign/dilithium2/m4fstack/pointwise_mont.h new file mode 120000 index 00000000..32558852 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/pointwise_mont.h @@ -0,0 +1 @@ +../m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/pointwise_mont.s b/crypto_sign/dilithium2/m4fstack/pointwise_mont.s new file mode 120000 index 00000000..3597ffdc --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/pointwise_mont.s @@ -0,0 +1 @@ +../m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/poly.c b/crypto_sign/dilithium2/m4fstack/poly.c new file mode 120000 index 00000000..2544e75b --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/poly.c @@ -0,0 +1 @@ +../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/poly.h b/crypto_sign/dilithium2/m4fstack/poly.h new file mode 120000 index 00000000..7ef70e53 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/poly.h @@ -0,0 +1 @@ +../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/polyvec.c b/crypto_sign/dilithium2/m4fstack/polyvec.c new file mode 120000 index 00000000..569a9a1b --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/polyvec.c @@ -0,0 +1 @@ +../m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/polyvec.h b/crypto_sign/dilithium2/m4fstack/polyvec.h new file mode 120000 index 00000000..d02c99c3 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/polyvec.h @@ -0,0 +1 @@ +../m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/reduce.h b/crypto_sign/dilithium2/m4fstack/reduce.h new file mode 120000 index 00000000..45fbf228 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/reduce.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/rounding.c b/crypto_sign/dilithium2/m4fstack/rounding.c new file mode 120000 index 00000000..ec780689 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/rounding.c @@ -0,0 +1 @@ +../m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/rounding.h b/crypto_sign/dilithium2/m4fstack/rounding.h new file mode 120000 index 00000000..e64114bc --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/rounding.h @@ -0,0 +1 @@ +../m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/sign.c b/crypto_sign/dilithium2/m4fstack/sign.c new file mode 120000 index 00000000..ae3b84fa --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/sign.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/sign.h b/crypto_sign/dilithium2/m4fstack/sign.h new file mode 120000 index 00000000..551f979a --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/sign.h @@ -0,0 +1 @@ +../m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallntt.h b/crypto_sign/dilithium2/m4fstack/smallntt.h new file mode 120000 index 00000000..cfd626b9 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallntt.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallntt_769.S b/crypto_sign/dilithium2/m4fstack/smallntt_769.S new file mode 120000 index 00000000..6300683f --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallntt_769.S @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.c b/crypto_sign/dilithium2/m4fstack/smallpoly.c new file mode 120000 index 00000000..7dbf4992 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallpoly.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.h b/crypto_sign/dilithium2/m4fstack/smallpoly.h new file mode 120000 index 00000000..366391d9 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallpoly.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.c b/crypto_sign/dilithium2/m4fstack/stack.c new file mode 120000 index 00000000..c89dc5a0 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/stack.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.h b/crypto_sign/dilithium2/m4fstack/stack.h new file mode 120000 index 00000000..c9aed5d7 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/stack.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/symmetric-shake.c b/crypto_sign/dilithium2/m4fstack/symmetric-shake.c new file mode 120000 index 00000000..b95855bb --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/symmetric-shake.c @@ -0,0 +1 @@ +../m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/symmetric.h b/crypto_sign/dilithium2/m4fstack/symmetric.h new file mode 120000 index 00000000..e89ae955 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/symmetric.h @@ -0,0 +1 @@ +../m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/vector.h b/crypto_sign/dilithium2/m4fstack/vector.h new file mode 120000 index 00000000..0793594b --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/vector.h @@ -0,0 +1 @@ +../m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/vector.s b/crypto_sign/dilithium2/m4fstack/vector.s new file mode 120000 index 00000000..1a496055 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/vector.s @@ -0,0 +1 @@ +../m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/api.h b/crypto_sign/dilithium3/m4fstack/api.h new file mode 100644 index 00000000..a289632c --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/api.h @@ -0,0 +1,26 @@ +#ifndef API_H +#define API_H + +#include +#include +#include "params.h" + +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/config.h b/crypto_sign/dilithium3/m4fstack/config.h new file mode 100644 index 00000000..55724079 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/config.h @@ -0,0 +1,7 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define DILITHIUM_MODE 3 +// #define SIGN_STACKSTRATEGY 2 + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/macros.i b/crypto_sign/dilithium3/m4fstack/macros.i new file mode 100644 index 00000000..25d98c2b --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/macros.i @@ -0,0 +1,191 @@ +#ifndef MACROS_I +#define MACROS_I +// 3 +.macro montgomery_mul_32 a, b, Qprime, Q, tmp, tmp2 + smull \tmp, \a, \a, \b + mul \tmp2, \tmp, \Qprime + smlal \tmp, \a, \tmp2, \Q +.endm + +// 2 +.macro addSub1 c0, c1 + add.w \c0, \c1 + sub.w \c1, \c0, \c1, lsl #1 +.endm + +// 3 +.macro addSub2 c0, c1, c2, c3 + add \c0, \c1 + add \c2, \c3 + sub.w \c1, \c0, \c1, lsl #1 + sub.w \c3, \c2, \c3, lsl #1 +.endm + +// 6 +.macro addSub4 c0, c1, c2, c3, c4, c5, c6, c7 + add \c0, \c1 + add \c2, \c3 + add \c4, \c5 + add \c6, \c7 + sub.w \c1, \c0, \c1, lsl #1 + sub.w \c3, \c2, \c3, lsl #1 + sub.w \c5, \c4, \c5, lsl #1 + sub.w \c7, \c6, \c7, lsl #1 +.endm + +.macro _2_layer_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 + montgomery_mul_32 \c2, \zeta0, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 + + montgomery_mul_32 \c1, \zeta1, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c1, \c2, \c3 +.endm + +.macro _2_layer_inv_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 + montgomery_mul_32 \c1, \zeta0, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c1, \c2, \c3 + + montgomery_mul_32 \c2, \zeta1, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 +.endm + +.macro _3_layer_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + vmov.w \twiddle, \xi0 + montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 + + vmov.w \twiddle, \xi1 + montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 + + vmov.w \twiddle, \xi3 + montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi4 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi5 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi6 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 +.endm + +.macro _3_layer_inv_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + vmov.w \twiddle, \xi0 + montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 + + vmov.w \twiddle, \xi1 + montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 + + vmov.w \twiddle, \xi3 + montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi4 + montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi5 + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + vmov.w \twiddle, \xi6 + montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 +.endm + +/************************************************************ +* Name: _3_layer_inv_butterfly_light_fast_first +* +* Description: upper half of 3-layer inverse butterfly +* defined over X^8 - 1 +* +* Input: (c4, c1, c6, c3) = coefficients on the upper half; +* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = +* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in +* Montgomery domain +* +* Symbols: R = 2^32 +* +* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD +* +* Output: +* c4 = c4 + c1 + (c6 + c3) +* c5 = (c4 - c1) w_4 + (c6 + c3) w_8^3 +* c6 = c4 + c1 - (c6 + c3) +* c7 = (c4 - c1) w_8^3 + (c6 + c3) w_4 +************************************************************/ +// 15 +.macro _3_layer_inv_butterfly_light_fast_first c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + addSub2 \c4, \c1, \c6, \c3 + addSub1 \c4, \c6 + + vmov.w \tmp, \xi4 + vmov.w \tmp2, \xi6 + + smull.w \c0, \c5, \c1, \tmp + smlal.w \c0, \c5, \c3, \tmp2 + mul.w \twiddle, \c0, \Qprime + smlal.w \c0, \c5, \twiddle, \Q + + smull.w \c2, \c7, \c1, \tmp2 + smlal.w \c2, \c7, \c3, \tmp + mul.w \twiddle, \c2, \Qprime + smlal.w \c2, \c7, \twiddle, \Q +.endm + +/************************************************************ +* Name: _3_layer_inv_butterfly_light_fast_second +* +* Description: lower half of 3-layer inverse butterfly +* defined over X^8 - 1, and the 2nd +* layer of butterflies +* +* Input: +* (c4, c5, c6, c7) = results of the upper half; +* (c0, c1, c2, c3) = coefficients on the lower half; +* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = +* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in +* Montgomery domain +* +* Symbols: R = 2^32 +* +* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD +* +* Output: (normal order) +* c0 = c0 + c1 + (c2 + c3) + ( c4 + c5 + (c6 + c7) ) +* c1 = (c0 - c1) w3 + (c2 - c3) w4 + ( (c4 - c5) w5 + (c6 - c7) w6 ) +* c2 = ( c0 + c1 - (c2 + c3)) w1 + (( c4 + c5 - (c6 + c7) ) w2) +* c3 = ((c0 - c1) w3 - (c2 - c3) w4) w1 + (((c4 - c5) w5 - (c6 - c7) w6) w2) +* c4 = c0 + c1 - (c2 + c3) - ( c4 + c5 + (c6 + c7) ) w0 +* c5 = (c0 - c1) w3 + (c2 - c3) w4 - ( (c4 - c5) w5 + (c6 - c7) w6 ) w0 +* c6 = ( c0 + c1 - (c2 + c3)) w1 - (( c4 + c5 - (c6 + c7) ) w2) w0 +* c7 = ((c0 - c1) w3 - (c2 - c3) w4) w1 - (((c4 - c5) w5 - (c6 - c7) w6) w2) w0 +************************************************************/ +// 19 +.macro _3_layer_inv_butterfly_light_fast_second c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 + addSub2 \c0, \c1, \c2, \c3 + + vmov.w \twiddle, \xi2 + montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 + addSub2 \c0, \c2, \c1, \c3 + + montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 + + addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 +.endm + +#endif /* MACROS_I */ diff --git a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i new file mode 100644 index 00000000..7c9a387c --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NTT and inverse NTT code from: + * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. + * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. + * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. + * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S +*/ + +#ifndef MACROS_SMALLNTT_I +#define MACROS_SMALLNTT_I + +// general macros +.macro load a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + ldr.w \a0, [\a, \mem0] + ldr.w \a1, [\a, \mem1] + ldr.w \a2, [\a, \mem2] + ldr.w \a3, [\a, \mem3] +.endm + +.macro store a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + str.w \a0, [\a, \mem0] + str.w \a1, [\a, \mem1] + str.w \a2, [\a, \mem2] + str.w \a3, [\a, \mem3] +.endm + +.macro doubleplant a, tmp, q, qa, plantconst + smulwb \tmp, \plantconst, \a + smulwt \a, \plantconst, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebarrett a, tmp, tmp2, q, barrettconst + smulbb \tmp, \a, \barrettconst + smultb \tmp2, \a, \barrettconst + asr \tmp, \tmp, #26 + asr \tmp2, \tmp2, #26 + smulbb \tmp, \tmp, \q + smulbb \tmp2, \tmp2, \q + pkhbt \tmp, \tmp, \tmp2, lsl#16 + usub16 \a, \a, \tmp +.endm + +// q locate in the top half of the register +.macro plant_red q, qa, qinv, tmp + mul \tmp, \tmp, \qinv + //tmp*qinv mod 2^2n/ 2^n; in high half + smlatt \tmp, \tmp, \q, \qa + // result in high half +.endm + +.macro mul_twiddle_plant a, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a + smulwt \a, \twiddle, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebutterfly_plant a0, a1, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a1 + smulwt \a1, \twiddle, \a1 + smlabt \tmp, \tmp, \q, \qa + smlabt \a1, \a1, \q, \qa + pkhtb \tmp, \a1, \tmp, asr#16 + usub16 \a1, \a0, \tmp + uadd16 \a0, \a0, \tmp +.endm + +.macro two_doublebutterfly_plant a0, a1, a2, a3, twiddle0, twiddle1, tmp, q, qa + doublebutterfly_plant \a0, \a1, \twiddle0, \tmp, \q, \qa + doublebutterfly_plant \a2, \a3, \twiddle1, \tmp, \q, \qa +.endm + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/ntt.S b/crypto_sign/dilithium3/m4fstack/ntt.S new file mode 100644 index 00000000..bfd5f7a4 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/ntt.S @@ -0,0 +1,402 @@ +// based on code by: Markus Krausz (18.03.18) +// date 23.07.21: Now licensed under CC0 with permission of the authors. + +.syntax unified +#include "macros.i" + +// This code uses UMULL - which is constant time on the M4, but not on the M3 +// Make sure that this code is never used on an M3 +smlad r0,r0,r0,r0 + +// ############################## +// ########## NTT ########## +// ############################## + +//void pqcrystals_dilithium_ntt(int32_t p[N]); +.global pqcrystals_dilithium_ntt +.type pqcrystals_dilithium_ntt,%function +.align 2 +pqcrystals_dilithium_ntt: + //bind aliases + ptr_p .req R0 + ptr_zeta .req R1 + zeta .req R1 + qinv .req R2 + q .req R3 + cntr .req R4 + pol4 .req R4 + pol0 .req R5 + pol1 .req R6 + pol2 .req R7 + pol3 .req R8 + temp_h .req R9 + temp_l .req R10 + zeta0 .req R11 + zeta1 .req R12 + zeta2 .req R14 + pol5 .req R11 + pol6 .req R12 + pol7 .req R14 + + //preserve registers + push {R4-R11, R14} + + //load constants, ptr + ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed + ldr.w q, inv_ntt_asm_smull_q + + //stage 1 - 3 + .equ distance, 512 + .equ strincr, 4 + + ldr ptr_zeta, =#zetas_new332 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + add.w temp_l, ptr_p, #32*strincr // 32 iterations + vmov s9, temp_l + 1: + .rept 2 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #strincr + .endr + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne 1b + + sub ptr_p, #32*4 + + // stage 4 - 6 + .equ distance, 64 + add.w temp_l, ptr_p, #8*112+8*4*4 // 8 iterations + vmov s9, temp_l + 1: + add.w temp_l, ptr_p, #4*strincr // 4 iterations + vmov s10, temp_l + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + 2: + .rept 2 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #4 + .endr + vmov temp_l, s10 + cmp.w ptr_p, temp_l + bne 2b + + add.w ptr_p, #112 + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne 1b + + sub ptr_p, #4*4*8+112*8 + vmov ptr_zeta, s0 + //stage 7 and 8 + add cntr, ptr_p, #1024 // 64 iterations + 1: + ldr.w zeta1, [ptr_zeta, #4] //z128,..., z254 + ldr.w zeta2, [ptr_zeta, #8] //z129,..., z255 + ldr zeta0, [ptr_zeta], #12 //z64, ..., z127 + ldr.w pol0, [ptr_p] //1*4 + ldr.w pol1, [ptr_p, #4] + ldr.w pol2, [ptr_p, #8] + ldr.w pol3, [ptr_p, #12] + + _2_layer_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #4] + str.w pol2, [ptr_p, #8] + str.w pol3, [ptr_p, #12] + str pol0, [ptr_p], #16 + + cmp.w cntr, ptr_p + bne.w 1b + + //restore registers + pop {R4-R11, PC} + + //unbind aliases + .unreq ptr_p + .unreq ptr_zeta + .unreq qinv + .unreq q + .unreq cntr + .unreq pol0 + .unreq pol1 + .unreq pol2 + .unreq pol3 + .unreq temp_h + .unreq temp_l + .unreq zeta0 + .unreq zeta1 + .unreq zeta2 + +.ltorg +// ############################## +// ########## NTT^-1 ########## +// ############################## + +//void pqcrystals_dilithium_invntt_tomont(int32_t p[N]); +.global pqcrystals_dilithium_invntt_tomont +.type pqcrystals_dilithium_invntt_tomont,%function +.align 2 +pqcrystals_dilithium_invntt_tomont: + //bind aliases + ptr_p .req R0 + ptr_zeta .req R1 + zeta .req R1 + qinv .req R2 + q .req R3 + cntr .req R4 + pol4 .req R4 + pol0 .req R5 + pol1 .req R6 + pol2 .req R7 + pol3 .req R8 + temp_h .req R9 + temp_l .req R10 + zeta0 .req R11 + zeta1 .req R12 + zeta2 .req R14 + pol5 .req R11 + pol6 .req R12 + pol7 .req R14 + + //preserve registers + push {R4-R11, R14} + + //load constants, ptr + ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed + ldr.w q, inv_ntt_asm_smull_q + + //stage 1 - 3 + .equ distance, 16 + .equ strincr, 32 + + ldr ptr_zeta, =#zetas_new332inv + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + add.w temp_l, ptr_p, #32*strincr // 32 iterations + vmov s9, temp_l + 1: + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol1, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol3, [ptr_p, #7*distance/4] + _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p], #strincr + vmov temp_l, s9 + cmp.w ptr_p, temp_l + bne.w 1b + + sub ptr_p, #32*strincr + + // stage 4 - 6 + .equ distance, 128 + .equ strincr, 256 + + // iteration 0 + movw temp_l, #4 + add.w temp_l, ptr_p, #4*256 // 4 iterations + vmov s10, temp_l + + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + + 2: + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol1, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol3, [ptr_p, #7*distance/4] + _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p] + add.w ptr_p, #strincr + + vmov temp_l, s10 + cmp.w temp_l, ptr_p + bne.w 2b + + sub.w ptr_p, #4*256-4 + + // iteration 1-7 + add.w temp_l, ptr_p, #7*4 // 7 iterations + vmov s9, temp_l + 1: + add.w temp_l, ptr_p, #4*strincr // 4 iterations + vmov s10, temp_l + + vmov ptr_zeta, s0 + vldm ptr_zeta!, {s2-s8} + vmov s0, ptr_zeta + 2: + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #1*distance/4] + ldr.w pol2, [ptr_p, #2*distance/4] + ldr.w pol3, [ptr_p, #3*distance/4] + ldr.w pol4, [ptr_p, #4*distance/4] + ldr.w pol5, [ptr_p, #5*distance/4] + ldr.w pol6, [ptr_p, #6*distance/4] + ldr.w pol7, [ptr_p, #7*distance/4] + + _3_layer_inv_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #1*distance/4] + str.w pol2, [ptr_p, #2*distance/4] + str.w pol3, [ptr_p, #3*distance/4] + str.w pol4, [ptr_p, #4*distance/4] + str.w pol5, [ptr_p, #5*distance/4] + str.w pol6, [ptr_p, #6*distance/4] + str.w pol7, [ptr_p, #7*distance/4] + str.w pol0, [ptr_p] + add.w ptr_p, #strincr + + vmov temp_l, s10 + cmp.w ptr_p, temp_l + bne 2b + sub.w ptr_p, #4*strincr-4 + + vmov temp_l, s9 + cmp.w temp_l, ptr_p + bne 1b + + sub ptr_p, #8*4 + vmov ptr_zeta, s0 + + //stage 7 and 8 + .equ strincr, 4 + + add.w cntr, ptr_p, #64*strincr // 64 iterations + vmov s9, cntr + 1: + ldr.w zeta1, [ptr_zeta, #4] + ldr.w zeta2, [ptr_zeta, #8] + ldr zeta0, [ptr_zeta], #12 + ldr.w pol0, [ptr_p] + ldr.w pol1, [ptr_p, #256] + ldr.w pol2, [ptr_p, #512] + ldr.w pol3, [ptr_p, #768] + + _2_layer_inv_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l + + ldr.w zeta1, [ptr_zeta, #4] + ldr.w zeta2, [ptr_zeta, #8] + ldr.w zeta0, [ptr_zeta, #12] + ldr.w cntr, [ptr_zeta], #16 + montgomery_mul_32 pol0, cntr, qinv, q, temp_h, temp_l + montgomery_mul_32 pol1, zeta1, qinv, q, temp_h, temp_l + montgomery_mul_32 pol2, zeta2, qinv, q, temp_h, temp_l + montgomery_mul_32 pol3, zeta0, qinv, q, temp_h, temp_l + + str.w pol1, [ptr_p, #256] + str.w pol2, [ptr_p, #512] + str.w pol3, [ptr_p, #768] + str pol0, [ptr_p], #strincr + + vmov cntr, s9 + cmp.w cntr, ptr_p + bne.w 1b + + //restore registers + pop {R4-R11, PC} + + //unbind aliases + .unreq ptr_p + .unreq ptr_zeta + .unreq qinv + .unreq q + .unreq cntr + .unreq pol0 + .unreq pol1 + .unreq pol2 + .unreq pol3 + .unreq temp_h + .unreq temp_l + .unreq zeta0 + .unreq zeta1 + .unreq zeta2 + +.align 2 +inv_ntt_asm_smull_qinv: +.word 0xfc7fdfff +.align 2 +inv_ntt_asm_smull_q: +.word 8380417 + +.section .rodata + +.type zetas_new332, %object +.align 2 +zetas_new332: +.word 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, 2725464, 1024112, 2706023, 95776, 3077325, 3530437, 2353451, -1079900, 3585928, -1661693, -3592148, -2537516, 3915439, -359251, -549488, -1119584, -3861115, -3043716, 3574422, -2867647, -2091905, 2619752, -2108549, 3539968, -300467, 2348700, -539299, 3119733, -2118186, -3859737, -1699267, -1643818, 3505694, -3821735, -2884855, -1399561, -3277672, 3507263, -2140649, -1600420, 3699596, 3111497, 1757237, -19422, 811944, 531354, 954230, 3881043, 2680103, 4010497, 280005, 3900724, -2556880, 2071892, -2797779, -3930395, 2091667, 3407706, -1528703, 2316500, 3817976, -3677745, -3342478, 2244091, -3041255, -2446433, -3562462, -1452451, 266997, 2434439, 3475950, -1235728, 3513181, 2176455, -3520352, -3759364, -1585221, -1197226, -3193378, -1257611, 900702, 1859098, 1939314, 909542, 819034, -4083598, 495491, -1613174, -1000202, -43260, -522500, -3190144, -655327, -3122442, -3157330, 2031748, 3207046, -3632928, -3556995, -525098, 126922, -768622, -3595838, 3412210, 342297, 286988, -983419, -2437823, 4108315, 2147896, 3437287, -3342277, 2715295, 1735879, 203044, -2967645, 2842341, 2691481, -3693493, -2590150, 1265009, -411027, 4055324, 1247620, -2477047, 2486353, 1595974, -671102, -3767016, 1250494, -1228525, 2635921, -3548272, -22981, -2994039, 1869119, -1308169, 1903435, -1050970, -381987, -1333058, 1237275, 1349076, -3318210, -1430225, 1852771, -451100, 1312455, -1430430, 3306115, -1962642, -3343383, -1279661, 1917081, 264944, -2546312, -1374803, 508951, 1500165, 777191, 3097992, 2235880, 3406031, 44288, -542412, -2831860, -1100098, -1671176, -1846953, 904516, -2584293, -3724270, 3958618, 594136, -3776993, -3724342, -2013608, 2432395, -8578, 2454455, -164721, 1653064, 1957272, 3369112, -3249728, 185531, -1207385, 2389356, -3183426, 162844, -210977, 1616392, 3014001, 759969, 810149, 1652634, -1316856, -3694233, -1799107, 189548, -3038916, 3523897, -3553272, 3866901, 269760, 3159746, 2213111, -975884, -1851402, 1717735, 472078, -2409325, -426683, 1723600, -177440, -1803090, 1910376, 1315589, -1667432, -1104333, 1341330, -260646, -3833893, 1285669, -2939036, -2235985, -1584928, -420899, -2286327, -812732, 183443, -976891, -1439742, 1612842, -3545687, -3019102, -554416, 3919660, -3881060, -48306, -1362209, -3628969, 3937738, 1400424, 3839961, -846154, 1976782 +.size zetas_new332,.-zetas_new332 + +.type zetas_new332inv, %object +.align 2 +zetas_new332inv: +.word 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894, 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894, -466468, -2680103, -3111497, -280005, 19422, -4010497, -1757237, 518909, -466468, 876248, -2680103, 2884855, -3111497, -3119733, 777960, 2091905, 359251, 2108549, 1119584, -2619752, 549488, -25847, 518909, 2608894, -466468, 777960, 876248, -237124, 876248, 2884855, -3119733, 3277672, 3859737, 1399561, 2118186, 2608894, 777960, -237124, 2091905, -2353451, 359251, -1826347, -237124, -2353451, -1826347, -3585928, -1024112, 1079900, -2725464, 4193792, 4193792, -25847, 41978, 3024400, 3975713, -1225192, 2797779, -3839961, 3628969, -1711436, 3835778, 485110, -3954267, -280005, 2797779, -2071892, -2831100, -2698859, -908040, -2292170, 539299, 1430430, -1852771, -3658785, 3512212, 1859141, -1607594, -2680103, -280005, -4010497, 715005, 1483994, -1045894, -980943, -3699596, 1316856, -759969, -955715, 3677139, 3933849, 2719610, 2108549, 539299, -2348700, 1658328, -1403403, 1775852, -2460465, -3915439, -126922, 3632928, 1067023, 3847594, 4179270, 1652689, -466468, -2680103, -3111497, -2953811, -284642, 2507426, -324139, -3881043, -1341330, -1315589, 3990128, -2137097, -4109898, 4092021, 3277672, -3699596, 1600420, 1541634, 3493410, 3487504, 2497815, 2867647, 2477047, 411027, 1654972, 1326223, -2608226, -2752209, 2091905, 2108549, -2619752, 1836700, 2945615, -1908953, 729864, 3821735, -3958618, -904516, 2080615, 1555380, -3471815, -1978758, -3585928, -3915439, 2537516, -892788, -553664, -3095038, 658596, -3530437, 1585221, -2176455, 3355482, -1783485, 2780552, -3623330, 518909, -466468, 876248, -442683, 2523147, -2847660, -3683140, 2556880, 1439742, 812732, 774207, -3168108, 1877157, 3406477, 19422, -3881043, -954230, -214686, -1182619, 2453526, -2201920, 300467, 1308169, 22981, 3614022, 2136260, 1459487, -2233803, 2884855, 3277672, 1399561, 394072, -3933227, 4136064, 156486, 2140649, 3249728, -1653064, 1596950, 633578, 2722529, -554462, 1119584, 2867647, -3574422, 1004840, 191586, 3969463, 1161373, 3592148, 1000202, 4083598, 3189243, 3561667, -3650125, 3490511, 777960, 2091905, 359251, -1829156, -3707725, -661807, 1144558, -531354, 1851402, -3159746, 1543095, -2903948, 1505516, -1500460, 3859737, 3821735, -3505694, -2413330, 3908886, -1203856, 3570263, 3043716, -2715295, -2147896, 758741, 3917553, -2414897, -1613811, -2353451, -3585928, 1079900, 990020, -719638, 2718792, 2260310, 1643818, -3097992, -508951, -783456, -2089539, 2616547, 4060031, -1024112, -3530437, -3077325, -1821861, 1920615, 3988525, 2048419, -95776, 3041255, 3677745, -971504, 2190617, 2311312, -1170082, -25847, 518909, 2608894, 1261528, -2073537, -959585, 3948120, -2071892, 3881060, 3019102, -1342633, -1115066, 3589694, -1929116, -4010497, 2556880, -3900724, 3360006, 1758630, -2306989, -1841637, -2348700, -1349076, 381987, -1699982, 3189673, 3531558, -1210546, -3111497, 19422, -1757237, 2977353, 2612035, -2718155, -1544829, 1600420, 210977, -2389356, 2052582, -2737802, 2383976, -450259, -2619752, 300467, -3539968, 1698289, -4065084, -644023, -1114140, 2537516, 3157330, 3190144, -993399, -2220524, 2920588, 252737, 876248, 2884855, -3119733, 1490985, -34731, -1212610, -3183745, -954230, 177440, 2409325, -3302554, -2390327, -2749545, 653128, 1399561, 2140649, -3507263, -3745105, -1942293, -3367121, 2734884, -3574422, 3693493, 2967645, 1393803, -2467905, 1786029, -1633410, 359251, 1119584, 549488, -2824548, -1325638, -2207625, -2601586, -3505694, 1100098, -44288, 3478676, -2457992, -1617107, 2551364, 1079900, 3592148, 1661693, 1593929, 318899, -3366475, 3118416, -3077325, -3475950, 1452451, 3772814, 1424805, -3391376, 632820, 2608894, 777960, -237124, 2062597, 4064335, 2197148, -1127864, -3900724, 1584928, -1285669, 2525341, -896437, -1915773, 1792087, -1757237, -531354, -811944, 938441, -674578, 2876837, 3959371, -3539968, 1228525, 671102, 1219592, -3853560, 2630979, -2134676, -3119733, 3859737, 2118186, -2432637, 2746655, 718593, -2353280, -3507263, 8578, 3724342, -34852, 1387945, 358956, 1604944, 549488, 3043716, 3861115, 1290746, 3208584, 2538711, -1442830, 1661693, -1939314, 1257611, -367371, -1308058, 264382, 2614173, -237124, -2353451, -1826347, 2050674, 592050, -138487, 2310528, -811944, 3553272, -189548, -2728561, -4168358, -79, 3844932, 2118186, 1643818, 1699267, 500408, 743398, 879633, -3105206, 3861115, 983419, -3412210, 712597, -23479, 3729381, -1010481, -1826347, -1024112, -2725464, -2361217, -1864453, 3850522, 2337144, 1699267, -264944, 3343383, 3842267, 4181974, -4032642, 3983585, -2725464, -95776, -2706023, 260345, 2526550, 2000777, 987079, -2706023, 1528703, 3930395, -3030761, -3082055, -2374824, 1836319 +.size zetas_new332inv,.-zetas_new332inv diff --git a/crypto_sign/dilithium3/m4fstack/ntt.h b/crypto_sign/dilithium3/m4fstack/ntt.h new file mode 100644 index 00000000..731132d5 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/ntt.h @@ -0,0 +1,13 @@ +#ifndef NTT_H +#define NTT_H + +#include +#include "params.h" + +#define ntt DILITHIUM_NAMESPACE(ntt) +void ntt(int32_t a[N]); + +#define invntt_tomont DILITHIUM_NAMESPACE(invntt_tomont) +void invntt_tomont(int32_t a[N]); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/packing.c b/crypto_sign/dilithium3/m4fstack/packing.c new file mode 100644 index 00000000..8aaff2a3 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/packing.c @@ -0,0 +1,286 @@ +#include "params.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" + +/************************************************* +* Name: pack_pk +* +* Description: Bit-pack public key pk = (rho, t1). +* +* Arguments: - uint8_t pk[]: output byte array +* - const uint8_t rho[]: byte array containing rho +* - const polyveck *t1: pointer to vector t1 +**************************************************/ +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], + const uint8_t rho[SEEDBYTES], + const polyveck *t1) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + pk[i] = rho[i]; + pk += SEEDBYTES; + + for(i = 0; i < K; ++i) + polyt1_pack(pk + i*POLYT1_PACKEDBYTES, &t1->vec[i]); +} + +/************************************************* +* Name: unpack_pk +* +* Description: Unpack public key pk = (rho, t1). +* +* Arguments: - const uint8_t rho[]: output byte array for rho +* - const polyveck *t1: pointer to output vector t1 +* - uint8_t pk[]: byte array containing bit-packed pk +**************************************************/ +void unpack_pk(uint8_t rho[SEEDBYTES], + polyveck *t1, + const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = pk[i]; + pk += SEEDBYTES; + + for(i = 0; i < K; ++i) + polyt1_unpack(&t1->vec[i], pk + i*POLYT1_PACKEDBYTES); +} + +/************************************************* +* Name: pack_sk +* +* Description: Bit-pack secret key sk = (rho, tr, key, t0, s1, s2). +* +* Arguments: - uint8_t sk[]: output byte array +* - const uint8_t rho[]: byte array containing rho +* - const uint8_t tr[]: byte array containing tr +* - const uint8_t key[]: byte array containing key +* - const polyveck *t0: pointer to vector t0 +* - const polyvecl *s1: pointer to vector s1 +* - const polyveck *s2: pointer to vector s2 +**************************************************/ +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t rho[SEEDBYTES], + const uint8_t tr[TRBYTES], + const uint8_t key[SEEDBYTES], + const polyveck *t0, + const polyvecl *s1, + const polyveck *s2) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = rho[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = key[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + sk[i] = tr[i]; + sk += TRBYTES; + + for(i = 0; i < L; ++i) + polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s1->vec[i]); + sk += L*POLYETA_PACKEDBYTES; + + for(i = 0; i < K; ++i) + polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s2->vec[i]); + sk += K*POLYETA_PACKEDBYTES; + + for(i = 0; i < K; ++i) + polyt0_pack(sk + i*POLYT0_PACKEDBYTES, &t0->vec[i]); +} + +/************************************************* +* Name: unpack_sk +* +* Description: Unpack secret key sk = (rho, tr, key, t0, s1, s2). +* +* Arguments: - const uint8_t rho[]: output byte array for rho +* - const uint8_t tr[]: output byte array for tr +* - const uint8_t key[]: output byte array for key +* - const polyveck *t0: pointer to output vector t0 +* - const polyvecl *s1: pointer to output vector s1 +* - const polyveck *s2: pointer to output vector s2 +* - uint8_t sk[]: byte array containing bit-packed sk +**************************************************/ +void unpack_sk(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + polyveck *t0, + smallpoly s1[L], + smallpoly s2[K], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + key[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + tr[i] = sk[i]; + sk += TRBYTES; + + for(i=0; i < L; ++i) + small_polyeta_unpack(&s1[i], sk + i*POLYETA_PACKEDBYTES); + sk += L*POLYETA_PACKEDBYTES; + + for(i=0; i < K; ++i) + small_polyeta_unpack(&s2[i], sk + i*POLYETA_PACKEDBYTES); + sk += K*POLYETA_PACKEDBYTES; + + for(i=0; i < K; ++i) + polyt0_unpack(&t0->vec[i], sk + i*POLYT0_PACKEDBYTES); +} + + +/************************************************* +* Name: pack_sig +* +* Description: Bit-pack signature sig = (c, z, h). +* +* Arguments: - uint8_t sig[]: output byte array +* - const uint8_t *c: pointer to challenge hash length SEEDBYTES +* - const polyvecl *z: pointer to vector z +* - const polyveck *h: pointer to hint vector h +**************************************************/ +void pack_sig(uint8_t sig[CRYPTO_BYTES], + const uint8_t c[CTILDEBYTES], + const polyvecl *z, + const polyveck *h) +{ + unsigned int i, j, k; + + for(i=0; i < CTILDEBYTES; ++i) + sig[i] = c[i]; + sig += CTILDEBYTES; + + for(i = 0; i < L; ++i) + polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); + sig += L*POLYZ_PACKEDBYTES; + + /* Encode h */ + for(i = 0; i < OMEGA + K; ++i) + sig[i] = 0; + + k = 0; + for(i = 0; i < K; ++i) { + for(j = 0; j < N; ++j) + if(h->vec[i].coeffs[j] != 0) + sig[k++] = j; + + sig[OMEGA + i] = k; + } +} + +void pack_sig_c(uint8_t sig[CRYPTO_BYTES], + const uint8_t c[CTILDEBYTES]) +{ + unsigned int i; + + for(i=0; i < CTILDEBYTES; ++i) + sig[i] = c[i]; + sig += CTILDEBYTES; +} + +void pack_sig_z(uint8_t sig[CRYPTO_BYTES], + const polyvecl *z) +{ + unsigned int i; + sig += CTILDEBYTES; + for(i = 0; i < L; ++i) + polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); +} + + +void pack_sig_h(unsigned char sig[CRYPTO_BYTES], + const poly *h_elem, + const unsigned int idx, + unsigned int *hints_written) +{ + sig += CTILDEBYTES; + sig += L*POLYZ_PACKEDBYTES; + + // Encode h + for (unsigned int j = 0; j < N; j++) { + if (h_elem->coeffs[j] != 0) { + sig[*hints_written] = (uint8_t)j; + (*hints_written)++; + } + } + sig[OMEGA + idx] = (uint8_t)*hints_written; +} + +void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], + unsigned int *hints_written) { + sig += CTILDEBYTES; + sig += L * POLYZ_PACKEDBYTES; + while (*hints_written < OMEGA) { + sig[*hints_written] = 0; + (*hints_written)++; + } +} + +/************************************************* +* Name: unpack_sig +* +* Description: Unpack signature sig = (c, z, h). +* +* Arguments: - uint8_t *c: pointer to output challenge hash +* - polyvecl *z: pointer to output vector z +* - polyveck *h: pointer to output hint vector h +* - const uint8_t sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig(uint8_t c[CTILDEBYTES], + polyvecl *z, + polyveck *h, + const uint8_t sig[CRYPTO_BYTES]) +{ + unsigned int i, j, k; + + for(i = 0; i < CTILDEBYTES; ++i) + c[i] = sig[i]; + sig += CTILDEBYTES; + + for(i = 0; i < L; ++i) + polyz_unpack(&z->vec[i], sig + i*POLYZ_PACKEDBYTES); + sig += L*POLYZ_PACKEDBYTES; + + /* Decode h */ + k = 0; + for(i = 0; i < K; ++i) { + for(j = 0; j < N; ++j) + h->vec[i].coeffs[j] = 0; + + if(sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) + return 1; + + for(j = k; j < sig[OMEGA + i]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if(j > k && sig[j] <= sig[j-1]) return 1; + h->vec[i].coeffs[sig[j]] = 1; + } + + k = sig[OMEGA + i]; + } + + /* Extra indices are zero for strong unforgeability */ + for(j = k; j < OMEGA; ++j) + if(sig[j]) + return 1; + + return 0; +} \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.h b/crypto_sign/dilithium3/m4fstack/packing.h new file mode 100644 index 00000000..35553545 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/packing.h @@ -0,0 +1,55 @@ +#ifndef PACKING_H +#define PACKING_H + +#include +#include "params.h" +#include "polyvec.h" +#include "smallpoly.h" + +#define pack_pk DILITHIUM_NAMESPACE(pack_pk) +void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], const uint8_t rho[SEEDBYTES], const polyveck *t1); + +#define pack_sk DILITHIUM_NAMESPACE(pack_sk) +void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], + const uint8_t rho[SEEDBYTES], + const uint8_t tr[TRBYTES], + const uint8_t key[SEEDBYTES], + const polyveck *t0, + const polyvecl *s1, + const polyveck *s2); + +#define pack_sig DILITHIUM_NAMESPACE(pack_sig) +void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h); + +#define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) +void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); + +#define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) +void unpack_sk(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + polyveck *t0, + smallpoly s1[L], + smallpoly s2[K], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +#define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) +int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + +#define pack_sig_c DILITHIUM_NAMESPACE(pack_sig_c) +void pack_sig_c(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES]); + +#define pack_sig_z DILITHIUM_NAMESPACE(pack_sig_z) +void pack_sig_z(uint8_t sig[CRYPTO_BYTES], const polyvecl *z); + +#define pack_sig_h DILITHIUM_NAMESPACE(pack_sig_h) +void pack_sig_h(unsigned char sig[CRYPTO_BYTES], + const poly *h_elem, + const unsigned int idx, + unsigned int *hints_written); + +#define pack_sig_h_zero DILITHIUM_NAMESPACE(pack_sig_h_zero) +void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], + unsigned int *hints_written); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/params.h b/crypto_sign/dilithium3/m4fstack/params.h new file mode 100644 index 00000000..507de467 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/params.h @@ -0,0 +1,83 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#include "config.h" + +#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium_##s + + +#define SEEDBYTES 32 +#define CRHBYTES 64 +#define TRBYTES 64 +#define RNDBYTES 32 +#define N 256 +#define Q 8380417 +#define D 13 +#define ROOT_OF_UNITY 1753 + +#if DILITHIUM_MODE == 2 +#define K 4 +#define L 4 +#define ETA 2 +#define TAU 39 +#define BETA 78 +#define GAMMA1 (1 << 17) +#define GAMMA2 ((Q-1)/88) +#define OMEGA 80 +#define CTILDEBYTES 32 + +#elif DILITHIUM_MODE == 3 +#define K 6 +#define L 5 +#define ETA 4 +#define TAU 49 +#define BETA 196 +#define GAMMA1 (1 << 19) +#define GAMMA2 ((Q-1)/32) +#define OMEGA 55 +#define CTILDEBYTES 48 + +#elif DILITHIUM_MODE == 5 +#define K 8 +#define L 7 +#define ETA 2 +#define TAU 60 +#define BETA 120 +#define GAMMA1 (1 << 19) +#define GAMMA2 ((Q-1)/32) +#define OMEGA 75 +#define CTILDEBYTES 64 + +#endif + +#define POLYT1_PACKEDBYTES 320 +#define POLYT0_PACKEDBYTES 416 +#define POLYVECH_PACKEDBYTES (OMEGA + K) + +#if GAMMA1 == (1 << 17) +#define POLYZ_PACKEDBYTES 576 +#elif GAMMA1 == (1 << 19) +#define POLYZ_PACKEDBYTES 640 +#endif + +#if GAMMA2 == (Q-1)/88 +#define POLYW1_PACKEDBYTES 192 +#elif GAMMA2 == (Q-1)/32 +#define POLYW1_PACKEDBYTES 128 +#endif + +#if ETA == 2 +#define POLYETA_PACKEDBYTES 96 +#elif ETA == 4 +#define POLYETA_PACKEDBYTES 128 +#endif + +#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLYT1_PACKEDBYTES) +#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES \ + + TRBYTES \ + + L*POLYETA_PACKEDBYTES \ + + K*POLYETA_PACKEDBYTES \ + + K*POLYT0_PACKEDBYTES) +#define CRYPTO_BYTES (CTILDEBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h new file mode 100644 index 00000000..2647a110 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h @@ -0,0 +1,13 @@ +#ifndef POINTWISE_MONT_H +#define POINTWISE_MONT_H + +#include +#include "params.h" + + +#define asm_pointwise_montgomery DILITHIUM_NAMESPACE(asm_pointwise_montgomery) +void asm_pointwise_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); +#define asm_pointwise_acc_montgomery DILITHIUM_NAMESPACE(asm_pointwise_acc_montgomery) +void asm_pointwise_acc_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s new file mode 100644 index 00000000..e21125d7 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s @@ -0,0 +1,128 @@ +.syntax unified +.thumb + +.macro montgomery_multiplication res, pa, pb, q, qinv + smull \pa, \res, \pa, \pb + mul \pb, \pa, \qinv + smlal \pa, \res, \pb, \q +.endm + + +// void asm_pointwise_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); +.global pqcrystals_dilithium_asm_pointwise_montgomery +.type pqcrystals_dilithium_asm_pointwise_montgomery,%function +.align 2 +pqcrystals_dilithium_asm_pointwise_montgomery: + push.w {r4-r11, r14} + c_ptr .req r0 + a_ptr .req r1 + b_ptr .req r2 + qinv .req r3 + q .req r4 + pa0 .req r5 + pa1 .req r6 + pa2 .req r7 + pb0 .req r8 + pb1 .req r9 + pb2 .req r10 + tmp0 .req r11 + ctr .req r12 + res .req r14 + + movw qinv, #:lower16:0xfc7fdfff + movt qinv, #:upper16:0xfc7fdfff + movw q, #0xE001 + movt q, #0x7F + + + // 85x3 = 255 coefficients + movw ctr, #85 + 1: + ldr.w pa1, [a_ptr, #4] + ldr.w pa2, [a_ptr, #8] + ldr pa0, [a_ptr], #12 + ldr.w pb1, [b_ptr, #4] + ldr.w pb2, [b_ptr, #8] + ldr pb0, [b_ptr], #12 + + montgomery_multiplication res, pa0, pb0, q, qinv + str res, [c_ptr], #4 + montgomery_multiplication res, pa1, pb1, q, qinv + str res, [c_ptr], #4 + montgomery_multiplication res, pa2, pb2, q, qinv + str res, [c_ptr], #4 + subs ctr, #1 + bne.w 1b + + // final coefficient + ldr.w pa0, [a_ptr] + ldr.w pb0, [b_ptr] + montgomery_multiplication res, pa0, pb0, q, qinv + str.w res, [c_ptr] + + pop.w {r4-r11, pc} +.size pqcrystals_dilithium_asm_pointwise_montgomery, .-pqcrystals_dilithium_asm_pointwise_montgomery + +// void asm_pointwise_acc_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); +.global pqcrystals_dilithium_asm_pointwise_acc_montgomery +.type pqcrystals_dilithium_asm_pointwise_acc_montgomery,%function +.align 2 +pqcrystals_dilithium_asm_pointwise_acc_montgomery: + push.w {r4-r11, r14} + c_ptr .req r0 + a_ptr .req r1 + b_ptr .req r2 + qinv .req r3 + q .req r4 + pa0 .req r5 + pa1 .req r6 + pa2 .req r7 + pb0 .req r8 + pb1 .req r9 + pb2 .req r10 + tmp0 .req r11 + ctr .req r12 + res .req r14 + + movw qinv, #:lower16:0xfc7fdfff + movt qinv, #:upper16:0xfc7fdfff + movw q, #0xE001 + movt q, #0x7F + + + // 85x3 = 255 coefficients + movw ctr, #85 + 1: + ldr.w pa1, [a_ptr, #4] + ldr.w pa2, [a_ptr, #8] + ldr pa0, [a_ptr], #12 + ldr.w pb1, [b_ptr, #4] + ldr.w pb2, [b_ptr, #8] + ldr pb0, [b_ptr], #12 + + montgomery_multiplication res, pa0, pb0, q, qinv + montgomery_multiplication pa0, pa1, pb1, q, qinv + montgomery_multiplication pa1, pa2, pb2, q, qinv + + ldr.w pb0, [c_ptr] + ldr.w pb1, [c_ptr, #4] + ldr.w pb2, [c_ptr, #8] + add.w res, res, pb0 + str res, [c_ptr], #12 + add.w pa0, pa0, pb1 + str pa0, [c_ptr, #-8] + add.w pa1, pa1, pb2 + str pa1, [c_ptr, #-4] + subs ctr, #1 + bne.w 1b + + // final coefficient + ldr.w pa0, [a_ptr] + ldr.w pb0, [b_ptr] + ldr.w pa1, [c_ptr] + montgomery_multiplication res, pa0, pb0, q, qinv + add.w res, res, pa1 + str.w res, [c_ptr] + + pop.w {r4-r11, pc} +.size pqcrystals_dilithium_asm_pointwise_acc_montgomery, .-pqcrystals_dilithium_asm_pointwise_acc_montgomery diff --git a/crypto_sign/dilithium3/m4fstack/poly.c b/crypto_sign/dilithium3/m4fstack/poly.c new file mode 100644 index 00000000..0d40fda3 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/poly.c @@ -0,0 +1,851 @@ +#include +#include "params.h" +#include "poly.h" +#include "vector.h" +#include "ntt.h" +#include "pointwise_mont.h" +#include "rounding.h" +#include "symmetric.h" + +#include +#include "hal.h" + +#ifdef DBENCH +#include "test/cpucycles.h" +extern const uint64_t timing_overhead; +extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; +#define DBENCH_START() uint64_t time = cpucycles() +#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead +#else +#define DBENCH_START() +#define DBENCH_STOP(t) +#endif + +/************************************************* +* Name: poly_reduce +* +* Description: Inplace reduction of all coefficients of polynomial to +* representative in [-6283009,6283007]. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_reduce(poly *a) { + asm_reduce32(a->coeffs); +} + +/************************************************* +* Name: poly_caddq +* +* Description: For all coefficients of in/out polynomial add Q if +* coefficient is negative. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_caddq(poly *a) { + asm_caddq(a->coeffs); +} + +#if 0 +/************************************************* +* Name: poly_freeze +* +* Description: Inplace reduction of all coefficients of polynomial to +* standard representatives. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_freeze(poly *a) { + asm_freeze(a->coeffs); +} +#endif + +/************************************************* +* Name: poly_add +* +* Description: Add polynomials. No modular reduction is performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first summand +* - const poly *b: pointer to second summand +**************************************************/ +void poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract polynomials. No modular reduction is +* performed. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial to be +* subtraced from first input polynomial +**************************************************/ +void poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; + + DBENCH_STOP(*tadd); +} + +/************************************************* +* Name: poly_shiftl +* +* Description: Multiply polynomial by 2^D without modular reduction. Assumes +* input coefficients to be less than 2^{31-D} in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_shiftl(poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a->coeffs[i] <<= D; + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_ntt +* +* Description: Inplace forward NTT. Coefficients can grow by +* 8*Q in absolute value. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_ntt(poly *a) { + DBENCH_START(); + + ntt(a->coeffs); + + DBENCH_STOP(*tmul); +} + + +/************************************************* +* Name: poly_invntt_tomont +* +* Description: Inplace inverse NTT and multiplication by 2^{32}. +* Input coefficients need to be less than Q in absolute +* value and output coefficients are again bounded by Q. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_invntt_tomont(poly *a) { + DBENCH_START(); + + invntt_tomont(a->coeffs); + + DBENCH_STOP(*tmul); +} + + +/************************************************* +* Name: poly_pointwise_montgomery +* +* Description: Pointwise multiplication of polynomials in NTT domain +* representation and multiplication of resulting polynomial +* by 2^{-32}. +* +* Arguments: - poly *c: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { + DBENCH_START(); + + asm_pointwise_montgomery(c->coeffs, a->coeffs, b->coeffs); + + DBENCH_STOP(*tmul); +} + +/************************************************* +* Name: poly_pointwise_acc_montgomery +* +* Description: Pointwise multiplication of polynomials in NTT domain +* representation, multiplication of resulting polynomial +* by 2^{-32} and accumulate. +* +* Arguments: - poly *c: pointer to output (accumulating) polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void poly_pointwise_acc_montgomery(poly *c, const poly *a, const poly *b) { + DBENCH_START(); + + asm_pointwise_acc_montgomery(c->coeffs, a->coeffs, b->coeffs); + + DBENCH_STOP(*tmul); +} + + +/************************************************* +* Name: poly_power2round +* +* Description: For all coefficients c of the input polynomial, +* compute c0, c1 such that c mod Q = c1*2^D + c0 +* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be +* standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_power2round(poly *a1, poly *a0, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a1->coeffs[i] = power2round(&a0->coeffs[i], a->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_decompose +* +* Description: For all coefficients c of the input polynomial, +* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0 +* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we +* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. +* Assumes coefficients to be standard representatives. +* +* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 +* - poly *a0: pointer to output polynomial with coefficients c0 +* - const poly *a: pointer to input polynomial +**************************************************/ +void poly_decompose(poly *a1, poly *a0, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + a1->coeffs[i] = decompose(&a0->coeffs[i], a->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_make_hint +* +* Description: Compute hint polynomial. The coefficients of which indicate +* whether the low bits of the corresponding coefficient of +* the input polynomial overflow into the high bits. +* +* Arguments: - poly *h: pointer to output hint polynomial +* - const poly *a0: pointer to low part of input polynomial +* - const poly *a1: pointer to high part of input polynomial +* +* Returns number of 1 bits. +**************************************************/ +unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1) { + unsigned int i, s = 0; + DBENCH_START(); + + for(i = 0; i < N; ++i) { + h->coeffs[i] = make_hint(a0->coeffs[i], a1->coeffs[i]); + s += h->coeffs[i]; + } + + DBENCH_STOP(*tround); + return s; +} + +/************************************************* +* Name: poly_use_hint +* +* Description: Use hint polynomial to correct the high bits of a polynomial. +* +* Arguments: - poly *b: pointer to output polynomial with corrected high bits +* - const poly *a: pointer to input polynomial +* - const poly *h: pointer to input hint polynomial +**************************************************/ +void poly_use_hint(poly *b, const poly *a, const poly *h) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N; ++i) + b->coeffs[i] = use_hint(a->coeffs[i], h->coeffs[i]); + + DBENCH_STOP(*tround); +} + +/************************************************* +* Name: poly_chknorm +* +* Description: Check infinity norm of polynomial against given bound. +* Assumes input coefficients were reduced by reduce32(). +* +* Arguments: - const poly *a: pointer to polynomial +* - int32_t B: norm bound +* +* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. +**************************************************/ +int poly_chknorm(const poly *a, int32_t B) { + unsigned int i; + int32_t t; + DBENCH_START(); + + if(B > (Q-1)/8) + return 1; + + /* It is ok to leak which coefficient violates the bound since + the probability for each coefficient is independent of secret + data but we must not leak the sign of the centralized representative. */ + for(i = 0; i < N; ++i) { + /* Absolute value */ + t = a->coeffs[i] >> 31; + t = a->coeffs[i] - (t & 2*a->coeffs[i]); + + if(t >= B) { + DBENCH_STOP(*tsample); + return 1; + } + } + + DBENCH_STOP(*tsample); + return 0; +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample polynomial with uniformly random coefficients +* in [0,Q-1] by performing rejection sampling on the +* output stream of SHAKE256(seed|nonce). +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length SEEDBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +#define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) +void poly_uniform(poly *a, + const uint8_t seed[SEEDBYTES], + uint16_t nonce) +{ + unsigned int i, ctr, off; + unsigned int buflen = POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES + 2]; + stream128_state state; + + stream128_init(&state, seed, nonce); + stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); + + ctr = asm_rej_uniform(a->coeffs, N, buf, buflen); + + while(ctr < N) { + off = buflen % 3; + for(i = 0; i < off; ++i) + buf[i] = buf[buflen - off + i]; + + stream128_squeezeblocks(buf + off, 1, &state); + buflen = STREAM128_BLOCKBYTES + off; + ctr += asm_rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); + } +} + +/************************************************* +* Name: rej_eta +* +* Description: Sample uniformly random coefficients in [-ETA, ETA] by +* performing rejection sampling on array of random bytes. +* +* Arguments: - int32_t *a: pointer to output array (allocated) +* - unsigned int len: number of coefficients to be sampled +* - const uint8_t *buf: array of random bytes +* - unsigned int buflen: length of array of random bytes +* +* Returns number of sampled coefficients. Can be smaller than len if not enough +* random bytes were given. +**************************************************/ +static unsigned int rej_eta(int32_t *a, + unsigned int len, + const uint8_t *buf, + unsigned int buflen) +{ + unsigned int ctr, pos; + uint32_t t0, t1; + DBENCH_START(); + + ctr = pos = 0; + while(ctr < len && pos < buflen) { + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; + +#if ETA == 2 + if(t0 < 15) { + t0 = t0 - (205*t0 >> 10)*5; + a[ctr++] = 2 - t0; + } + if(t1 < 15 && ctr < len) { + t1 = t1 - (205*t1 >> 10)*5; + a[ctr++] = 2 - t1; + } +#elif ETA == 4 + if(t0 < 9) + a[ctr++] = 4 - t0; + if(t1 < 9 && ctr < len) + a[ctr++] = 4 - t1; +#endif + } + + DBENCH_STOP(*tsample); + return ctr; +} + +/************************************************* +* Name: poly_uniform_eta +* +* Description: Sample polynomial with uniformly random coefficients +* in [-ETA,ETA] by performing rejection sampling on the +* output stream from SHAKE256(seed|nonce). +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length SEEDBYTES +* - uint16_t nonce: 2-byte nonce +**************************************************/ +#if ETA == 2 +#define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +#elif ETA == 4 +#define POLY_UNIFORM_ETA_NBLOCKS ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +#endif +void poly_uniform_eta(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce) { + unsigned int ctr; + unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; + uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); + + ctr = rej_eta(a->coeffs, N, buf, buflen); + + while(ctr < N) { + stream256_squeezeblocks(buf, 1, &state); + ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); + } +} + +/************************************************* +* Name: poly_uniform_gamma1m1 +* +* Description: Sample polynomial with uniformly random coefficients +* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream +* of SHAKE256(seed|nonce). +* +* Arguments: - poly *a: pointer to output polynomial +* - const uint8_t seed[]: byte array with seed of length CRHBYTES +* - uint16_t nonce: 16-bit nonce +**************************************************/ +#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) +void poly_uniform_gamma1(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce) +{ + uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES]; + stream256_state state; + + stream256_init(&state, seed, nonce); + stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); + polyz_unpack(a, buf); +} + +/************************************************* +* Name: challenge +* +* Description: Implementation of H. Samples polynomial with TAU nonzero +* coefficients in {-1,1} using the output stream of +* SHAKE256(seed). +* +* Arguments: - poly *c: pointer to output polynomial +* - const uint8_t mu[]: byte array containing seed of length SEEDBYTES +**************************************************/ +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { + unsigned int i, b, pos; + uint64_t signs; + uint8_t buf[SHAKE256_RATE]; + shake256incctx state; + + shake256_inc_init(&state); + shake256_inc_absorb(&state, seed, SEEDBYTES); + shake256_inc_finalize(&state); + shake256_inc_squeezeblocks(buf, 1, &state); + + signs = 0; + for(i = 0; i < 8; ++i) + signs |= (uint64_t)buf[i] << 8*i; + pos = 8; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + for(i = N-TAU; i < N; ++i) { + do { + if(pos >= SHAKE256_RATE) { + shake256_inc_squeezeblocks(buf, 1, &state); + pos = 0; + } + + b = buf[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2*(signs & 1); + signs >>= 1; + } +} + +/************************************************* +* Name: polyeta_pack +* +* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYETA_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyeta_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint8_t t[8]; + DBENCH_START(); + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + t[0] = ETA - a->coeffs[8*i+0]; + t[1] = ETA - a->coeffs[8*i+1]; + t[2] = ETA - a->coeffs[8*i+2]; + t[3] = ETA - a->coeffs[8*i+3]; + t[4] = ETA - a->coeffs[8*i+4]; + t[5] = ETA - a->coeffs[8*i+5]; + t[6] = ETA - a->coeffs[8*i+6]; + t[7] = ETA - a->coeffs[8*i+7]; + + r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); + r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + t[0] = ETA - a->coeffs[2*i+0]; + t[1] = ETA - a->coeffs[2*i+1]; + r[i] = t[0] | (t[1] << 4); + } +#endif + + DBENCH_STOP(*tpack); +} + + +/************************************************* +* Name: polyt1_pack +* +* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. +* Input coefficients are assumed to be standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt1_pack(uint8_t *r, const poly *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r[5*i+0] = (a->coeffs[4*i+0] >> 0); + r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); + r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); + r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); + r[5*i+4] = (a->coeffs[4*i+3] >> 2); + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt1_unpack +* +* Description: Unpack polynomial t1 with 10-bit coefficients. +* Output coefficients are standard representatives. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt1_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; + r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; + r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; + r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_pack +* +* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYT0_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyt0_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint32_t t[8]; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; + t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; + t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; + t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; + t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; + t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; + t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; + t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; + + r[13*i+ 0] = t[0]; + r[13*i+ 1] = t[0] >> 8; + r[13*i+ 1] |= t[1] << 5; + r[13*i+ 2] = t[1] >> 3; + r[13*i+ 3] = t[1] >> 11; + r[13*i+ 3] |= t[2] << 2; + r[13*i+ 4] = t[2] >> 6; + r[13*i+ 4] |= t[3] << 7; + r[13*i+ 5] = t[3] >> 1; + r[13*i+ 6] = t[3] >> 9; + r[13*i+ 6] |= t[4] << 4; + r[13*i+ 7] = t[4] >> 4; + r[13*i+ 8] = t[4] >> 12; + r[13*i+ 8] |= t[5] << 1; + r[13*i+ 9] = t[5] >> 7; + r[13*i+ 9] |= t[6] << 6; + r[13*i+10] = t[6] >> 2; + r[13*i+11] = t[6] >> 10; + r[13*i+11] |= t[7] << 3; + r[13*i+12] = t[7] >> 5; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyt0_unpack +* +* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyt0_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = a[13*i+0]; + r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; + r->coeffs[8*i+0] &= 0x1FFF; + + r->coeffs[8*i+1] = a[13*i+1] >> 5; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; + r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; + r->coeffs[8*i+1] &= 0x1FFF; + + r->coeffs[8*i+2] = a[13*i+3] >> 2; + r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; + r->coeffs[8*i+2] &= 0x1FFF; + + r->coeffs[8*i+3] = a[13*i+4] >> 7; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; + r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; + r->coeffs[8*i+3] &= 0x1FFF; + + r->coeffs[8*i+4] = a[13*i+6] >> 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; + r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; + r->coeffs[8*i+4] &= 0x1FFF; + + r->coeffs[8*i+5] = a[13*i+8] >> 1; + r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; + r->coeffs[8*i+5] &= 0x1FFF; + + r->coeffs[8*i+6] = a[13*i+9] >> 6; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; + r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; + r->coeffs[8*i+6] &= 0x1FFF; + + r->coeffs[8*i+7] = a[13*i+11] >> 3; + r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; + r->coeffs[8*i+7] &= 0x1FFF; + + r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; + } + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_pack +* +* Description: Bit-pack polynomial with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYZ_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyz_pack(uint8_t *r, const poly *a) { + unsigned int i; + uint32_t t[4]; + DBENCH_START(); + +#if GAMMA1 == (1 << 17) + for(i = 0; i < N/4; ++i) { + t[0] = GAMMA1 - a->coeffs[4*i+0]; + t[1] = GAMMA1 - a->coeffs[4*i+1]; + t[2] = GAMMA1 - a->coeffs[4*i+2]; + t[3] = GAMMA1 - a->coeffs[4*i+3]; + + r[9*i+0] = t[0]; + r[9*i+1] = t[0] >> 8; + r[9*i+2] = t[0] >> 16; + r[9*i+2] |= t[1] << 2; + r[9*i+3] = t[1] >> 6; + r[9*i+4] = t[1] >> 14; + r[9*i+4] |= t[2] << 4; + r[9*i+5] = t[2] >> 4; + r[9*i+6] = t[2] >> 12; + r[9*i+6] |= t[3] << 6; + r[9*i+7] = t[3] >> 2; + r[9*i+8] = t[3] >> 10; + } +#elif GAMMA1 == (1 << 19) + for(i = 0; i < N/2; ++i) { + t[0] = GAMMA1 - a->coeffs[2*i+0]; + t[1] = GAMMA1 - a->coeffs[2*i+1]; + + r[5*i+0] = t[0]; + r[5*i+1] = t[0] >> 8; + r[5*i+2] = t[0] >> 16; + r[5*i+2] |= t[1] << 4; + r[5*i+3] = t[1] >> 4; + r[5*i+4] = t[1] >> 12; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyz_unpack +* +* Description: Unpack polynomial z with coefficients +* in [-(GAMMA1 - 1), GAMMA1]. +* +* Arguments: - poly *r: pointer to output polynomial +* - const uint8_t *a: byte array with bit-packed polynomial +**************************************************/ +void polyz_unpack(poly *r, const uint8_t *a) { + unsigned int i; + DBENCH_START(); + +#if GAMMA1 == (1 << 17) + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = a[9*i+0]; + r->coeffs[4*i+0] |= (uint32_t)a[9*i+1] << 8; + r->coeffs[4*i+0] |= (uint32_t)a[9*i+2] << 16; + r->coeffs[4*i+0] &= 0x3FFFF; + + r->coeffs[4*i+1] = a[9*i+2] >> 2; + r->coeffs[4*i+1] |= (uint32_t)a[9*i+3] << 6; + r->coeffs[4*i+1] |= (uint32_t)a[9*i+4] << 14; + r->coeffs[4*i+1] &= 0x3FFFF; + + r->coeffs[4*i+2] = a[9*i+4] >> 4; + r->coeffs[4*i+2] |= (uint32_t)a[9*i+5] << 4; + r->coeffs[4*i+2] |= (uint32_t)a[9*i+6] << 12; + r->coeffs[4*i+2] &= 0x3FFFF; + + r->coeffs[4*i+3] = a[9*i+6] >> 6; + r->coeffs[4*i+3] |= (uint32_t)a[9*i+7] << 2; + r->coeffs[4*i+3] |= (uint32_t)a[9*i+8] << 10; + r->coeffs[4*i+3] &= 0x3FFFF; + + r->coeffs[4*i+0] = GAMMA1 - r->coeffs[4*i+0]; + r->coeffs[4*i+1] = GAMMA1 - r->coeffs[4*i+1]; + r->coeffs[4*i+2] = GAMMA1 - r->coeffs[4*i+2]; + r->coeffs[4*i+3] = GAMMA1 - r->coeffs[4*i+3]; + } +#elif GAMMA1 == (1 << 19) + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[5*i+0]; + r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; + r->coeffs[2*i+0] |= (uint32_t)a[5*i+2] << 16; + r->coeffs[2*i+0] &= 0xFFFFF; + + r->coeffs[2*i+1] = a[5*i+2] >> 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; + r->coeffs[2*i+0] &= 0xFFFFF; + + r->coeffs[2*i+0] = GAMMA1 - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = GAMMA1 - r->coeffs[2*i+1]; + } +#endif + + DBENCH_STOP(*tpack); +} + +/************************************************* +* Name: polyw1_pack +* +* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. +* Input coefficients are assumed to be standard representatives. +* +* Arguments: - uint8_t *r: pointer to output byte array with at least +* POLYW1_PACKEDBYTES bytes +* - const poly *a: pointer to input polynomial +**************************************************/ +void polyw1_pack(uint8_t *r, const poly *a) { + unsigned int i; + DBENCH_START(); + +#if GAMMA2 == (Q-1)/88 + for(i = 0; i < N/4; ++i) { + r[3*i+0] = a->coeffs[4*i+0]; + r[3*i+0] |= a->coeffs[4*i+1] << 6; + r[3*i+1] = a->coeffs[4*i+1] >> 2; + r[3*i+1] |= a->coeffs[4*i+2] << 4; + r[3*i+2] = a->coeffs[4*i+2] >> 4; + r[3*i+2] |= a->coeffs[4*i+3] << 2; + } +#elif GAMMA2 == (Q-1)/32 + for(i = 0; i < N/2; ++i) + r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); +#endif + + DBENCH_STOP(*tpack); +} diff --git a/crypto_sign/dilithium3/m4fstack/poly.h b/crypto_sign/dilithium3/m4fstack/poly.h new file mode 100644 index 00000000..8f8819b0 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/poly.h @@ -0,0 +1,82 @@ +#ifndef POLY_H +#define POLY_H + +#include +#include "params.h" + +typedef struct { + int32_t coeffs[N]; +} poly; + +#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) +void poly_reduce(poly *a); +#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) +void poly_caddq(poly *a); +#define poly_freeze DILITHIUM_NAMESPACE(poly_freeze) +void poly_freeze(poly *a); + +#define poly_add DILITHIUM_NAMESPACE(poly_add) +void poly_add(poly *c, const poly *a, const poly *b); +#define poly_sub DILITHIUM_NAMESPACE(poly_sub) +void poly_sub(poly *c, const poly *a, const poly *b); +#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) +void poly_shiftl(poly *a); + +#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) +void poly_ntt(poly *a); + +#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) +void poly_invntt_tomont(poly *a); +#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) +void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); +#define poly_pointwise_acc_montgomery DILITHIUM_NAMESPACE(poly_pointwise_acc_montgomery) +void poly_pointwise_acc_montgomery(poly *c, const poly *a, const poly *b); + +#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) +void poly_power2round(poly *a1, poly *a0, const poly *a); +#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) +void poly_decompose(poly *a1, poly *a0, const poly *a); +#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) +unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1); +#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) +void poly_use_hint(poly *b, const poly *a, const poly *h); + +#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) +int poly_chknorm(const poly *a, int32_t B); +#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) +void poly_uniform(poly *a, + const uint8_t seed[SEEDBYTES], + uint16_t nonce); +#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) +void poly_uniform_eta(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce); +#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) +void poly_uniform_gamma1(poly *a, + const uint8_t seed[CRHBYTES], + uint16_t nonce); +#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) +void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); + +#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) +void polyeta_pack(uint8_t *r, const poly *a); + +#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) +void polyt1_pack(uint8_t *r, const poly *a); +#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) +void polyt1_unpack(poly *r, const uint8_t *a); + +#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) +void polyt0_pack(uint8_t *r, const poly *a); +#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) +void polyt0_unpack(poly *r, const uint8_t *a); + +#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) +void polyz_pack(uint8_t *r, const poly *a); +#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) +void polyz_unpack(poly *r, const uint8_t *a); + +#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) +void polyw1_pack(uint8_t *r, const poly *a); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.c b/crypto_sign/dilithium3/m4fstack/polyvec.c new file mode 100644 index 00000000..e20749c0 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/polyvec.c @@ -0,0 +1,429 @@ +#include +#include "params.h" +#include "polyvec.h" +#include "poly.h" + +#include +#include "hal.h" + +/************************************************* +* Name: expand_mat +* +* Description: Implementation of ExpandA. Generates matrix A with uniformly +* random coefficients a_{i,j} by performing rejection +* sampling on the output stream of SHAKE128(rho|j|i). +* +* Arguments: - polyvecl mat[K]: output matrix +* - const uint8_t rho[]: byte array containing seed rho +**************************************************/ +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { + unsigned int i, j; + + for(i = 0; i < K; ++i) + for(j = 0; j < L; ++j) + poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); +} + +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); +} + +/**************************************************************/ +/************ Vectors of polynomials of length L **************/ +/**************************************************************/ + +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); +} + +void polyvecl_reduce(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_reduce(&v->vec[i]); +} + +#if 0 +/************************************************* +* Name: polyvecl_freeze +* +* Description: Reduce coefficients of polynomials in vector of length L +* to standard representatives. +* +* Arguments: - polyvecl *v: pointer to input/output vector +**************************************************/ +void polyvecl_freeze(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_freeze(&v->vec[i]); +} +#endif + +/************************************************* +* Name: polyvecl_add +* +* Description: Add vectors of polynomials of length L. +* No modular reduction is performed. +* +* Arguments: - polyvecl *w: pointer to output vector +* - const polyvecl *u: pointer to first summand +* - const polyvecl *v: pointer to second summand +**************************************************/ +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyvecl_ntt +* +* Description: Forward NTT of all polynomials in vector of length L. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyvecl *v: pointer to input/output vector +**************************************************/ +void polyvecl_ntt(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_ntt(&v->vec[i]); +} + +void polyvecl_invntt_tomont(polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_invntt_tomont(&v->vec[i]); +} + +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { + unsigned int i; + + for(i = 0; i < L; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + + + +/************************************************* +* Name: polyvecl_pointwise_acc_montgomery +* +* Description: Pointwise multiply vectors of polynomials of length L, multiply +* resulting vector by 2^{-32} and add (accumulate) polynomials +* in it. Input/output vectors are in NTT domain representation. +* +* Arguments: - poly *w: output polynomial +* - const polyvecl *u: pointer to first input vector +* - const polyvecl *v: pointer to second input vector +**************************************************/ +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v) +{ + unsigned int i; + + poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); + for(i = 1; i < L; ++i) { + poly_pointwise_acc_montgomery(w, &u->vec[i], &v->vec[i]); + } +} + +/************************************************* +* Name: polyvecl_chknorm +* +* Description: Check infinity norm of polynomials in vector of length L. +* Assumes input polyvecl to be reduced by polyvecl_reduce(). +* +* Arguments: - const polyvecl *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyvecl_chknorm(const polyvecl *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < L; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/**************************************************************/ +/************ Vectors of polynomials of length K **************/ +/**************************************************************/ + +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_uniform_eta(&v->vec[i], seed, nonce++); +} + +/************************************************* +* Name: polyveck_reduce +* +* Description: Reduce coefficients of polynomials in vector of length K +* to representatives in [-6283009,6283007]. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_reduce(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_reduce(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_caddq +* +* Description: For all coefficients of polynomials in vector of length K +* add Q if coefficient is negative. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_caddq(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_caddq(&v->vec[i]); +} + +#if 0 +/************************************************* +* Name: polyveck_freeze +* +* Description: Reduce coefficients of polynomials in vector of length K +* to standard representatives. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_freeze(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_freeze(&v->vec[i]); +} +#endif + +/************************************************* +* Name: polyveck_add +* +* Description: Add vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first summand +* - const polyveck *v: pointer to second summand +**************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_sub +* +* Description: Subtract vectors of polynomials of length K. +* No modular reduction is performed. +* +* Arguments: - polyveck *w: pointer to output vector +* - const polyveck *u: pointer to first input vector +* - const polyveck *v: pointer to second input vector to be +* subtracted from first input vector +**************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_shiftl +* +* Description: Multiply vector of polynomials of Length K by 2^D without modular +* reduction. Assumes input coefficients to be less than 2^{31-D}. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_shiftl(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_shiftl(&v->vec[i]); +} + +/************************************************* +* Name: polyveck_ntt +* +* Description: Forward NTT of all polynomials in vector of length K. Output +* coefficients can be up to 16*Q larger than input coefficients. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_ntt(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_ntt(&v->vec[i]); +} + + + +/************************************************* +* Name: polyveck_invntt_tomont +* +* Description: Inverse NTT and multiplication by 2^{32} of polynomials +* in vector of length K. Input coefficients need to be less +* than 2*Q. +* +* Arguments: - polyveck *v: pointer to input/output vector +**************************************************/ +void polyveck_invntt_tomont(polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_invntt_tomont(&v->vec[i]); +} + + +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); +} + + +/************************************************* +* Name: polyveck_chknorm +* +* Description: Check infinity norm of polynomials in vector of length K. +* Assumes input polyveck to be reduced by polyveck_reduce(). +* +* Arguments: - const polyveck *v: pointer to vector +* - int32_t B: norm bound +* +* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 +* and 1 otherwise. +**************************************************/ +int polyveck_chknorm(const polyveck *v, int32_t bound) { + unsigned int i; + + for(i = 0; i < K; ++i) + if(poly_chknorm(&v->vec[i], bound)) + return 1; + + return 0; +} + +/************************************************* +* Name: polyveck_power2round +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 +* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be +* standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_decompose +* +* Description: For all coefficients a of polynomials in vector of length K, +* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 +* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we +* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. +* Assumes coefficients to be standard representatives. +* +* Arguments: - polyveck *v1: pointer to output vector of polynomials with +* coefficients a1 +* - polyveck *v0: pointer to output vector of polynomials with +* coefficients a0 +* - const polyveck *v: pointer to input vector +**************************************************/ +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); +} + +/************************************************* +* Name: polyveck_make_hint +* +* Description: Compute hint vector. +* +* Arguments: - polyveck *h: pointer to output vector +* - const polyveck *v0: pointer to low part of input vector +* - const polyveck *v1: pointer to high part of input vector +* +* Returns number of 1 bits. +**************************************************/ +unsigned int polyveck_make_hint(polyveck *h, + const polyveck *v0, + const polyveck *v1) +{ + unsigned int i, s = 0; + + for(i = 0; i < K; ++i) + s += poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]); + + return s; +} + +/************************************************* +* Name: polyveck_use_hint +* +* Description: Use hint vector to correct the high bits of input vector. +* +* Arguments: - polyveck *w: pointer to output vector of polynomials with +* corrected high bits +* - const polyveck *u: pointer to input vector +* - const polyveck *h: pointer to input hint vector +**************************************************/ +void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { + unsigned int i; + + for(i = 0; i < K; ++i) + poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); +} + +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { + unsigned int i; + + for(i = 0; i < K; ++i) + polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); +} diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.h b/crypto_sign/dilithium3/m4fstack/polyvec.h new file mode 100644 index 00000000..d92cd753 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/polyvec.h @@ -0,0 +1,99 @@ +#ifndef POLYVEC_H +#define POLYVEC_H + +#include +#include "params.h" +#include "poly.h" + +/* Vectors of polynomials of length L */ +typedef struct { + poly vec[L]; +} polyvecl; + +#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) +void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) +void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) +void polyvecl_reduce(polyvecl *v); + +#define polyvecl_freeze DILITHIUM_NAMESPACE(polyvecl_freeze) +void polyvecl_freeze(polyvecl *v); + +#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); + +#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) +void polyvecl_ntt(polyvecl *v); +#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) +void polyvecl_invntt_tomont(polyvecl *v); +#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) +void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); +#define polyvecl_pointwise_acc_montgomery \ + DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) +void polyvecl_pointwise_acc_montgomery(poly *w, + const polyvecl *u, + const polyvecl *v); + + +#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) +int polyvecl_chknorm(const polyvecl *v, int32_t B); + + + +/* Vectors of polynomials of length K */ +typedef struct { + poly vec[K]; +} polyveck; + +#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) +void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); + +#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) +void polyveck_reduce(polyveck *v); +#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) +void polyveck_caddq(polyveck *v); +#define polyveck_freeze DILITHIUM_NAMESPACE(polyveck_freeze) +void polyveck_freeze(polyveck *v); + +#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); +#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) +void polyveck_shiftl(polyveck *v); + +#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) +void polyveck_ntt(polyveck *v); +#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) +void polyveck_invntt_tomont(polyveck *v); +#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) +void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); + + +#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) +int polyveck_chknorm(const polyveck *v, int32_t B); + +#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); +#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) +unsigned int polyveck_make_hint(polyveck *h, + const polyveck *v0, + const polyveck *v1); +#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) +void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); + +#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) +void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); + +#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) +void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); + +#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) +void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/reduce.h b/crypto_sign/dilithium3/m4fstack/reduce.h new file mode 100644 index 00000000..5990918a --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/reduce.h @@ -0,0 +1,79 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include +#include "params.h" + +#define MONT -4186625 // 2^32 % Q +#define QINV 58728449 // q^(-1) mod 2^32 + +#define montgomery_reduce DILITHIUM_NAMESPACE(montgomery_reduce) +/************************************************* +* Name: montgomery_reduce +* +* Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, +* compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. +* +* Arguments: - int64_t: finite field element a +* +* Returns r. +**************************************************/ +static inline int32_t montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a*QINV; + t = (a - (int64_t)t*Q) >> 32; + return t; +} + +/************************************************* +* Name: reduce32 +* +* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, +* compute r \equiv a (mod Q) such that -6283009 <= r <= 6283007. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t reduce32(int32_t a) { + int32_t t; + + t = (a + (1 << 22)) >> 23; + t = a - t*Q; + return t; +} + +/************************************************* +* Name: caddq +* +* Description: Add Q if input coefficient is negative. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* +* Name: freeze +* +* Description: For finite field element a, compute standard +* representative r = a mod^+ Q. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t freeze(int32_t a) { + a = reduce32(a); + a = caddq(a); + return a; +} + + + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/rounding.c b/crypto_sign/dilithium3/m4fstack/rounding.c new file mode 100644 index 00000000..889f0a29 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/rounding.c @@ -0,0 +1,102 @@ +#include +#include "params.h" +#include "rounding.h" + +/************************************************* +* Name: power2round +* +* Description: For finite field element a, compute a0, a1 such that +* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. +* Assumes a to be standard representative. +* +* Arguments: - int32_t a: input element +* - int32_t *a0: pointer to output element a0 +* +* Returns a1. +**************************************************/ +int32_t power2round(int32_t *a0, int32_t a) { + int32_t a1; + + a1 = (a + (1 << (D-1)) - 1) >> D; + *a0 = a - (a1 << D); + return a1; +} + +/************************************************* +* Name: decompose +* +* Description: For finite field element a, compute high and low bits a0, a1 such +* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except +* if a1 = (Q-1)/ALPHA where we set a1 = 0 and +* -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard +* representative. +* +* Arguments: - int32_t a: input element +* - int32_t *a0: pointer to output element a0 +* +* Returns a1. +**************************************************/ +int32_t decompose(int32_t *a0, int32_t a) { + int32_t a1; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + *a0 = a - a1*2*GAMMA2; + *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; + return a1; +} + +/************************************************* +* Name: make_hint +* +* Description: Compute hint bit indicating whether the low bits of the +* input element overflow into the high bits. +* +* Arguments: - int32_t a0: low bits of input element +* - int32_t a1: high bits of input element +* +* Returns 1 if overflow. +**************************************************/ +unsigned int make_hint(int32_t a0, int32_t a1) { + if(a0 > GAMMA2 || a0 < -GAMMA2 || (a0 == -GAMMA2 && a1 != 0)) + return 1; + + return 0; +} + +/************************************************* +* Name: use_hint +* +* Description: Correct high bits according to hint. +* +* Arguments: - int32_t a: input element +* - unsigned int hint: hint bit +* +* Returns corrected high bits. +**************************************************/ +int32_t use_hint(int32_t a, unsigned int hint) { + int32_t a0, a1; + + a1 = decompose(&a0, a); + if(hint == 0) + return a1; + +#if GAMMA2 == (Q-1)/32 + if(a0 > 0) + return (a1 + 1) & 15; + else + return (a1 - 1) & 15; +#elif GAMMA2 == (Q-1)/88 + if(a0 > 0) + return (a1 == 43) ? 0 : a1 + 1; + else + return (a1 == 0) ? 43 : a1 - 1; +#endif +} diff --git a/crypto_sign/dilithium3/m4fstack/rounding.h b/crypto_sign/dilithium3/m4fstack/rounding.h new file mode 100644 index 00000000..b72e8e8d --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/rounding.h @@ -0,0 +1,19 @@ +#ifndef ROUNDING_H +#define ROUNDING_H + +#include +#include "params.h" + +#define power2round DILITHIUM_NAMESPACE(power2round) +int32_t power2round(int32_t *a0, int32_t a); + +#define decompose DILITHIUM_NAMESPACE(decompose) +int32_t decompose(int32_t *a0, int32_t a); + +#define make_hint DILITHIUM_NAMESPACE(make_hint) +unsigned int make_hint(int32_t a0, int32_t a1); + +#define use_hint DILITHIUM_NAMESPACE(use_hint) +int32_t use_hint(int32_t a, unsigned int hint); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/sign.c b/crypto_sign/dilithium3/m4fstack/sign.c new file mode 100644 index 00000000..71cff9bb --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/sign.c @@ -0,0 +1,484 @@ +#include +#include "params.h" +#include "sign.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" +#include "randombytes.h" +#include "symmetric.h" +#include "smallpoly.h" +#include "stack.h" + +#include "smallntt.h" + +/************************************************* +* Name: crypto_sign_keypair +* +* Description: Generates public and private key. +* +* Arguments: - uint8_t *pk: pointer to output public key (allocated +* array of CRYPTO_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key (allocated +* array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + unsigned int i, j; + uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; + const uint8_t *rho, *rhoprime, *key; + + poly tA, tB; + + union { + uint8_t tr[TRBYTES]; + shake256incctx s256; + poly tC; + } data; + + shake256incctx *s256 = &data.s256; + uint8_t *tr = &data.tr; + poly *tC = &data.tC; + + /* Get randomness for rho, rhoprime and key */ + randombytes(seedbuf, SEEDBYTES); + shake256_inc_init(s256); + shake256_inc_absorb(s256, seedbuf, SEEDBYTES); + shake256_inc_finalize(s256); + shake256_inc_squeeze(seedbuf, 2*SEEDBYTES + CRHBYTES, s256); + + rho = seedbuf; + rhoprime = rho + SEEDBYTES; + key = rhoprime + CRHBYTES; + + pack_sk_rho(sk, rho); + pack_sk_key(sk, key); + pack_pk_rho(pk, rho); + + /* Matrix-vector multiplication */ + for (i = 0; i < K; i++) + { + /* Expand part of s1 */ + poly_uniform_eta(tC, rhoprime, 0); + if (i == 0) + { + pack_sk_s1(sk, tC, 0); + } + poly_ntt(tC); + /* expand part of the matrix */ + poly_uniform(&tB, rho, (i << 8) + 0); + /* partial matrix-vector multiplication */ + poly_pointwise_montgomery(&tA, &tB, tC); + for(j = 1; j < L; j++) + { + /* Expand part of s1 */ + poly_uniform_eta(tC, rhoprime, j); + if (i == 0) + { + pack_sk_s1(sk, tC, j); + } + poly_ntt(tC); + poly_uniform(&tB, rho, (i << 8) + j); + poly_pointwise_acc_montgomery(&tA, &tB, tC); + } + + poly_reduce(&tA); + poly_invntt_tomont(&tA); + + /* Add error vector s2 */ + /* Sample short vector s2 */ + poly_uniform_eta(&tB, rhoprime, L + i); + pack_sk_s2(sk, &tB, i); + poly_add(&tA, &tA, &tB); + + /* Compute t{0,1} */ + poly_caddq(&tA); + poly_power2round(tC, &tB, &tA); + pack_sk_t0(sk, &tB, i); + pack_pk_t1(pk, tC, i); + + } + + /* Compute H(rho, t1) and write secret key */ + shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); + pack_sk_tr(sk, tr); + + return 0; +} + + +/************************************************* +* Name: crypto_sign_signature +* +* Description: Computes signature. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_signature(uint8_t *sig, + size_t *siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *sk) +{ + uint8_t buf[2 * CRHBYTES]; + uint8_t *mu, *rhoprime, *rnd; + const uint8_t *rho, *tr, *key; + uint16_t nonce = 0; + unsigned int n; + uint8_t wcomp[K][768]; + uint8_t ccomp[68]; + + union { + shake128incctx s128; + shake256incctx s256; + } state; + + union { + poly full; + struct { + smallpoly stmp0; + smallpoly stmp1; + } small; + } polybuffer; + + poly *tmp0 = &polybuffer.full; + smallpoly *stmp0 = &polybuffer.small.stmp0; + smallpoly *scp = &polybuffer.small.stmp1; + + rho = sk; + tr = sk + SEEDBYTES*2; + key = sk + SEEDBYTES; + + mu = buf; + rnd = mu + CRHBYTES; + rhoprime = mu + CRHBYTES; + unpack_sk_stack(rho, tr, key, sk); + + /* Compute mu = CRH(tr, msg) */ + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, tr, TRBYTES); + shake256_inc_absorb(&state.s256, m, mlen); + shake256_inc_finalize(&state.s256); + shake256_inc_squeeze(mu, CRHBYTES, &state.s256); + + // Note: RNDBYTES < CRHBYTES, so buffer has proper size + for (n = 0; n < RNDBYTES; n++) { + rnd[n] = 0; + } + + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, key, SEEDBYTES); + shake256_inc_absorb(&state.s256, rnd, RNDBYTES); + shake256_inc_absorb(&state.s256, mu, CRHBYTES); + shake256_inc_finalize(&state.s256); + // rnd can be overwritten here + shake256_inc_squeeze(rhoprime, CRHBYTES, &state.s256); + +rej: + for (size_t k_idx = 0; k_idx < K; k_idx++) { + for(size_t i=0;i<768;i++){ + wcomp[k_idx][i] = 0; + } + } + + for (size_t l_idx = 0; l_idx < L; l_idx++) { + /* Sample intermediate vector y */ + poly_uniform_gamma1_stack(tmp0, rhoprime, L*nonce + l_idx, &state.s256); + poly_ntt(tmp0); + + /* Matrix-vector multiplication */ + for (size_t k_idx = 0; k_idx < K; k_idx++) { + // sampling of y and packing into wcomp inlined into the basemul + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp[k_idx], tmp0, rho, (k_idx << 8) + l_idx, &state.s128); + } + } + nonce++; + for (size_t k_idx = 0; k_idx < K; k_idx++) { + polyw_unpack(tmp0, wcomp[k_idx]); + poly_invntt_tomont(tmp0); + poly_caddq(tmp0); + + polyw_pack(wcomp[k_idx], tmp0); + poly_highbits(tmp0, tmp0); + polyw1_pack(&sig[k_idx*POLYW1_PACKEDBYTES], tmp0); + } + + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, mu, CRHBYTES); + shake256_inc_absorb(&state.s256, sig, K*POLYW1_PACKEDBYTES); + shake256_inc_finalize(&state.s256); + shake256_inc_squeeze(sig, CTILDEBYTES, &state.s256); + poly_challenge(tmp0, sig); + + poly_challenge_compress(ccomp, tmp0); + + /* Compute z, reject if it reveals secret */ + for(size_t l_idx=0;l_idx < L; l_idx++){ + if(l_idx != 0){ + poly_challenge_decompress(tmp0, ccomp); + } + poly_small_ntt_copy(scp, tmp0); + unpack_sk_s1(stmp0, sk, l_idx); + small_ntt(stmp0->coeffs); + poly_small_basemul_invntt(tmp0, scp, stmp0); + + poly_uniform_gamma1_add_stack(tmp0, tmp0, rhoprime, L*(nonce-1) + l_idx, &state.s256); + + poly_reduce(tmp0); + + if(poly_chknorm(tmp0, GAMMA1 - BETA)) + goto rej; + + polyz_pack(sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES, tmp0); + } + + + /* Write signature */ + unsigned int hint_n = 0; + unsigned int hints_written = 0; + /* Check that subtracting cs2 does not change high bits of w and low bits + * do not reveal secret information */ + + for(unsigned int k_idx = 0; k_idx < K; ++k_idx) { + poly_challenge_decompress(tmp0, ccomp); + poly_small_ntt_copy(scp, tmp0); + + unpack_sk_s2(stmp0, sk, k_idx); + small_ntt(stmp0->coeffs); + poly_small_basemul_invntt(tmp0, scp, stmp0); + + polyw_sub(tmp0, wcomp[k_idx], tmp0); + poly_reduce(tmp0); + + polyw_pack(wcomp[k_idx], tmp0); + + poly_lowbits(tmp0, tmp0); + poly_reduce(tmp0); + if(poly_chknorm(tmp0, GAMMA2 - BETA)){ + goto rej; + } + + poly_schoolbook(tmp0, ccomp, sk + SEEDBYTES + TRBYTES + SEEDBYTES + + L*POLYETA_PACKEDBYTES + K*POLYETA_PACKEDBYTES + k_idx*POLYT0_PACKEDBYTES); + + /* Compute hints for w1 */ + + if(poly_chknorm(tmp0, GAMMA2)) { + goto rej; + } + + hint_n += poly_make_hint_stack(tmp0, tmp0, wcomp[k_idx]); + + if (hint_n > OMEGA) { + goto rej; + } + pack_sig_h(sig, tmp0, k_idx, &hints_written); + } + pack_sig_h_zero(sig, &hints_written); + *siglen = CRYPTO_BYTES; + return 0; +} + +/************************************************* +* Name: crypto_sign +* +* Description: Compute signed message. +* +* Arguments: - uint8_t *sm: pointer to output signed message (allocated +* array with CRYPTO_BYTES + mlen bytes), +* can be equal to m +* - size_t *smlen: pointer to output length of signed +* message +* - const uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - const uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign(uint8_t *sm, + size_t *smlen, + const uint8_t *m, + size_t mlen, + const uint8_t *sk) +{ + size_t i; + + for(i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + *smlen += mlen; + return 0; +} + +/************************************************* +* Name: crypto_sign_verify +* +* Description: Verifies signature. +* +* Arguments: - uint8_t *m: pointer to input signature +* - size_t siglen: length of signature +* - const uint8_t *m: pointer to message +* - size_t mlen: length of message +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signature could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_verify(const uint8_t *sig, + size_t siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *pk) +{ + unsigned int i; + + poly p; + + union { + uint8_t w1_packed[POLYW1_PACKEDBYTES]; + uint8_t wcomp[768]; + } w1_packed_comp; + uint8_t *w1_packed = &w1_packed_comp.w1_packed; + uint8_t *wcomp = &w1_packed_comp.wcomp; + + union { + uint8_t ccomp[68]; + uint8_t mu[CRHBYTES]; + } ccomp_mu; + uint8_t *ccomp = &ccomp_mu.ccomp; + uint8_t *mu = &ccomp_mu.mu; + + shake256incctx s256; + + union { + uint8_t hint_ones[OMEGA]; + shake128incctx s128; + uint8_t c2[CTILDEBYTES]; + } shake_hint; + + uint8_t *hint_ones = &shake_hint.hint_ones; + shake128incctx *s128 = &shake_hint.s128; + uint8_t *c2 = &shake_hint.c2; + + if(siglen != CRYPTO_BYTES) + return -1; + + /* Compute CRH(h(rho, t1), msg) */ + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, pk, CRYPTO_PUBLICKEYBYTES); + shake256_inc_finalize(&s256); + shake256_inc_squeeze(mu, CRHBYTES, &s256); + + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, mu, TRBYTES); + shake256_inc_absorb(&s256, m, mlen); + shake256_inc_finalize(&s256); + shake256_inc_squeeze(mu, CRHBYTES, &s256); + + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, mu, CRHBYTES); + + /* Matrix-vector multiplication; compute Az - c2^dt1 */ + poly_challenge_stack(&p, sig); + poly_challenge_compress(ccomp, &p); + + for (size_t k_idx = 0; k_idx < K; k_idx++) { + for(size_t widx=0;widx<768;widx++){ + wcomp[widx] = 0; + } + + polyz_unpack(&p, sig + CTILDEBYTES); + if(poly_chknorm(&p, GAMMA1 - BETA)) + return -1; + poly_ntt(&p); + + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + 0, s128); + + for (size_t l_idx = 1; l_idx < L; l_idx++) { + polyz_unpack(&p, sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES); + if(poly_chknorm(&p, GAMMA1 - BETA)) + return -1; + poly_ntt(&p); + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + l_idx, s128); + } + polyw_unpack(&p, wcomp); + poly_reduce(&p); + poly_invntt_tomont(&p); + polyw_pack(wcomp, &p); + + poly_schoolbook_t1(&p, ccomp, pk + SEEDBYTES + k_idx*POLYT1_PACKEDBYTES); + + polyw_sub(&p, wcomp, &p); + poly_reduce(&p); + + /* Reconstruct w1 */ + poly_caddq(&p); + + if (unpack_sig_h_indices(hint_ones, &i, k_idx, sig) != 0) + { + return -1; + } + poly_use_hint_stack(&p, &p, hint_ones, i); + + polyw1_pack(w1_packed, &p); + + shake256_inc_absorb(&s256, w1_packed, POLYW1_PACKEDBYTES); + } + /* Call random oracle and verify challenge */ + shake256_inc_finalize(&s256); + shake256_inc_squeeze(c2, CTILDEBYTES, &s256); + for(i = 0; i < CTILDEBYTES; ++i) + if(sig[i] != c2[i]) + return -1; + + return 0; +} + +/************************************************* +* Name: crypto_sign_open +* +* Description: Verify signed message. +* +* Arguments: - uint8_t *m: pointer to output message (allocated +* array with smlen bytes), can be equal to sm +* - size_t *mlen: pointer to output length of message +* - const uint8_t *sm: pointer to signed message +* - size_t smlen: length of signed message +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signed message could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_open(uint8_t *m, + size_t *mlen, + const uint8_t *sm, + size_t smlen, + const uint8_t *pk) +{ + size_t i; + + if(smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for(i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + for(i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/crypto_sign/dilithium3/m4fstack/sign.h b/crypto_sign/dilithium3/m4fstack/sign.h new file mode 100644 index 00000000..42240b30 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/sign.h @@ -0,0 +1,37 @@ +#ifndef SIGN_H +#define SIGN_H + +#include +#include +#include "params.h" +#include "api.h" +#include "polyvec.h" +#include "poly.h" + +#define challenge DILITHIUM_NAMESPACE(challenge) +void challenge(poly *c, const uint8_t seed[SEEDBYTES]); + +// #define crypto_sign_keypair DILITHIUM_NAMESPACE(crypto_sign_keypair) +// int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +// #define crypto_sign_signature DILITHIUM_NAMESPACE(signature) +// int crypto_sign_signature(uint8_t *sig, size_t *siglen, +// const uint8_t *m, size_t mlen, +// const uint8_t *sk); + +// #define crypto_sign DILITHIUM_NAMESPACE(crypto_sign) +// int crypto_sign(uint8_t *sm, size_t *smlen, +// const uint8_t *m, size_t mlen, +// const uint8_t *sk); + +// #define crypto_sign_verify DILITHIUM_NAMESPACE(verify) +// int crypto_sign_verify(const uint8_t *sig, size_t siglen, +// const uint8_t *m, size_t mlen, +// const uint8_t *pk); + +// #define crypto_sign_open DILITHIUM_NAMESPACE(crypto_sign_open) +// int crypto_sign_open(uint8_t *m, size_t *mlen, +// const uint8_t *sm, size_t smlen, +// const uint8_t *pk); + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/smallntt.h b/crypto_sign/dilithium3/m4fstack/smallntt.h new file mode 100644 index 00000000..244fad24 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallntt.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMALLNTT_H +#define SMALLNTT_H + +#include +#include "params.h" + +#define SMALL_Q 769 + +static const int32_t zetas_769[64] = { + 3138844760, 1334846793, 999738812, 1854264165, 1681125041, 1150537404, 2820492178, 3071823164, 726067294, 2066499220, 3272887953, 1055590142, 4255871365, 1871019564, 2731130050, 1826338500, 513832239, 1792827701, 3373420347, 2993631302, 1161707670, 3306398751, 3518633806, 3406931146, 1586177780, 3853741788, 3317569017, 3825816122, 971813147, 122872927, 217820188, 619949766, 3753209393, 770748358, 4099487641, 765163225, 3630336467, 1742561504, 3479537875, 982983413, 2809321912, 2379266669, 703726762, 681386230, 4110657907, 1457719720, 1217559000, 2474213930, 1195218468, 1089100940, 564098436, 614364633, 3635921600, 2088839752, 3702943196, 1949211426, 2569161192, 374203913, 3982199847, 2083254619, 1513571050, 3647091866, 413299844, 4149753838}; + +static const int32_t zetas_asm_769[128] = { + 346278248, 223405321, 966228013, 759578091, -150798592, 318352582, -1736976371, 1697880440, -2105595150, -804259156, 1675539907, -1016494210, 1401868389, -2005062756, 240160720, 474736307, -1200803600, -1435379187, -1156122536, 1334846793, 999738811, 1854264164, -631120032, -787503756, -1580592646, 1681125040, 1150537403, -1474475119, -1223144132, 1809583100, -100532394, -1938041160, 726067293, 2066499219, -1022079344, 1055590142, 525002504, 273671518, -212235055, -39095931, 1871019563, -1563837247, 1826338499, 139628326, 27925665, 1731391238, 513832238, 1792827701, -921546949, -1301335995, 67021596, 1117026605, 536172770, 1161707669, -988568545, -776333490, -888036151, 1290165729, -497076839, -753992958, 1586177779, -441225509, -977398279, -469151174, -1614103444, 1591762912, -94947261, 971813146, 122872927, 217820188, 619949766, -1709050706, 1010909077, -1748146637, -541757903, 770748357, -195479656, 765163224, 1413038655, 1781657435, -1206388733, -664630830, 1742561504, -815429422, 982983412, 357448514, 44681064, -1524741316, -1485645385, -1915700627, 703726761, 681386229, 686971362, 1787242568, -860110486, -184309390, 1457719719, 1217558999, -1820753366, -502661972, -1921285760, 1139367137, 1195218467, 1089100940, 564098435, 614364633, -1100271206, 457980908, -1669954774, -659045697, 2088839751, -592024101, 1949211426, 1368357591, 698141628, 335107981, -1725806105, 374203913, -312767449, 2083254618, -1061175275, -2139105948, 519417371, 1513571050, -647875431, 413299844, -145213459, 0}; + +// INTT with CT butterfly +static const int32_t zetas_inv_asm_769[256] = { + 5585134, 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 5585134, 1736976371, -966228013, 150798592, -346278248, -318352582, -223405321, -759578091, + // removed first "2285" + LAYER 3+2+1 - 1 - butterfly + 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 636705165, 446810642, 1519156183, 11170266, -821014555, -1932456027, 301597183, -692556495, -240160720, 1061175275, -1368357591, -519417371, -335107981, 2139105948, -698141628, -625534899, -1267825197, 843355087, 290426917, 128458060, 1295750862, -748407825, -826599688, 1736976371, -240160720, 2005062756, 1061175275, 1100271206, -1368357591, 502661972, 915961816, 1396283256, 452395775, -1038834743, -955057747, -670215963, 2016233022, -16755399, -1675539907, 1614103444, -1290165729, 94947261, 753992958, -1591762912, 497076839, -1954796559, 1943626293, -1122611738, -1239899531, 938302348, -245745853, 882451018, -435640376, -966228013, 1736976371, -318352582, -240160720, -1401868389, 2005062756, 1016494210, 714897027, -1005323944, 876865885, 2122350549, -1373942724, -2094424884, 1468889985, 1558252114, -1401868389, -686971362, -357448514, 860110486, 1524741316, -1787242568, -44681064, 1407453522, -368618780, 1323676527, -653460564, -1362772458, 1379527857, -463566041, 1859849297, 150798592, -1675539907, 804259156, 1614103444, -67021596, -1290165729, -139628326, -2060914086, -994153678, 55851330, 189894523, -1072345541, 1507985917, 832184821, 1111441472, 2105595150, -525002504, -1809583100, 212235055, 1938041160, -273671518, 100532394, -2044158687, -78191862, 1452134586, 642290298, -2111180283, 552928169, 161968858, -1167292802, -346278248, -966228013, -223405321, 1736976371, 150798592, -318352582, -759578091, -1608518311, -2032988421, -899206417, -480321440, 943887481, 1491230518, -83776995, -284841784, 2005062756, 1100271206, 502661972, 1669954774, -1139367137, -457980908, 1921285760, 1128196871, -1318091394, -1904530361, 396544445, -1228729265, 117287794, 2116765416, 1184048201, -318352582, -1401868389, 1016494210, -686971362, -1413038655, -357448514, 1709050706, -731652426, 89362128, 2021818155, 1720220972, -1882189829, -1245484665, -798674023, 720482160, 804259156, -67021596, -139628326, -536172770, -1731391238, -1117026605, -27925665, -1843093898, -1971551958, 1027664477, 1776072302, -1692295306, 1977137091, 709311894, 1552666981, -223405321, 150798592, -759578091, -1675539907, 2105595150, 804259156, -1697880440, -675801096, 279256651, 949472614, -1066760408, -1050005009, -134043193, 1262240064, 1714635839, 1016494210, -1413038655, 1709050706, 1206388733, 1748146637, -1781657435, -1010909077, -390959312, -1329261660, -1083515807, -1965966825, -1530326449, 809844289, -1541496715, 1630858843, -759578091, 2105595150, -1697880440, -525002504, 631120032, -1809583100, -474736307, -1575007513, -201064789, 1893360095, 424470110, -1133782004, -418884977, -1424208921, -547343036, -1697880440, 631120032, -474736307, 1580592646, 1435379187, 787503756, 1200803600, 1999477623, -932717215, 1982722224, -1848679031, 586438968, 1993892490, 1625273710, -1346017059, 0}; + +// Q1=769 +void small_ntt_asm_769(int16_t a[N], const int32_t * zetas); +void small_invntt_asm_769(int16_t a[N], const int32_t * zetas); +void small_basemul_asm_769(int16_t *c, const int16_t *a, const int16_t *b, const int32_t *zetas); + +// small NTT for computing cs0 and cs1 +#define small_ntt(a) small_ntt_asm_769(a, zetas_asm_769) +#define small_invntt_tomont(a) small_invntt_asm_769(a, zetas_inv_asm_769) +#define small_basemul(r,a,b) small_basemul_asm_769(r, a, b, zetas_769) + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/smallntt_769.S b/crypto_sign/dilithium3/m4fstack/smallntt_769.S new file mode 100644 index 00000000..1c3c9a88 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallntt_769.S @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NTT and inverse NTT code from: + * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. + * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. + * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. + * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S +*/ + +#include "macros.i" + +.syntax unified +.cpu cortex-m4 +.thumb + +#include "macros_smallntt.i" +// ####### +// ####### +// # NTT # +// ####### +// ####### + +.macro _3_layer_double_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_CT_16_plant_fp c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle1, twiddle2, q, qa, tmp + // layer 3 + vmov \twiddle1, \xi0 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + vmov \twiddle1, \xi1 + vmov \twiddle2, \xi2 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + vmov \twiddle1, \xi3 + vmov \twiddle2, \xi4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + vmov \twiddle1, \xi5 + vmov \twiddle2, \xi6 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.global small_ntt_asm_769 +.type small_ntt_asm_769, %function +.align 2 +small_ntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s24} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + ### qinv .req r11 ### q^-1 mod 2^2n; n=16 + q .req r12 + ### at the top of r12 + qa .req r0 + ### qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + // movw qa, #24608 + // Why movt? Because we initially placed qa at the bottom of the same register as q; + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 256 + .equ offset, 32 + .equ strincr, 4 + // pre-load 15 twiddle factors to 15 FPU registers + // s0-s7 used to temporary store 16 16-bit polys. + vldm twiddle_ptr!, {s8-s22} + + add tmp, poly, #strincr*8 + // s23: poly addr + // s24: tmp + vmov s24, tmp + 1: + // load a1, a3, ..., a15 + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // 8-NTT on a1, a3, ..., a15 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // s15, s16, s17, s18, s19, s20, s21, s22 left + // multiply coeffs by layer 8 twiddles for later use + vmov twiddle1, s15 + vmov twiddle2, s16 + mul_twiddle_plant poly0, twiddle1, tmp, q, qa + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + + vmov poly, s23 + + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // 8-NTT on a0, a2, ..., a14 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle1, s1 // load a3 + uadd16 tmp, poly1, twiddle1 + usub16 poly1, poly1, twiddle1 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle1, s3 // load a7 + uadd16 tmp, poly3, twiddle1 + usub16 poly3, poly3, twiddle1 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle1, s5 // load a11 + uadd16 tmp, poly5, twiddle1 + usub16 poly5, poly5, twiddle1 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle1, s7 // load a15 + uadd16 tmp, poly7, twiddle1 + usub16 poly7, poly7, twiddle1 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle1, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle1, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle1, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle1, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle1, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle1, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle1, poly0, poly1 + str.w twiddle1, [poly, #offset] + str.w tmp, [poly], #4 + + vmov tmp, s24 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance/16 + .equ strincr, 32 + + add.w tmp, poly, #strincr*16 + vmov s13, tmp + 2: + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s23 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #strincr + + vmov tmp, s13 + cmp.w poly, tmp + bne.w 2b + vpop.w {s16-s24} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + + +// ######## +// ######## +// # INTT # +// ######## +// ######## + +// input: 0.5/1q +.macro _3_layer_double_inv_CT_16_plant_light c0, c1, c2, c3, c4, c5, c6, c7, xi2, xi4, xi5, xi6, twiddle1, tmp2, q, qa, tmp + + // layer 1 + sadd16.w \tmp, \c0, \c1 // c0, c1 + ssub16.w \c1, \c0, \c1 + sadd16.w \tmp2, \c2, \c3 // c2, c3 + ssub16.w \c3, \c2, \c3 + // tmp, c1, tmp2, c3: 1q maximum + sadd16.w \c0, \c4, \c5 // c4, c5 + ssub16.w \c5, \c4, \c5 + sadd16.w \c2, \c6, \c7 // c6, c7 + ssub16.w \c7, \c6, \c7 + // c4, c6 are free at this point + // c0,c5,c2,c7 1q maximum + + // layer 2 + sadd16.w \c6, \tmp, \tmp2 // c0, c2 + ssub16.w \tmp2, \tmp, \tmp2 + sadd16.w \c4, \c0, \c2 // c4, c6 + ssub16.w \c2, \c0, \c2 + // c6, tmp2, c4, c2: 2q maximum + + vmov.w \twiddle1, \xi2 + doublebutterfly_plant \c1, \c3, \twiddle1, \tmp, \q, \qa + doublebutterfly_plant \c5, \c7, \twiddle1, \tmp, \q, \qa + // c1, c3, c7, c5: 1.5q maximum; + + // tmp and c0 are free at this point + // layer 3 + sadd16.w \c0, \c6, \c4 // c0, c4 + ssub16.w \c4, \c6, \c4 + // c0, c4: 4q + // c6 are free at this point + vmov.w \twiddle1, \xi4 + doublebutterfly_plant \c1, \c5, \twiddle1, \tmp, \q, \qa + // c1, c5: 2q maximum + + vmov.w \twiddle1, \xi5 + // this block is one doublebutterfly + smulwb \tmp, \twiddle1, \c2 // c2, c6 + smulwt \c2, \twiddle1, \c2 + smlabt \tmp, \tmp, \q, \qa + smlabt \c2, \c2, \q, \qa + pkhtb \tmp, \c2, \tmp, asr#16 + ssub16.w \c6, \tmp2, \tmp + sadd16.w \c2, \tmp2, \tmp + //c6, c2: 4.5q + vmov.w \twiddle1, \xi6 + doublebutterfly_plant \c3, \c7, \twiddle1, \tmp, \q, \qa + //c3, c7: 2.5q maximum +.endm +.macro _3_layer_double_inv_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_inv_twist_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c0, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c1, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c2, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c3, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c4, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c5, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c6, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c7, \twiddle2, \tmp, \q, \qa +.endm +# input coefficients < 0.5q +.global small_invntt_asm_769 +.type small_invntt_asm_769, %function +.align 2 +small_invntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s23} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + q .req r12 + // at the top of r12 + qa .req r0 + // qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 16 + .equ offset, 32 + .equ strincr, 64 + + // pre-load twiddle factors to FPU registers + vldm twiddle_ptr!, {s8-s22} + + add.w tmp, poly, #8*strincr + vmov s8, tmp + 1: + vmov s23, poly + // load a1, a3, ..., a15 + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // NTT on a1, a3, ..., a15 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // multiply coeffs by layer 4 twiddles for later use + // vmov twiddle1, s15 + vmov twiddle2, s16 + // mul_twiddle_plant poly0, twiddle1, tmp, q, qa // could be omitted but kept for reduction only + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + // 0.5q + // ---------- + + vmov poly, s23 + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // NTT on a0, a2, ..., a14 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + // 1,3,5,7: <5q; 0,2,4,6:<1q + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle2, s1 // load a3 + uadd16 tmp, poly1, twiddle2 + usub16 poly1, poly1, twiddle2 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle2, s3 // load a7 + uadd16 tmp, poly3, twiddle2 + usub16 poly3, poly3, twiddle2 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle2, s5 // load a11 + uadd16 tmp, poly5, twiddle2 + usub16 poly5, poly5, twiddle2 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle2, s7 // load a15 + uadd16 tmp, poly7, twiddle2 + usub16 poly7, poly7, twiddle2 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + //1,3,5,7: < 5.5q + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle2, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle2, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle2, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle2, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle2, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle2, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle2, poly0, poly1 + str.w twiddle2, [poly, #offset] + str.w tmp, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) + //0,2,4,6: < 1.5q + vmov tmp, s8 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance*16 + .equ strincr, 4 + + // ITER 0 + vmov s6, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + vldm twiddle_ptr!, {s0-s5} + movw qa, #24608 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s1, s3, s4, s5, twiddle1, twiddle2, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + // ITER 1-15 + add.w tmp, poly, #strincr*3*(5) + vmov s14, tmp + 2: + vmov s6, poly + // polys upto 5.5q + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_inv_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + vmov tmp, s14 + cmp.w poly, tmp + bne.w 2b + + vpop.w {s16-s23} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + +// BASEMUL + +/* +* Basemul code (adapted to q=769) from: +* Huang, J. et al. 2022. Improved Plantard Arithmetic for Lattice-based Cryptography. +* IACR Transactions on Cryptographic Hardware and Embedded Systems. 2022, 4 (Aug. 2022), 614–636. +* DOI:https://doi.org/10.46586/tches.v2022.i4.614-636. +* https://github.com/UIC-ESLAS/ImprovedPlantardArithmetic/blob/f3482cfd09dda8f1f55b95e13616147e3b6dd008/crypto_kem/kyber768/m4fstack/fastbasemul.S +*/ + +.global small_basemul_asm_769 +.type small_basemul_asm_769, %function +.align 2 +small_basemul_asm_769: + push {r4-r11, lr} + + rptr .req r0 + aptr .req r1 + bptr .req r2 + zetaptr .req r3 + poly0 .req r4 + poly1 .req r6 + poly2 .req r5 + poly3 .req r7 + q .req r8 + qa .req r14 + qinv .req r9 + tmp .req r10 + tmp2 .req r11 + zeta .req r12 + loop .req r14 + + movt q, #769 + movw qinv, #64769 + movt qinv, #58632 + + movw loop, #64 + 1: + vmov.w s0,loop + movw qa, #24608 + + ldrd poly0, poly2, [aptr], #8 + ldrd poly1, poly3, [bptr], #8 + // ldr poly0, [aptr], #4 + // ldr poly1, [bptr], #4 + // ldr poly2, [aptr], #4 + // ldr poly3, [bptr], #4 + + ldr.w zeta, [zetaptr], #4 + + // basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, zetas[64 + i]); + smulwt tmp, zeta, poly1 + smlabt tmp, tmp, q, qa + smultt tmp, poly0, tmp + smlabb tmp, poly0, poly1, tmp + plant_red q, qa, qinv, tmp + // r[0] in upper half of tmp + + smuadx tmp2, poly0, poly1 + plant_red q, qa, qinv, tmp2 + // r[1] in upper half of tmp2 + pkhtb tmp, tmp2, tmp, asr#16 + str tmp, [rptr], #4 + + neg zeta, zeta + + // basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - zetas[64 + i]); + smulwt tmp, zeta, poly3 + smlabt tmp, tmp, q, qa + smultt tmp, poly2, tmp + smlabb tmp, poly2, poly3, tmp + plant_red q, qa, qinv, tmp + // r[0] in upper half of tmp + + smuadx tmp2, poly2, poly3 + plant_red q, qa, qinv, tmp2 + // r[1] in upper half of tmp2 + pkhtb tmp, tmp2, tmp, asr#16 + str tmp, [rptr], #4 + + vmov.w loop,s0 + subs.w loop, #1 + bne.w 1b + + .unreq rptr + .unreq aptr + .unreq bptr + .unreq zetaptr + .unreq poly0 + .unreq poly1 + .unreq poly2 + .unreq poly3 + .unreq q + .unreq qa + .unreq qinv + .unreq tmp + .unreq tmp2 + .unreq zeta + .unreq loop + + pop {r4-r11, pc} +//-0.5p~0.5p \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.c b/crypto_sign/dilithium3/m4fstack/smallpoly.c new file mode 100644 index 00000000..433d98af --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallpoly.c @@ -0,0 +1,83 @@ +#include "smallpoly.h" +#include "smallntt.h" + +void poly_small_ntt_copy(smallpoly *out, poly *in) { + for (int i = N - 1; i >= 0; i--) + { + out->coeffs[i] = in->coeffs[i]; + } + small_ntt(out->coeffs); +} + + +void polyvecl_small_ntt(smallpoly v[L]) { + unsigned int i; + + for(i = 0; i < L; ++i) + small_ntt(v[i].coeffs); +} + + +void polyveck_small_ntt(smallpoly v[K]) { + unsigned int i; + + for(i = 0; i < K; ++i) + small_ntt(v[i].coeffs); +} + + + +void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b){ + // re-use the buffer + smallpoly *tmp = (smallpoly *)r; + small_basemul(tmp->coeffs, a->coeffs, b->coeffs); + small_invntt_tomont(tmp->coeffs); + + #ifdef SMALL_POLY_16_BIT + int j; + // buffer is the same, so we neeed to be careful + for(j=N-1;j>=0;j--){ + r->coeffs[j] = tmp->coeffs[j]; + } + #endif +} + +void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]){ + unsigned int i; + for(i=0;ivec[i], a, &b[i]); + } +} + +void small_polyeta_unpack(smallpoly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; + r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; + r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; + r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; + r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; + r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; + r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; + r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; + + r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[i] & 0x0F; + r->coeffs[2*i+1] = a[i] >> 4; + r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; + } +#endif +} diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.h b/crypto_sign/dilithium3/m4fstack/smallpoly.h new file mode 100644 index 00000000..1aac98fa --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallpoly.h @@ -0,0 +1,27 @@ +#ifndef SMALLPOLY_H +#define SMALLPOLY_H +#include "params.h" +#include "poly.h" +#include "polyvec.h" + + + +#define SMALL_POLY_16_BIT +typedef struct { + int16_t coeffs[N]; +} smallpoly; + +typedef smallpoly smallhalfpoly; + +void poly_small_ntt_copy(smallpoly*, poly*); + +void polyvecl_small_ntt(smallpoly v[L]); +void polyveck_small_ntt(smallpoly v[K]); + + +void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]); +void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b); + +void small_polyeta_unpack(smallpoly *r, const uint8_t *a); + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.c b/crypto_sign/dilithium3/m4fstack/stack.c new file mode 100644 index 00000000..b45f7021 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/stack.c @@ -0,0 +1,715 @@ +#include "stack.h" +#include "fips202.h" +#include "symmetric.h" +#include "vector.h" +#include "reduce.h" +#include "rounding.h" + +void poly_challenge_compress(uint8_t c[68], const poly *cp){ + unsigned int i, pos; + uint64_t signs; + uint64_t mask; + /* Encode c */ + for(i=0;i<68;i++) c[i] = 0; + signs = 0; + mask = 1; + pos = 0; + for(i = 0; i < N; ++i){ + if(cp->coeffs[i] != 0){ + c[pos++] = i; + if(cp->coeffs[i] == -1){ + signs |= mask; + } + mask <<= 1; + } + } + + for (i = 0; i < 8; ++i) { + c[60+i] = (unsigned char) (signs >> 8 * i); + } +} + +void poly_challenge_decompress(poly *cp, const uint8_t c[68]){ + unsigned int i; + unsigned pos; + uint64_t signs = 0; + for(i = 0; i < N; i++) cp->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)c[60+i]) << (8*i); + } + + for(i = 0; i < TAU; i++){ + pos = c[i]; + if(signs & 1){ + cp->coeffs[pos] = -1; + } else { + cp->coeffs[pos] = 1; + } + signs >>= 1; + } +} + + +// TODO: buffer at most 8 coeffs at once +static inline int32_t polyt0_unpack_idx(const uint8_t *t0, unsigned idx){ + int32_t coeff; + // 8 coefficients are packed in 13 bytes + t0 += 13*(idx >> 3); + + if(idx % 8 == 0){ + coeff = t0[0]; + coeff |= (uint32_t)t0[1] << 8; + } else if(idx % 8 == 1){ + coeff = t0[1] >> 5; + coeff |= (uint32_t)t0[2] << 3; + coeff |= (uint32_t)t0[3] << 11; + } else if(idx % 8 == 2){ + coeff = t0[3] >> 2; + coeff |= (uint32_t)t0[4] << 6; + } else if(idx % 8 == 3){ + coeff = t0[4] >> 7; + coeff |= (uint32_t)t0[5] << 1; + coeff |= (uint32_t)t0[6] << 9; + } else if(idx % 8 == 4){ + coeff = t0[6] >> 4; + coeff |= (uint32_t)t0[7] << 4; + coeff |= (uint32_t)t0[8] << 12; + } else if(idx % 8 == 5){ + coeff = t0[8] >> 1; + coeff |= (uint32_t)t0[9] << 7; + } else if(idx % 8 == 6){ + coeff = t0[9] >> 6; + coeff |= (uint32_t)t0[10] << 2; + coeff |= (uint32_t)t0[11] << 10; + } else if(idx % 8 == 7){ + coeff = t0[11] >> 3; + coeff |= (uint32_t)t0[12] << 5; + } + coeff &= 0x1FFF; + return (1 << (D-1)) - coeff; +} + +static inline int32_t polyt1_unpack_idx(const uint8_t *t1, unsigned idx){ + int32_t coeff; + // 4 coefficients are packed in 5 bytes + t1 += 5*(idx >> 2); + + if(idx % 4 == 0){ + coeff = (t1[0] >> 0); + coeff |= ((uint32_t)t1[1] << 8); + } else if(idx % 4 == 1){ + coeff = (t1[1] >> 2); + coeff |= ((uint32_t)t1[2] << 6); + } else if(idx % 4 == 2){ + coeff = (t1[2] >> 4); + coeff |= ((uint32_t)t1[3] << 4); + } else if(idx % 4 == 3){ + coeff = (t1[3] >> 6); + coeff |= ((uint32_t)t1[4] << 2); + } + coeff &= 0x3FF; + return coeff; +} + +void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0){ + unsigned i,j,idx; + uint64_t signs = 0; + for(i = 0; i < N; i++) c->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)ccomp[60+i]) << (8*i); + } + + for(idx = 0; idx < TAU; idx++){ + i = ccomp[idx]; + if(!(signs & 1)){ + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] += polyt0_unpack_idx(t0, j); + } + for(j = N-i; jcoeffs[i+j-N] -= polyt0_unpack_idx(t0, j); + } + } else { + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] -= polyt0_unpack_idx(t0, j); + } + for(j = N-i; jcoeffs[i+j-N] += polyt0_unpack_idx(t0, j); + } + } + + signs >>= 1; + } +} + +void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1){ + unsigned i,j,idx; + uint64_t signs = 0; + for(i = 0; i < N; i++) c->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)ccomp[60+i]) << (8*i); + } + + for(idx = 0; idx < TAU; idx++){ + i = ccomp[idx]; + if(!(signs & 1)){ + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] += (polyt1_unpack_idx(t1, j) << D); + } + for(j = N-i; jcoeffs[i+j-N] -= (polyt1_unpack_idx(t1, j) << D); + } + } else { + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] -= (polyt1_unpack_idx(t1, j) << D); + } + for(j = N-i; jcoeffs[i+j-N] += (polyt1_unpack_idx(t1, j) << D); + } + } + + signs >>= 1; + } +} + + +void polyw_pack(uint8_t buf[3*256], poly *w){ + poly_reduce(w); + poly_caddq(w); + unsigned int i; + for(i = 0; i < N; i++){ + buf[i*3 + 0] = w->coeffs[i]; + buf[i*3 + 1] = w->coeffs[i] >> 8; + buf[i*3 + 2] = w->coeffs[i] >> 16; + } +} + +void polyw_unpack(poly *w, const uint8_t buf[3*256]) { + unsigned int i; + for(i = 0; i < N; i++){ + w->coeffs[i] = buf[i*3 + 0]; + w->coeffs[i] |= (int32_t)buf[i*3 + 1] << 8; + w->coeffs[i] |= (int32_t)buf[i*3 + 2] << 16; + } +} + + +static void polyw_add_idx(uint8_t buf[3*256], int32_t a, size_t i){ + int32_t coeff; + coeff = buf[i*3 + 0]; + coeff |= (int32_t)buf[i*3 + 1] << 8; + coeff |= (int32_t)buf[i*3 + 2] << 16; + + coeff += a; + + coeff = freeze(coeff); + + buf[i*3 + 0] = coeff; + buf[i*3 + 1] = coeff >> 8; + buf[i*3 + 2] = coeff >> 16; +} + +void polyw_add(uint8_t buf[3*256], poly *p){ + unsigned int i; + for(i = 0; i < N; i++){ + polyw_add_idx(buf, p->coeffs[i], i); + } +} +void polyw_sub(poly* c, uint8_t buf[3*256], poly *a){ + int32_t coeff; + + + for(size_t i=0;icoeffs[i] = coeff - a->coeffs[i]; + } +} + +static int32_t highbits(int32_t a){ + int32_t a1; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + return a1; +} + +void poly_highbits(poly *a1, const poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a1->coeffs[i] = highbits(a->coeffs[i]); +} + +static int32_t lowbits(int32_t a){ + int32_t a1; + int32_t a0; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + a0 = a - a1*2*GAMMA2; + a0 -= (((Q-1)/2 - a0) >> 31) & Q; + return a0; +} + +void poly_lowbits(poly *a0, const poly *a){ + unsigned int i; + + for(i = 0; i < N; ++i) + a0->coeffs[i] = lowbits(a->coeffs[i]); +} + +void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx) { + small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + idx*POLYETA_PACKEDBYTES); +} +void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx) { + small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + L*POLYETA_PACKEDBYTES + idx*POLYETA_PACKEDBYTES); +} + + +// TODO: in the end increase this buffer size as far as possible +#define POLY_UNIFORM_BUFFERSIZE 3 +void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state){ + int32_t t; + uint8_t buf[POLY_UNIFORM_BUFFERSIZE*3]; + { + size_t ctr = 0; + stream128_init(state, seed, nonce); + + do { + shake128_inc_squeeze(buf, sizeof buf, state); + + for(size_t pos=0; pos < sizeof buf && ctr < N; pos += 3){ + t = buf[pos]; + t |= (uint32_t)buf[pos+1] << 8; + t |= (uint32_t)buf[pos+2] << 16; + t &= 0x7FFFFF; + + if(t < Q) { + t = montgomery_reduce((int64_t)t * b->coeffs[ctr]); + polyw_add_idx(wcomp, t, ctr); + ctr++; + } + } + } while(ctr < N); + + } +} + +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE 1 +#if GAMMA1 == (1 << 17) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*4) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*9) +#elif GAMMA1 == (1 << 19) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*2) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*5) +#endif + +static void polyz_unpack_inplace(int32_t *r){ + uint8_t *a = (uint8_t *)r; + + unsigned int i,j; + #if GAMMA1 == (1 << 17) + for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { + i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; + int32_t t0; + + + r[4*i+3] = a[9*i+6] >> 6; + r[4*i+3] |= (uint32_t)a[9*i+7] << 2; + r[4*i+3] |= (uint32_t)a[9*i+8] << 10; + r[4*i+3] &= 0x3FFFF; + + r[4*i+2] = a[9*i+4] >> 4; + r[4*i+2] |= (uint32_t)a[9*i+5] << 4; + r[4*i+2] |= (uint32_t)a[9*i+6] << 12; + r[4*i+2] &= 0x3FFFF; + + + r[4*i+1] = (uint32_t)a[9*i+4] << 14; + r[4*i+1] |= a[9*i+2] >> 2; + r[4*i+1] |= (uint32_t)a[9*i+3] << 6; + r[4*i+1] &= 0x3FFFF; + + t0 = a[9*i+0]; + t0 |= (uint32_t)a[9*i+1] << 8; + t0 |= (uint32_t)a[9*i+2] << 16; + t0 &= 0x3FFFF; + + r[4*i+0] = GAMMA1 - t0; + r[4*i+1] = GAMMA1 - r[4*i+1]; + r[4*i+2] = GAMMA1 - r[4*i+2]; + r[4*i+3] = GAMMA1 - r[4*i+3]; + + } +#elif GAMMA1 == (1 << 19) + for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { + i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; + int32_t tmp0, tmp1; + + tmp0 = a[5*i+2] >> 4; + tmp0 |= (uint32_t)a[5*i+3] << 4; + tmp0 |= (uint32_t)a[5*i+4] << 12; + tmp0 &= 0xFFFFF; + + tmp1 = a[5*i+0]; + tmp1 |= (uint32_t)a[5*i+1] << 8; + tmp1 |= (uint32_t)a[5*i+2] << 16; + tmp1 &= 0xFFFFF; + + r[2*i+0] = GAMMA1 - tmp1; + r[2*i+1] = GAMMA1 - tmp0; + } +#endif +} + +void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ + int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; + + stream256_init(state, seed, nonce); + for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ + shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); + polyz_unpack_inplace(buf); + + for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ + a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j]; + } + } +} + +void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ + int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; + + stream256_init(state, seed, nonce); + for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ + shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); + polyz_unpack_inplace(buf); + + for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ + a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j] + b->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j]; + } + } +} + + +static inline int32_t make_hint_stack(int32_t z, int32_t r){ + int32_t r1, v1; + + r1 = highbits(r); + v1 = highbits(r+z); + + if(r1 != v1) return 1; + return 0; +} + +size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]){ + int32_t coeff; + size_t hints_n = 0; + for(size_t i=0;icoeffs[i]; + + a->coeffs[i] = make_hint_stack(-t->coeffs[i], coeff); + if(a->coeffs[i] == 1){ + hints_n++; + } + } + return hints_n; +} + +void unpack_sk_stack(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + key[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + tr[i] = sk[i]; + sk += TRBYTES; +} + +/************************************************* +* Name: unpack_sig_h_indices +* +* Description: Unpack only h from signature sig = (c, z, h). +* +* Arguments: - polyveck *h: pointer to output hint vector h +* - const unsigned char sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]) { + sig += L * POLYZ_PACKEDBYTES; + sig += CTILDEBYTES; + /* Decode h */ + unsigned int k = 0; + unsigned int hidx = 0; + + if (idx > 0) + { + k = sig[OMEGA + (idx - 1)]; + } + + if (sig[OMEGA + idx] < k || sig[OMEGA + idx] > OMEGA) { + return 1; + } + + for (unsigned int j = k; j < sig[OMEGA + idx]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if (j > k && sig[j] <= sig[j - 1]) { + return 1; + } + h_i[hidx++] = sig[j]; + } + + *number_of_hints = hidx; + + /* TODO: extract this check, redundant here */ + k = sig[OMEGA + (K - 1)]; + /* Extra indices are zero for strong unforgeability */ + for (unsigned int j = k; j < OMEGA; ++j) { + if (sig[j]) { + return 1; + } + } + return 0; +} + +/************************************************* +* Name: poly_use_hint_stack +* +* Description: Use hint polynomial to correct the high bits of a polynomial. +* +* Arguments: - poly *b: pointer to output polynomial with corrected high bits +* - const poly *a: pointer to input polynomial +* - const poly *h: pointer to input hint polynomial +**************************************************/ +void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints) { + unsigned int i; + unsigned int in_list; + + for(i = 0; i < N; ++i) + { + in_list = 0; + for (size_t hidx = 0; hidx < number_of_hints; hidx++) + { + if (i == h_i[hidx]) + { + in_list = 1; + break; + } + } + if (in_list) + { + b->coeffs[i] = use_hint(a->coeffs[i], 1); + } + else + { + b->coeffs[i] = use_hint(a->coeffs[i], 0); + } + + } +} + +/************************************************* +* Name: pack_pk_rho +* +* Description: Bit-pack only rho in public key pk = (rho, t1). +* +* Arguments: - unsigned char pk[]: output byte array +* - const unsigned char rho[]: byte array containing rho +**************************************************/ +void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const unsigned char rho[SEEDBYTES]) { + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + pk[i] = rho[i]; + } +} + +/************************************************* +* Name: pack_pk_t1 +* +* Description: Bit-pack only the t1 elem at idx in public key pk = (rho, t1). +* +* Arguments: - unsigned char pk[]: output byte array +* - const polyveck *t1: pointer to vector t1 +* - const unsigned int idx: index to the elem to pack +**************************************************/ +void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const poly *t1, + const unsigned int idx) { + pk += SEEDBYTES; + polyt1_pack(pk + idx * POLYT1_PACKEDBYTES, t1); +} + +/************************************************* +* Name: pack_sk_s1 +* +* Description: Bit-pack only some element of s1 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *s1_elem: pointer to vector element idx in s1 +* - const unisgned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s1_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES; + polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s1_elem); +} + +/************************************************* +* Name: pack_sk_s2 +* +* Description: Bit-pack only some element of s2 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *s2_elem: pointer to vector element idx in s2 +* - const unsigned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s2_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES; + polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s2_elem); +} + +/************************************************* +* Name: pack_sk_t0 +* +* Description: Bit-pack only some element of t0 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *t0_elem: pointer to vector element idx in s2 +* - const unsigned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *t0_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES + K * POLYETA_PACKEDBYTES; + polyt0_pack(sk + idx * POLYT0_PACKEDBYTES, t0_elem); +} + +/************************************************* +* Name: pack_sk_rho +* +* Description: Bit-pack only rho in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char rho[]: byte array containing rho +**************************************************/ +void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char rho[SEEDBYTES]) { + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + sk[i] = rho[i]; + } +} + +/************************************************* +* Name: pack_sk_key +* +* Description: Bit-pack only key in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char key[]: byte array containing key +**************************************************/ +void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char key[SEEDBYTES]) { + sk += SEEDBYTES; + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + sk[i] = key[i]; + } +} + +/************************************************* +* Name: pack_sk_tr +* +* Description: Bit-pack only tr in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char tr[]: byte array containing tr +**************************************************/ +void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char tr[TRBYTES]) { + sk += 2*SEEDBYTES; + for (unsigned int i = 0; i < TRBYTES; ++i) { + sk[i] = tr[i]; + } +} + +/************************************************* +* Name: challenge +* +* Description: Implementation of H. Samples polynomial with TAU nonzero +* coefficients in {-1,1} using the output stream of +* SHAKE256(seed). Stack optimized. +* +* Arguments: - poly *c: pointer to output polynomial +* - const uint8_t mu[]: byte array containing seed of length SEEDBYTES +**************************************************/ +#define CHALLENGE_STACK_BUF_SIZE 8 +void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]) { + unsigned int i, b, pos; + uint64_t signs; + uint8_t buf[CHALLENGE_STACK_BUF_SIZE]; + shake256incctx state; + + shake256_inc_init(&state); + shake256_inc_absorb(&state, seed, SEEDBYTES); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); + signs = 0; + for(i = 0; i < 8; ++i) + { + signs |= (uint64_t)buf[i] << 8*i; + } + pos = 8; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + for(i = N-TAU; i < N; ++i) { + do { + if(pos >= CHALLENGE_STACK_BUF_SIZE) { + shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); + pos = 0; + } + + b = buf[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2*(signs & 1); + signs >>= 1; + } +} \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.h b/crypto_sign/dilithium3/m4fstack/stack.h new file mode 100644 index 00000000..06c8c576 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/stack.h @@ -0,0 +1,69 @@ +#ifndef STACK_H +#define STACK_H + +#include "poly.h" +#include "smallpoly.h" +#include +#include +#include "fips202.h" + +void poly_challenge_compress(uint8_t c[68], const poly *cp); +void poly_challenge_decompress(poly *cp, const uint8_t c[68]); + + +void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0); +void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1); +void polyw_pack(uint8_t buf[3*256], poly *w); +void polyw_unpack(poly *w, const uint8_t buf[3*256]); + +void polyw_add(uint8_t buf[3*256], poly *p); +void polyw_sub(poly* c, uint8_t buf[3*256], poly *a); + +void poly_highbits(poly *a1, const poly *a); +void poly_lowbits(poly *a0, const poly *a); + +void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx); +void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx); + +void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state); +void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); +void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); +void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]); + +size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]); +int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]); +void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints); + +void unpack_sk_stack(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const unsigned char rho[SEEDBYTES]); + +void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const poly *t1, + const unsigned int idx); + +void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s1_elem, + const unsigned int idx); + +void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s2_elem, + const unsigned int idx); + +void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *t0_elem, + const unsigned int idx); + +void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char rho[SEEDBYTES]); + +void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char key[SEEDBYTES]); + +void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char tr[TRBYTES]); +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c new file mode 100644 index 00000000..963f6498 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c @@ -0,0 +1,28 @@ +#include +#include "params.h" +#include "symmetric.h" +#include "fips202.h" + +void dilithium_shake128_stream_init(shake128incctx *state, const uint8_t seed[SEEDBYTES], uint16_t nonce) +{ + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake128_inc_init(state); + shake128_inc_absorb(state, seed, SEEDBYTES); + shake128_inc_absorb(state, t, 2); + shake128_inc_finalize(state); +} + +void dilithium_shake256_stream_init(shake256incctx *state, const uint8_t seed[CRHBYTES], uint16_t nonce) +{ + uint8_t t[2]; + t[0] = nonce; + t[1] = nonce >> 8; + + shake256_inc_init(state); + shake256_inc_absorb(state, seed, CRHBYTES); + shake256_inc_absorb(state, t, 2); + shake256_inc_finalize(state); +} diff --git a/crypto_sign/dilithium3/m4fstack/symmetric.h b/crypto_sign/dilithium3/m4fstack/symmetric.h new file mode 100644 index 00000000..47037377 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/symmetric.h @@ -0,0 +1,65 @@ +#ifndef SYMMETRIC_H +#define SYMMETRIC_H + +#include +#include "params.h" + +#ifdef DILITHIUM_USE_AES + +#include "aes256ctr.h" +#include "fips202.h" + +typedef aes256ctr_ctx stream128_state; +typedef aes256ctr_ctx stream256_state; + +#define dilithium_aes256ctr_init DILITHIUM_NAMESPACE(dilithium_aes256ctr_init) +void dilithium_aes256ctr_init(aes256ctr_ctx *state, + const uint8_t key[32], + uint16_t nonce); + +#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES +#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES + +#define stream128_init(STATE, SEED, NONCE) \ + dilithium_aes256ctr_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + dilithium_aes256ctr_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) + +#else + +#include "fips202.h" +typedef shake128incctx stream128_state; +typedef shake256incctx stream256_state; + +#define shake256_inc_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_inc_squeeze(OUT, OUTBLOCKS*SHAKE256_RATE, STATE) + +#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) +void dilithium_shake128_stream_init(stream128_state *state, + const uint8_t seed[SEEDBYTES], + uint16_t nonce); + +#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) +void dilithium_shake256_stream_init(stream256_state *state, + const uint8_t seed[CRHBYTES], + uint16_t nonce); + +#define STREAM128_BLOCKBYTES SHAKE128_RATE +#define STREAM256_BLOCKBYTES SHAKE256_RATE + +#define stream128_init(STATE, SEED, NONCE) \ + dilithium_shake128_stream_init(STATE, SEED, NONCE) +#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake128_inc_squeeze(OUT, OUTBLOCKS*SHAKE128_RATE, STATE) +#define stream256_init(STATE, SEED, NONCE) \ + dilithium_shake256_stream_init(STATE, SEED, NONCE) +#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ + shake256_inc_squeeze(OUT, OUTBLOCKS*SHAKE256_RATE, STATE) + +#endif + +#endif diff --git a/crypto_sign/dilithium3/m4fstack/vector.h b/crypto_sign/dilithium3/m4fstack/vector.h new file mode 100644 index 00000000..e5c5dda3 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/vector.h @@ -0,0 +1,20 @@ +#ifndef VECTOR_H +#define VECTOR_H + +#include +#include "params.h" + +#define asm_reduce32 DILITHIUM_NAMESPACE(asm_reduce32) +void asm_reduce32(int32_t a[N]); +#define small_asm_reduce32_central DILITHIUM_NAMESPACE(small_asm_reduce32_central) +void small_asm_reduce32_central(int32_t a[N]); +#define asm_caddq DILITHIUM_NAMESPACE(asm_caddq) +void asm_caddq(int32_t a[N]); +#define asm_freeze DILITHIUM_NAMESPACE(asm_freeze) +void asm_freeze(int32_t a[N]); +#define asm_rej_uniform DILITHIUM_NAMESPACE(asm_rej_uniform) +unsigned int asm_rej_uniform(int32_t *a, + unsigned int len, + const unsigned char *buf, + unsigned int buflen); +#endif diff --git a/crypto_sign/dilithium3/m4fstack/vector.s b/crypto_sign/dilithium3/m4fstack/vector.s new file mode 100644 index 00000000..559f11b0 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/vector.s @@ -0,0 +1,210 @@ +.syntax unified +.thumb +.macro redq a, tmp, q + add \tmp, \a, #4194304 + asrs \tmp, \tmp, #23 + mls \a, \tmp, \q, \a +.endm + +// void asm_reduce32(int32_t a[N]); +.global pqcrystals_dilithium_asm_reduce32 +.type pqcrystals_dilithium_asm_reduce32, %function +.align 2 +pqcrystals_dilithium_asm_reduce32: + push {r4-r10} + + movw r12,#:lower16:8380417 + movt r12,#:upper16:8380417 + movw r10, #32 + 1: + ldr.w r1, [r0] + ldr.w r2, [r0, #1*4] + ldr.w r3, [r0, #2*4] + ldr.w r4, [r0, #3*4] + ldr.w r5, [r0, #4*4] + ldr.w r6, [r0, #5*4] + ldr.w r7, [r0, #6*4] + ldr.w r8, [r0, #7*4] + + redq r1, r9, r12 + redq r2, r9, r12 + redq r3, r9, r12 + redq r4, r9, r12 + redq r5, r9, r12 + redq r6, r9, r12 + redq r7, r9, r12 + redq r8, r9, r12 + + str.w r2, [r0, #1*4] + str.w r3, [r0, #2*4] + str.w r4, [r0, #3*4] + str.w r5, [r0, #4*4] + str.w r6, [r0, #5*4] + str.w r7, [r0, #6*4] + str.w r8, [r0, #7*4] + str r1, [r0], #8*4 + subs r10, #1 + bne.w 1b + + pop {r4-r10} + bx lr +.size pqcrystals_dilithium_asm_reduce32, .-pqcrystals_dilithium_asm_reduce32 + +.macro barrett_32 a, Qbar, Q, tmp + smmulr.w \tmp, \a, \Qbar + mls.w \a, \tmp, \Q, \a +.endm + +// INPUT: target (signed), KYBER_Q (signed) +// OUTPUT: target adjusted to be between -KYBER_Q/2 and KYBER_Q/2 +.macro central_reduce target, Q + cmp \target, \Q, lsr #1 + it hi + subhi \target, \Q + cmn \target, \Q, lsr #1 + it lt + addlt \target, \Q +.endm + +// void asm_reduce32(int32_t a[N]); +.global pqcrystals_dilithium_small_asm_reduce32_central +.type pqcrystals_dilithium_small_asm_reduce32_central, %function +.align 2 +pqcrystals_dilithium_small_asm_reduce32_central: + push {r4-r12, lr} + + + movw r9, #:lower16:5585133 + movt r9, #:upper16:5585133 + mov.w r10,#769 + + movw r12, #32 + 1: + ldr.w r1, [r0] + ldr.w r2, [r0, #1*4] + ldr.w r3, [r0, #2*4] + ldr.w r4, [r0, #3*4] + ldr.w r5, [r0, #4*4] + ldr.w r6, [r0, #5*4] + ldr.w r7, [r0, #6*4] + ldr.w r8, [r0, #7*4] + + barrett_32 r1, r9, r10, r11 + barrett_32 r2, r9, r10, r11 + barrett_32 r3, r9, r10, r11 + barrett_32 r4, r9, r10, r11 + barrett_32 r5, r9, r10, r11 + barrett_32 r6, r9, r10, r11 + barrett_32 r7, r9, r10, r11 + barrett_32 r8, r9, r10, r11 + + + str.w r2, [r0, #1*4] + str.w r3, [r0, #2*4] + str.w r4, [r0, #3*4] + str.w r5, [r0, #4*4] + str.w r6, [r0, #5*4] + str.w r7, [r0, #6*4] + str.w r8, [r0, #7*4] + str r1, [r0], #8*4 + subs r12, #1 + bne.w 1b + + pop {r4-r12, pc} + +.size pqcrystals_dilithium_small_asm_reduce32_central, .-pqcrystals_dilithium_small_asm_reduce32_central + +.macro caddq a, tmp, q + and \tmp, \q, \a, asr #31 + add \a, \a, \tmp +.endm + +.macro freezeq a, tmp, q + redq \a, \tmp, \q + caddq \a, \tmp, \q +.endm + +// void asm_caddq(int32_t a[N]); +.global pqcrystals_dilithium_asm_caddq +.type pqcrystals_dilithium_asm_caddq, %function +.align 2 +pqcrystals_dilithium_asm_caddq: + push {r4-r10} + + movw r12,#:lower16:8380417 + movt r12,#:upper16:8380417 + + movw r10, #32 + 1: + ldr.w r1, [r0] + ldr.w r2, [r0, #1*4] + ldr.w r3, [r0, #2*4] + ldr.w r4, [r0, #3*4] + ldr.w r5, [r0, #4*4] + ldr.w r6, [r0, #5*4] + ldr.w r7, [r0, #6*4] + ldr.w r8, [r0, #7*4] + + caddq r1, r9, r12 + caddq r2, r9, r12 + caddq r3, r9, r12 + caddq r4, r9, r12 + caddq r5, r9, r12 + caddq r6, r9, r12 + caddq r7, r9, r12 + caddq r8, r9, r12 + + str.w r2, [r0, #1*4] + str.w r3, [r0, #2*4] + str.w r4, [r0, #3*4] + str.w r5, [r0, #4*4] + str.w r6, [r0, #5*4] + str.w r7, [r0, #6*4] + str.w r8, [r0, #7*4] + str r1, [r0], #8*4 + subs r10, #1 + bne.w 1b + + pop {r4-r10} + bx lr +.size pqcrystals_dilithium_asm_caddq, .-pqcrystals_dilithium_asm_caddq + + +// asm_rej_uniform(int32_t *a,unsigned int len,const unsigned char *buf, unsigned int buflen); +.global pqcrystals_dilithium_asm_rej_uniform +.type pqcrystals_dilithium_asm_rej_uniform, %function +.align 2 +pqcrystals_dilithium_asm_rej_uniform: + push.w {r4-r6} + push.w {r1} + // Store Q-1 in r12. + movw r12,#:lower16:8380416 + movt r12,#:upper16:8380416 + + add.w r6, r0, r1, lsl #2 + add.w r3, r2, r3 + sub.w r3, r3, #2 + +1: + // If there are less than 3 bytes available, return. + cmp.w r3, r2 + ble.w end + + ldr r5, [r2], #3 + ubfx r5, r5, #0, #23 + + cmp.n r5, r12 + it le + strle r5, [r0], #4 + + cmp.n r0, r6 + bne.n 1b + +end: + pop.w {r5} + + sub.w r0, r6, r0 + sub.w r0, r5, r0, lsr #2 + pop.w {r4-r6} + bx lr +.size pqcrystals_dilithium_asm_rej_uniform, .-pqcrystals_dilithium_asm_rej_uniform diff --git a/crypto_sign/dilithium5/m4fstack/api.h b/crypto_sign/dilithium5/m4fstack/api.h new file mode 120000 index 00000000..d29362d1 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/api.h @@ -0,0 +1 @@ +../m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/config.h b/crypto_sign/dilithium5/m4fstack/config.h new file mode 120000 index 00000000..f3892d90 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/config.h @@ -0,0 +1 @@ +../m4f/config.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros.i b/crypto_sign/dilithium5/m4fstack/macros.i new file mode 120000 index 00000000..d615b854 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/macros.i @@ -0,0 +1 @@ +../m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros_smallntt.i b/crypto_sign/dilithium5/m4fstack/macros_smallntt.i new file mode 120000 index 00000000..fc731f12 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/macros_smallntt.i @@ -0,0 +1 @@ +../../dilithium3/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.S b/crypto_sign/dilithium5/m4fstack/ntt.S new file mode 120000 index 00000000..40cd5d40 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/ntt.S @@ -0,0 +1 @@ +../m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.h b/crypto_sign/dilithium5/m4fstack/ntt.h new file mode 120000 index 00000000..8e99caeb --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/ntt.h @@ -0,0 +1 @@ +../m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.c b/crypto_sign/dilithium5/m4fstack/packing.c new file mode 120000 index 00000000..1052fe26 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/packing.c @@ -0,0 +1 @@ +../m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.h b/crypto_sign/dilithium5/m4fstack/packing.h new file mode 120000 index 00000000..643cc32a --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/packing.h @@ -0,0 +1 @@ +../m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/params.h b/crypto_sign/dilithium5/m4fstack/params.h new file mode 120000 index 00000000..1f91a364 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/params.h @@ -0,0 +1 @@ +../m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.h b/crypto_sign/dilithium5/m4fstack/pointwise_mont.h new file mode 120000 index 00000000..32558852 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/pointwise_mont.h @@ -0,0 +1 @@ +../m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.s b/crypto_sign/dilithium5/m4fstack/pointwise_mont.s new file mode 120000 index 00000000..3597ffdc --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/pointwise_mont.s @@ -0,0 +1 @@ +../m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.c b/crypto_sign/dilithium5/m4fstack/poly.c new file mode 120000 index 00000000..b5bdaa81 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/poly.c @@ -0,0 +1 @@ +../m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.h b/crypto_sign/dilithium5/m4fstack/poly.h new file mode 120000 index 00000000..bd94e469 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/poly.h @@ -0,0 +1 @@ +../m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.c b/crypto_sign/dilithium5/m4fstack/polyvec.c new file mode 120000 index 00000000..569a9a1b --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/polyvec.c @@ -0,0 +1 @@ +../m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.h b/crypto_sign/dilithium5/m4fstack/polyvec.h new file mode 120000 index 00000000..d02c99c3 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/polyvec.h @@ -0,0 +1 @@ +../m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/reduce.h b/crypto_sign/dilithium5/m4fstack/reduce.h new file mode 120000 index 00000000..45fbf228 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/reduce.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.c b/crypto_sign/dilithium5/m4fstack/rounding.c new file mode 120000 index 00000000..ec780689 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/rounding.c @@ -0,0 +1 @@ +../m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.h b/crypto_sign/dilithium5/m4fstack/rounding.h new file mode 120000 index 00000000..e64114bc --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/rounding.h @@ -0,0 +1 @@ +../m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.c b/crypto_sign/dilithium5/m4fstack/sign.c new file mode 120000 index 00000000..ae3b84fa --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/sign.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.h b/crypto_sign/dilithium5/m4fstack/sign.h new file mode 120000 index 00000000..551f979a --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/sign.h @@ -0,0 +1 @@ +../m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt.h b/crypto_sign/dilithium5/m4fstack/smallntt.h new file mode 120000 index 00000000..cfd626b9 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/smallntt.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt_769.S b/crypto_sign/dilithium5/m4fstack/smallntt_769.S new file mode 120000 index 00000000..6300683f --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/smallntt_769.S @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.c b/crypto_sign/dilithium5/m4fstack/smallpoly.c new file mode 120000 index 00000000..7dbf4992 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/smallpoly.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.h b/crypto_sign/dilithium5/m4fstack/smallpoly.h new file mode 120000 index 00000000..366391d9 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/smallpoly.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.c b/crypto_sign/dilithium5/m4fstack/stack.c new file mode 120000 index 00000000..c89dc5a0 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/stack.c @@ -0,0 +1 @@ +../../dilithium3/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.h b/crypto_sign/dilithium5/m4fstack/stack.h new file mode 120000 index 00000000..c9aed5d7 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/stack.h @@ -0,0 +1 @@ +../../dilithium3/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric-shake.c b/crypto_sign/dilithium5/m4fstack/symmetric-shake.c new file mode 120000 index 00000000..b95855bb --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/symmetric-shake.c @@ -0,0 +1 @@ +../m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric.h b/crypto_sign/dilithium5/m4fstack/symmetric.h new file mode 120000 index 00000000..e89ae955 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/symmetric.h @@ -0,0 +1 @@ +../m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.h b/crypto_sign/dilithium5/m4fstack/vector.h new file mode 120000 index 00000000..0793594b --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/vector.h @@ -0,0 +1 @@ +../m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.s b/crypto_sign/dilithium5/m4fstack/vector.s new file mode 120000 index 00000000..1a496055 --- /dev/null +++ b/crypto_sign/dilithium5/m4fstack/vector.s @@ -0,0 +1 @@ +../m4f/vector.s \ No newline at end of file diff --git a/skiplist.py b/skiplist.py index 47192e42..b97c1b84 100644 --- a/skiplist.py +++ b/skiplist.py @@ -237,4 +237,7 @@ {'scheme': 'tuov_is_pkc_skc', 'implementation': 'ref', 'estmemory': 1275904}, {'scheme': 'tuov_v_pkc', 'implementation': 'ref', 'estmemory': 7083008}, {'scheme': 'tuov_v_pkc_skc', 'implementation': 'ref', 'estmemory': 4639744}, + {'scheme': 'dilithium2', 'implementation': 'm4fstack', 'estmemory': 12288}, + {'scheme': 'dilithium5', 'implementation': 'm4fstack', 'estmemory': 21504}, + {'scheme': 'dilithium3', 'implementation': 'm4fstack', 'estmemory': 17408}, ] From 4584cfcef04e937c92ca6a923c9ea42e01d3122e Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 16 Apr 2024 09:24:06 +0800 Subject: [PATCH 090/107] Fix inlining of Kyber re-encryption (#339) * fix inlining of Kyber reencryption * update benchmarks --- benchmarks.csv | 55 +++++++++++++++-------------- benchmarks.md | 55 +++++++++++++++-------------- crypto_kem/kyber512/m4fspeed/poly.c | 5 ++- crypto_kem/kyber512/m4fstack/poly.c | 5 ++- crypto_kem/kyber768/m4fspeed/kem.c | 5 +-- crypto_kem/kyber768/m4fspeed/poly.c | 5 ++- crypto_kem/kyber768/m4fstack/poly.c | 5 ++- 7 files changed, 67 insertions(+), 68 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index e3bb1bbb..6064966e 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -8,12 +8,15 @@ bikel3 (10 executions),opt,248083316,248083286,248083345,16405238,16405236,16405 hqc-128 (10 executions),clean,52705201,52705180,52705224,105650897,105650877,105650927,159569179,159569176,159569183 hqc-192 (10 executions),clean,161458617,161458590,161458638,323146261,323146250,323146292,486156251,486156214,486156266 hqc-256 (10 executions),clean,295934078,295934057,295934104,591853870,591853850,591853898,891163005,891162988,891163038 -kyber1024 (10 executions),m4fspeed,1004995,1004386,1005713,1023370,1022780,1024086,1094273,1093643,1094989 -kyber1024 (10 executions),m4fstack,1011563,1007750,1019668,1035234,1031419,1043376,1106876,1103061,1114980 -kyber512 (10 executions),m4fspeed,387426,387191,387884,386486,386251,386942,427576,427342,428033 -kyber512 (10 executions),m4fstack,387995,386694,398090,389242,387941,399338,430376,429075,440473 -kyber768 (10 executions),m4fspeed,632049,631494,632680,651880,651323,652515,706301,705744,706936 -kyber768 (10 executions),m4fstack,635213,632659,643980,658865,656311,667633,713751,711197,722519 +kyber1024 (10 executions),clean,1540378,1537672,1549497,1707203,1704498,1716319,2019461,2016781,2028566 +kyber1024 (10 executions),m4fspeed,1007332,1004620,1027834,1025692,1023006,1046169,1088140,1085497,1108618 +kyber1024 (10 executions),m4fstack,1010439,1007447,1019916,1034164,1031168,1043640,1097375,1094378,1106850 +kyber512 (10 executions),clean,596231,595868,596646,696137,695809,696547,884186,883823,884599 +kyber512 (10 executions),m4fspeed,387168,386737,387669,386230,385800,386729,423509,423078,424010 +kyber512 (10 executions),m4fstack,386859,386551,387231,388111,387802,388486,425445,425136,425820 +kyber768 (10 executions),clean,990392,988002,998996,1134996,1132606,1143599,1384768,1382378,1393371 +kyber768 (10 executions),m4fspeed,631922,631406,632490,651769,651258,652364,700842,700331,701436 +kyber768 (10 executions),m4fstack,633057,632425,633410,656716,656088,657072,706247,705620,706604 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) aimer-l1-param1 (10 executions),ref,392943,392938,392977,32386301,32386203,32386424,31111672,31111588,31111782 @@ -156,14 +159,14 @@ hqc-128,clean,33644,51428,55892,,,,,, hqc-192,clean,65668,101636,110660,,,,,, hqc-256,clean,103756,161508,175972,,,,,, kyber1024,clean,15136,18784,20360,,,,,, -kyber1024,m4fspeed,6436,7500,9076,,,,,, -kyber1024,m4fstack,3332,3372,4948,,,,,, +kyber1024,m4fspeed,6436,7500,7484,,,,,, +kyber1024,m4fstack,3332,3372,3356,,,,,, kyber512,clean,6168,8800,9576,,,,,, -kyber512,m4fspeed,4364,5436,6212,,,,,, -kyber512,m4fstack,2292,2348,3124,,,,,, +kyber512,m4fspeed,4364,5436,5412,,,,,, +kyber512,m4fstack,2292,2348,2332,,,,,, kyber768,clean,10272,13408,14504,,,,,, -kyber768,m4fspeed,5396,6468,7564,,,,,, -kyber768,m4fstack,2820,2860,3956,,,,,, +kyber768,m4fspeed,5396,6468,6452,,,,,, +kyber768,m4fstack,2820,2860,2844,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, aimer-l1-param1,ref,10952,187724,196728,,,,,, @@ -308,15 +311,15 @@ bikel3,opt,0.0,6.3,0.2,,,,,, hqc-128,clean,0.4,0.8,0.5,,,,,, hqc-192,clean,0.3,0.5,0.3,,,,,, hqc-256,clean,0.2,0.4,0.3,,,,,, -kyber1024,clean,49.9,45.7,38.6,,,,,, -kyber1024,m4fspeed,76.1,75.9,71.0,,,,,, -kyber1024,m4fstack,75.8,75.2,70.4,,,,,, +kyber1024,clean,50.0,45.8,38.7,,,,,, +kyber1024,m4fspeed,76.0,75.8,71.5,,,,,, +kyber1024,m4fstack,75.9,75.3,71.0,,,,,, kyber512,clean,49.8,41.4,32.6,,,,,, -kyber512,m4fspeed,76.5,74.4,67.3,,,,,, -kyber512,m4fstack,76.6,74.0,67.0,,,,,, -kyber768,clean,48.4,43.2,35.4,,,,,, -kyber768,m4fspeed,75.4,74.9,69.1,,,,,, -kyber768,m4fstack,75.3,74.3,68.6,,,,,, +kyber512,m4fspeed,76.6,74.4,68.0,,,,,, +kyber512,m4fstack,76.6,74.0,67.6,,,,,, +kyber768,clean,48.4,43.3,35.5,,,,,, +kyber768,m4fspeed,75.4,74.9,69.6,,,,,, +kyber768,m4fstack,75.4,74.5,69.3,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, aimer-l1-param1,ref,72.0,47.2,46.7,,,,,, @@ -461,14 +464,14 @@ hqc-128,clean,18628,0,0,18628,,,,, hqc-192,clean,21104,0,0,21104,,,,, hqc-256,clean,26260,0,0,26260,,,,, kyber1024,clean,6296,0,0,6296,,,,, -kyber1024,m4fspeed,16928,0,0,16928,,,,, -kyber1024,m4fstack,14136,0,0,14136,,,,, +kyber1024,m4fspeed,16912,0,0,16912,,,,, +kyber1024,m4fstack,14120,0,0,14120,,,,, kyber512,clean,5164,0,0,5164,,,,, -kyber512,m4fspeed,15840,0,0,15840,,,,, -kyber512,m4fstack,13324,0,0,13324,,,,, +kyber512,m4fspeed,15824,0,0,15824,,,,, +kyber512,m4fstack,13308,0,0,13308,,,,, kyber768,clean,5168,0,0,5168,,,,, -kyber768,m4fspeed,16008,0,0,16008,,,,, -kyber768,m4fstack,13332,0,0,13332,,,,, +kyber768,m4fspeed,15992,0,0,15992,,,,, +kyber768,m4fstack,13316,0,0,13316,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, aimer-l1-param1,ref,19302,468,0,19770,,,,, diff --git a/benchmarks.md b/benchmarks.md index 5aef4137..ba34c3d9 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -9,12 +9,15 @@ | hqc-128 (10 executions) | clean | AVG: 52,705,201
MIN: 52,705,180
MAX: 52,705,224 | AVG: 105,650,897
MIN: 105,650,877
MAX: 105,650,927 | AVG: 159,569,179
MIN: 159,569,176
MAX: 159,569,183 | | hqc-192 (10 executions) | clean | AVG: 161,458,617
MIN: 161,458,590
MAX: 161,458,638 | AVG: 323,146,261
MIN: 323,146,250
MAX: 323,146,292 | AVG: 486,156,251
MIN: 486,156,214
MAX: 486,156,266 | | hqc-256 (10 executions) | clean | AVG: 295,934,078
MIN: 295,934,057
MAX: 295,934,104 | AVG: 591,853,870
MIN: 591,853,850
MAX: 591,853,898 | AVG: 891,163,005
MIN: 891,162,988
MAX: 891,163,038 | -| kyber1024 (10 executions) | m4fspeed | AVG: 1,004,995
MIN: 1,004,386
MAX: 1,005,713 | AVG: 1,023,370
MIN: 1,022,780
MAX: 1,024,086 | AVG: 1,094,273
MIN: 1,093,643
MAX: 1,094,989 | -| kyber1024 (10 executions) | m4fstack | AVG: 1,011,563
MIN: 1,007,750
MAX: 1,019,668 | AVG: 1,035,234
MIN: 1,031,419
MAX: 1,043,376 | AVG: 1,106,876
MIN: 1,103,061
MAX: 1,114,980 | -| kyber512 (10 executions) | m4fspeed | AVG: 387,426
MIN: 387,191
MAX: 387,884 | AVG: 386,486
MIN: 386,251
MAX: 386,942 | AVG: 427,576
MIN: 427,342
MAX: 428,033 | -| kyber512 (10 executions) | m4fstack | AVG: 387,995
MIN: 386,694
MAX: 398,090 | AVG: 389,242
MIN: 387,941
MAX: 399,338 | AVG: 430,376
MIN: 429,075
MAX: 440,473 | -| kyber768 (10 executions) | m4fspeed | AVG: 632,049
MIN: 631,494
MAX: 632,680 | AVG: 651,880
MIN: 651,323
MAX: 652,515 | AVG: 706,301
MIN: 705,744
MAX: 706,936 | -| kyber768 (10 executions) | m4fstack | AVG: 635,213
MIN: 632,659
MAX: 643,980 | AVG: 658,865
MIN: 656,311
MAX: 667,633 | AVG: 713,751
MIN: 711,197
MAX: 722,519 | +| kyber1024 (10 executions) | clean | AVG: 1,540,378
MIN: 1,537,672
MAX: 1,549,497 | AVG: 1,707,203
MIN: 1,704,498
MAX: 1,716,319 | AVG: 2,019,461
MIN: 2,016,781
MAX: 2,028,566 | +| kyber1024 (10 executions) | m4fspeed | AVG: 1,007,332
MIN: 1,004,620
MAX: 1,027,834 | AVG: 1,025,692
MIN: 1,023,006
MAX: 1,046,169 | AVG: 1,088,140
MIN: 1,085,497
MAX: 1,108,618 | +| kyber1024 (10 executions) | m4fstack | AVG: 1,010,439
MIN: 1,007,447
MAX: 1,019,916 | AVG: 1,034,164
MIN: 1,031,168
MAX: 1,043,640 | AVG: 1,097,375
MIN: 1,094,378
MAX: 1,106,850 | +| kyber512 (10 executions) | clean | AVG: 596,231
MIN: 595,868
MAX: 596,646 | AVG: 696,137
MIN: 695,809
MAX: 696,547 | AVG: 884,186
MIN: 883,823
MAX: 884,599 | +| kyber512 (10 executions) | m4fspeed | AVG: 387,168
MIN: 386,737
MAX: 387,669 | AVG: 386,230
MIN: 385,800
MAX: 386,729 | AVG: 423,509
MIN: 423,078
MAX: 424,010 | +| kyber512 (10 executions) | m4fstack | AVG: 386,859
MIN: 386,551
MAX: 387,231 | AVG: 388,111
MIN: 387,802
MAX: 388,486 | AVG: 425,445
MIN: 425,136
MAX: 425,820 | +| kyber768 (10 executions) | clean | AVG: 990,392
MIN: 988,002
MAX: 998,996 | AVG: 1,134,996
MIN: 1,132,606
MAX: 1,143,599 | AVG: 1,384,768
MIN: 1,382,378
MAX: 1,393,371 | +| kyber768 (10 executions) | m4fspeed | AVG: 631,922
MIN: 631,406
MAX: 632,490 | AVG: 651,769
MIN: 651,258
MAX: 652,364 | AVG: 700,842
MIN: 700,331
MAX: 701,436 | +| kyber768 (10 executions) | m4fstack | AVG: 633,057
MIN: 632,425
MAX: 633,410 | AVG: 656,716
MIN: 656,088
MAX: 657,072 | AVG: 706,247
MIN: 705,620
MAX: 706,604 | ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | @@ -159,14 +162,14 @@ | hqc-192 | clean | 65,668 | 101,636 | 110,660 | | hqc-256 | clean | 103,756 | 161,508 | 175,972 | | kyber1024 | clean | 15,136 | 18,784 | 20,360 | -| kyber1024 | m4fspeed | 6,436 | 7,500 | 9,076 | -| kyber1024 | m4fstack | 3,332 | 3,372 | 4,948 | +| kyber1024 | m4fspeed | 6,436 | 7,500 | 7,484 | +| kyber1024 | m4fstack | 3,332 | 3,372 | 3,356 | | kyber512 | clean | 6,168 | 8,800 | 9,576 | -| kyber512 | m4fspeed | 4,364 | 5,436 | 6,212 | -| kyber512 | m4fstack | 2,292 | 2,348 | 3,124 | +| kyber512 | m4fspeed | 4,364 | 5,436 | 5,412 | +| kyber512 | m4fstack | 2,292 | 2,348 | 2,332 | | kyber768 | clean | 10,272 | 13,408 | 14,504 | -| kyber768 | m4fspeed | 5,396 | 6,468 | 7,564 | -| kyber768 | m4fstack | 2,820 | 2,860 | 3,956 | +| kyber768 | m4fspeed | 5,396 | 6,468 | 6,452 | +| kyber768 | m4fstack | 2,820 | 2,860 | 2,844 | ## Signature Schemes | Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | | ------ | -------------- | ---------------------- | ------------ | -------------- | @@ -313,15 +316,15 @@ | hqc-128 | clean | 0.4% | 0.8% | 0.5% | | hqc-192 | clean | 0.3% | 0.5% | 0.3% | | hqc-256 | clean | 0.2% | 0.4% | 0.3% | -| kyber1024 | clean | 49.9% | 45.7% | 38.6% | -| kyber1024 | m4fspeed | 76.1% | 75.9% | 71.0% | -| kyber1024 | m4fstack | 75.8% | 75.2% | 70.4% | +| kyber1024 | clean | 50.0% | 45.8% | 38.7% | +| kyber1024 | m4fspeed | 76.0% | 75.8% | 71.5% | +| kyber1024 | m4fstack | 75.9% | 75.3% | 71.0% | | kyber512 | clean | 49.8% | 41.4% | 32.6% | -| kyber512 | m4fspeed | 76.5% | 74.4% | 67.3% | -| kyber512 | m4fstack | 76.6% | 74.0% | 67.0% | -| kyber768 | clean | 48.4% | 43.2% | 35.4% | -| kyber768 | m4fspeed | 75.4% | 74.9% | 69.1% | -| kyber768 | m4fstack | 75.3% | 74.3% | 68.6% | +| kyber512 | m4fspeed | 76.6% | 74.4% | 68.0% | +| kyber512 | m4fstack | 76.6% | 74.0% | 67.6% | +| kyber768 | clean | 48.4% | 43.3% | 35.5% | +| kyber768 | m4fspeed | 75.4% | 74.9% | 69.6% | +| kyber768 | m4fstack | 75.4% | 74.5% | 69.3% | ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | @@ -468,14 +471,14 @@ | hqc-192 | clean | 21,104 | 0 | 0 | 21,104 | | hqc-256 | clean | 26,260 | 0 | 0 | 26,260 | | kyber1024 | clean | 6,296 | 0 | 0 | 6,296 | -| kyber1024 | m4fspeed | 16,928 | 0 | 0 | 16,928 | -| kyber1024 | m4fstack | 14,136 | 0 | 0 | 14,136 | +| kyber1024 | m4fspeed | 16,912 | 0 | 0 | 16,912 | +| kyber1024 | m4fstack | 14,120 | 0 | 0 | 14,120 | | kyber512 | clean | 5,164 | 0 | 0 | 5,164 | -| kyber512 | m4fspeed | 15,840 | 0 | 0 | 15,840 | -| kyber512 | m4fstack | 13,324 | 0 | 0 | 13,324 | +| kyber512 | m4fspeed | 15,824 | 0 | 0 | 15,824 | +| kyber512 | m4fstack | 13,308 | 0 | 0 | 13,308 | | kyber768 | clean | 5,168 | 0 | 0 | 5,168 | -| kyber768 | m4fspeed | 16,008 | 0 | 0 | 16,008 | -| kyber768 | m4fstack | 13,332 | 0 | 0 | 13,332 | +| kyber768 | m4fspeed | 15,992 | 0 | 0 | 15,992 | +| kyber768 | m4fstack | 13,316 | 0 | 0 | 13,316 | ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | diff --git a/crypto_kem/kyber512/m4fspeed/poly.c b/crypto_kem/kyber512/m4fspeed/poly.c index f9d408b8..29861e69 100644 --- a/crypto_kem/kyber512/m4fspeed/poly.c +++ b/crypto_kem/kyber512/m4fspeed/poly.c @@ -237,7 +237,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for (i = 0; i < KYBER_N; i += 8) { + for(i=0;icoeffs[8*i+j]; @@ -256,8 +256,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[8*i+j]; diff --git a/crypto_kem/kyber512/m4fstack/poly.c b/crypto_kem/kyber512/m4fstack/poly.c index f42154ff..cc849592 100644 --- a/crypto_kem/kyber512/m4fstack/poly.c +++ b/crypto_kem/kyber512/m4fstack/poly.c @@ -237,7 +237,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for (i = 0; i < KYBER_N; i += 8) { + for(i=0;icoeffs[8*i+j]; @@ -256,8 +256,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[8*i+j]; diff --git a/crypto_kem/kyber768/m4fspeed/kem.c b/crypto_kem/kyber768/m4fspeed/kem.c index 7e6474e2..5cfa62bc 100644 --- a/crypto_kem/kyber768/m4fspeed/kem.c +++ b/crypto_kem/kyber768/m4fspeed/kem.c @@ -138,7 +138,6 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch uint8_t buf[2 * KYBER_SYMBYTES]; /* Will contain key, coins */ uint8_t kr[2 * KYBER_SYMBYTES]; - uint8_t cmp[KYBER_CIPHERTEXTBYTES + KYBER_SYMBYTES]; const uint8_t *pk = sk + KYBER_INDCPA_SECRETKEYBYTES; indcpa_dec(buf, ct, sk); @@ -148,9 +147,7 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch hash_g(kr, buf, 2 * KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */ - indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); - - fail = verify(ct, cmp, KYBER_CIPHERTEXTBYTES); + fail = indcpa_enc_cmp(ct, buf, pk, kr + KYBER_SYMBYTES); /* Compute rejection key */ rkprf(ss, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, ct); diff --git a/crypto_kem/kyber768/m4fspeed/poly.c b/crypto_kem/kyber768/m4fspeed/poly.c index 9864534a..f73f1acd 100644 --- a/crypto_kem/kyber768/m4fspeed/poly.c +++ b/crypto_kem/kyber768/m4fspeed/poly.c @@ -237,7 +237,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for (i = 0; i < KYBER_N; i += 8) { + for(i=0;icoeffs[8*i+j]; @@ -256,8 +256,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[8*i+j]; diff --git a/crypto_kem/kyber768/m4fstack/poly.c b/crypto_kem/kyber768/m4fstack/poly.c index 91fab840..29b959f7 100644 --- a/crypto_kem/kyber768/m4fstack/poly.c +++ b/crypto_kem/kyber768/m4fstack/poly.c @@ -237,7 +237,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { int i, j, k = 0; #if (KYBER_POLYCOMPRESSEDBYTES == 128) - for (i = 0; i < KYBER_N; i += 8) { + for(i=0;icoeffs[8*i+j]; @@ -256,8 +256,7 @@ int cmp_poly_compress(const unsigned char *r, poly *a) { k += 4; } #elif (KYBER_POLYCOMPRESSEDBYTES == 160) - for(i=0;icoeffs[8*i+j]; From 006a1098d2a4a117f10a026c711658c39b102fdd Mon Sep 17 00:00:00 2001 From: Amin Abdulrahman Date: Mon, 22 Apr 2024 06:56:30 +0200 Subject: [PATCH 091/107] Symlinks for dilithium m4fstack (#342) --- .../dilithium2/m4fstack/macros_smallntt.i | 92 +- crypto_sign/dilithium2/m4fstack/reduce.h | 80 +- crypto_sign/dilithium2/m4fstack/sign.c | 485 +++++++++- crypto_sign/dilithium2/m4fstack/smallntt.h | 48 +- .../dilithium2/m4fstack/smallntt_769.S | 692 +++++++++++++- crypto_sign/dilithium2/m4fstack/smallpoly.c | 84 +- crypto_sign/dilithium2/m4fstack/smallpoly.h | 28 +- crypto_sign/dilithium2/m4fstack/stack.c | 716 ++++++++++++++- crypto_sign/dilithium2/m4fstack/stack.h | 70 +- crypto_sign/dilithium3/m4fstack/api.h | 27 +- crypto_sign/dilithium3/m4fstack/config.h | 8 +- crypto_sign/dilithium3/m4fstack/macros.i | 192 +--- .../dilithium3/m4fstack/macros_smallntt.i | 92 +- crypto_sign/dilithium3/m4fstack/ntt.S | 403 +-------- crypto_sign/dilithium3/m4fstack/ntt.h | 14 +- crypto_sign/dilithium3/m4fstack/packing.c | 287 +----- crypto_sign/dilithium3/m4fstack/packing.h | 56 +- crypto_sign/dilithium3/m4fstack/params.h | 84 +- .../dilithium3/m4fstack/pointwise_mont.h | 14 +- .../dilithium3/m4fstack/pointwise_mont.s | 129 +-- crypto_sign/dilithium3/m4fstack/poly.c | 852 +----------------- crypto_sign/dilithium3/m4fstack/poly.h | 83 +- crypto_sign/dilithium3/m4fstack/polyvec.c | 430 +-------- crypto_sign/dilithium3/m4fstack/polyvec.h | 100 +- crypto_sign/dilithium3/m4fstack/reduce.h | 80 +- crypto_sign/dilithium3/m4fstack/rounding.c | 103 +-- crypto_sign/dilithium3/m4fstack/rounding.h | 20 +- crypto_sign/dilithium3/m4fstack/sign.c | 485 +--------- crypto_sign/dilithium3/m4fstack/sign.h | 38 +- crypto_sign/dilithium3/m4fstack/smallntt.h | 48 +- .../dilithium3/m4fstack/smallntt_769.S | 692 +------------- crypto_sign/dilithium3/m4fstack/smallpoly.c | 84 +- crypto_sign/dilithium3/m4fstack/smallpoly.h | 28 +- crypto_sign/dilithium3/m4fstack/stack.c | 716 +-------------- crypto_sign/dilithium3/m4fstack/stack.h | 70 +- .../dilithium3/m4fstack/symmetric-shake.c | 29 +- crypto_sign/dilithium3/m4fstack/symmetric.h | 66 +- crypto_sign/dilithium3/m4fstack/vector.h | 21 +- crypto_sign/dilithium3/m4fstack/vector.s | 211 +---- crypto_sign/dilithium5/m4fstack/api.h | 2 +- crypto_sign/dilithium5/m4fstack/macros.i | 2 +- .../dilithium5/m4fstack/macros_smallntt.i | 2 +- crypto_sign/dilithium5/m4fstack/ntt.S | 2 +- crypto_sign/dilithium5/m4fstack/ntt.h | 2 +- crypto_sign/dilithium5/m4fstack/packing.c | 2 +- crypto_sign/dilithium5/m4fstack/packing.h | 2 +- crypto_sign/dilithium5/m4fstack/params.h | 2 +- .../dilithium5/m4fstack/pointwise_mont.h | 2 +- .../dilithium5/m4fstack/pointwise_mont.s | 2 +- crypto_sign/dilithium5/m4fstack/poly.c | 2 +- crypto_sign/dilithium5/m4fstack/poly.h | 2 +- crypto_sign/dilithium5/m4fstack/polyvec.c | 2 +- crypto_sign/dilithium5/m4fstack/polyvec.h | 2 +- crypto_sign/dilithium5/m4fstack/reduce.h | 2 +- crypto_sign/dilithium5/m4fstack/rounding.c | 2 +- crypto_sign/dilithium5/m4fstack/rounding.h | 2 +- crypto_sign/dilithium5/m4fstack/sign.c | 2 +- crypto_sign/dilithium5/m4fstack/sign.h | 2 +- crypto_sign/dilithium5/m4fstack/smallntt.h | 2 +- .../dilithium5/m4fstack/smallntt_769.S | 2 +- crypto_sign/dilithium5/m4fstack/smallpoly.c | 2 +- crypto_sign/dilithium5/m4fstack/smallpoly.h | 2 +- crypto_sign/dilithium5/m4fstack/stack.c | 2 +- crypto_sign/dilithium5/m4fstack/stack.h | 2 +- .../dilithium5/m4fstack/symmetric-shake.c | 2 +- crypto_sign/dilithium5/m4fstack/symmetric.h | 2 +- crypto_sign/dilithium5/m4fstack/vector.h | 2 +- crypto_sign/dilithium5/m4fstack/vector.s | 2 +- 68 files changed, 2345 insertions(+), 5470 deletions(-) mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/macros_smallntt.i mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/reduce.h mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/sign.c mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/smallntt.h mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/smallntt_769.S mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/smallpoly.c mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/smallpoly.h mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/stack.c mode change 120000 => 100644 crypto_sign/dilithium2/m4fstack/stack.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/api.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/config.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/macros.i mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/macros_smallntt.i mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/ntt.S mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/ntt.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/packing.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/packing.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/params.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/pointwise_mont.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/pointwise_mont.s mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/poly.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/poly.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/polyvec.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/polyvec.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/reduce.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/rounding.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/rounding.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/sign.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/sign.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/smallntt.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/smallntt_769.S mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/smallpoly.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/smallpoly.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/stack.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/stack.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/symmetric-shake.c mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/symmetric.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/vector.h mode change 100644 => 120000 crypto_sign/dilithium3/m4fstack/vector.s diff --git a/crypto_sign/dilithium2/m4fstack/macros_smallntt.i b/crypto_sign/dilithium2/m4fstack/macros_smallntt.i deleted file mode 120000 index fc731f12..00000000 --- a/crypto_sign/dilithium2/m4fstack/macros_smallntt.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/macros_smallntt.i b/crypto_sign/dilithium2/m4fstack/macros_smallntt.i new file mode 100644 index 00000000..7c9a387c --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/macros_smallntt.i @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NTT and inverse NTT code from: + * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. + * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. + * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. + * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S +*/ + +#ifndef MACROS_SMALLNTT_I +#define MACROS_SMALLNTT_I + +// general macros +.macro load a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + ldr.w \a0, [\a, \mem0] + ldr.w \a1, [\a, \mem1] + ldr.w \a2, [\a, \mem2] + ldr.w \a3, [\a, \mem3] +.endm + +.macro store a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 + str.w \a0, [\a, \mem0] + str.w \a1, [\a, \mem1] + str.w \a2, [\a, \mem2] + str.w \a3, [\a, \mem3] +.endm + +.macro doubleplant a, tmp, q, qa, plantconst + smulwb \tmp, \plantconst, \a + smulwt \a, \plantconst, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebarrett a, tmp, tmp2, q, barrettconst + smulbb \tmp, \a, \barrettconst + smultb \tmp2, \a, \barrettconst + asr \tmp, \tmp, #26 + asr \tmp2, \tmp2, #26 + smulbb \tmp, \tmp, \q + smulbb \tmp2, \tmp2, \q + pkhbt \tmp, \tmp, \tmp2, lsl#16 + usub16 \a, \a, \tmp +.endm + +// q locate in the top half of the register +.macro plant_red q, qa, qinv, tmp + mul \tmp, \tmp, \qinv + //tmp*qinv mod 2^2n/ 2^n; in high half + smlatt \tmp, \tmp, \q, \qa + // result in high half +.endm + +.macro mul_twiddle_plant a, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a + smulwt \a, \twiddle, \a + smlabt \tmp, \tmp, \q, \qa + smlabt \a, \a, \q, \qa + pkhtb \a, \a, \tmp, asr#16 +.endm + +.macro doublebutterfly_plant a0, a1, twiddle, tmp, q, qa + smulwb \tmp, \twiddle, \a1 + smulwt \a1, \twiddle, \a1 + smlabt \tmp, \tmp, \q, \qa + smlabt \a1, \a1, \q, \qa + pkhtb \tmp, \a1, \tmp, asr#16 + usub16 \a1, \a0, \tmp + uadd16 \a0, \a0, \tmp +.endm + +.macro two_doublebutterfly_plant a0, a1, a2, a3, twiddle0, twiddle1, tmp, q, qa + doublebutterfly_plant \a0, \a1, \twiddle0, \tmp, \q, \qa + doublebutterfly_plant \a2, \a3, \twiddle1, \tmp, \q, \qa +.endm + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/reduce.h b/crypto_sign/dilithium2/m4fstack/reduce.h deleted file mode 120000 index 45fbf228..00000000 --- a/crypto_sign/dilithium2/m4fstack/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/reduce.h b/crypto_sign/dilithium2/m4fstack/reduce.h new file mode 100644 index 00000000..5990918a --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/reduce.h @@ -0,0 +1,79 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include +#include "params.h" + +#define MONT -4186625 // 2^32 % Q +#define QINV 58728449 // q^(-1) mod 2^32 + +#define montgomery_reduce DILITHIUM_NAMESPACE(montgomery_reduce) +/************************************************* +* Name: montgomery_reduce +* +* Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, +* compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. +* +* Arguments: - int64_t: finite field element a +* +* Returns r. +**************************************************/ +static inline int32_t montgomery_reduce(int64_t a) { + int32_t t; + + t = (int64_t)(int32_t)a*QINV; + t = (a - (int64_t)t*Q) >> 32; + return t; +} + +/************************************************* +* Name: reduce32 +* +* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, +* compute r \equiv a (mod Q) such that -6283009 <= r <= 6283007. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t reduce32(int32_t a) { + int32_t t; + + t = (a + (1 << 22)) >> 23; + t = a - t*Q; + return t; +} + +/************************************************* +* Name: caddq +* +* Description: Add Q if input coefficient is negative. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t caddq(int32_t a) { + a += (a >> 31) & Q; + return a; +} + +/************************************************* +* Name: freeze +* +* Description: For finite field element a, compute standard +* representative r = a mod^+ Q. +* +* Arguments: - int32_t: finite field element a +* +* Returns r. +**************************************************/ +static int32_t freeze(int32_t a) { + a = reduce32(a); + a = caddq(a); + return a; +} + + + +#endif diff --git a/crypto_sign/dilithium2/m4fstack/sign.c b/crypto_sign/dilithium2/m4fstack/sign.c deleted file mode 120000 index ae3b84fa..00000000 --- a/crypto_sign/dilithium2/m4fstack/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/sign.c b/crypto_sign/dilithium2/m4fstack/sign.c new file mode 100644 index 00000000..71cff9bb --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/sign.c @@ -0,0 +1,484 @@ +#include +#include "params.h" +#include "sign.h" +#include "packing.h" +#include "polyvec.h" +#include "poly.h" +#include "randombytes.h" +#include "symmetric.h" +#include "smallpoly.h" +#include "stack.h" + +#include "smallntt.h" + +/************************************************* +* Name: crypto_sign_keypair +* +* Description: Generates public and private key. +* +* Arguments: - uint8_t *pk: pointer to output public key (allocated +* array of CRYPTO_PUBLICKEYBYTES bytes) +* - uint8_t *sk: pointer to output private key (allocated +* array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { + unsigned int i, j; + uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; + const uint8_t *rho, *rhoprime, *key; + + poly tA, tB; + + union { + uint8_t tr[TRBYTES]; + shake256incctx s256; + poly tC; + } data; + + shake256incctx *s256 = &data.s256; + uint8_t *tr = &data.tr; + poly *tC = &data.tC; + + /* Get randomness for rho, rhoprime and key */ + randombytes(seedbuf, SEEDBYTES); + shake256_inc_init(s256); + shake256_inc_absorb(s256, seedbuf, SEEDBYTES); + shake256_inc_finalize(s256); + shake256_inc_squeeze(seedbuf, 2*SEEDBYTES + CRHBYTES, s256); + + rho = seedbuf; + rhoprime = rho + SEEDBYTES; + key = rhoprime + CRHBYTES; + + pack_sk_rho(sk, rho); + pack_sk_key(sk, key); + pack_pk_rho(pk, rho); + + /* Matrix-vector multiplication */ + for (i = 0; i < K; i++) + { + /* Expand part of s1 */ + poly_uniform_eta(tC, rhoprime, 0); + if (i == 0) + { + pack_sk_s1(sk, tC, 0); + } + poly_ntt(tC); + /* expand part of the matrix */ + poly_uniform(&tB, rho, (i << 8) + 0); + /* partial matrix-vector multiplication */ + poly_pointwise_montgomery(&tA, &tB, tC); + for(j = 1; j < L; j++) + { + /* Expand part of s1 */ + poly_uniform_eta(tC, rhoprime, j); + if (i == 0) + { + pack_sk_s1(sk, tC, j); + } + poly_ntt(tC); + poly_uniform(&tB, rho, (i << 8) + j); + poly_pointwise_acc_montgomery(&tA, &tB, tC); + } + + poly_reduce(&tA); + poly_invntt_tomont(&tA); + + /* Add error vector s2 */ + /* Sample short vector s2 */ + poly_uniform_eta(&tB, rhoprime, L + i); + pack_sk_s2(sk, &tB, i); + poly_add(&tA, &tA, &tB); + + /* Compute t{0,1} */ + poly_caddq(&tA); + poly_power2round(tC, &tB, &tA); + pack_sk_t0(sk, &tB, i); + pack_pk_t1(pk, tC, i); + + } + + /* Compute H(rho, t1) and write secret key */ + shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); + pack_sk_tr(sk, tr); + + return 0; +} + + +/************************************************* +* Name: crypto_sign_signature +* +* Description: Computes signature. +* +* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) +* - size_t *siglen: pointer to output length of signature +* - uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign_signature(uint8_t *sig, + size_t *siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *sk) +{ + uint8_t buf[2 * CRHBYTES]; + uint8_t *mu, *rhoprime, *rnd; + const uint8_t *rho, *tr, *key; + uint16_t nonce = 0; + unsigned int n; + uint8_t wcomp[K][768]; + uint8_t ccomp[68]; + + union { + shake128incctx s128; + shake256incctx s256; + } state; + + union { + poly full; + struct { + smallpoly stmp0; + smallpoly stmp1; + } small; + } polybuffer; + + poly *tmp0 = &polybuffer.full; + smallpoly *stmp0 = &polybuffer.small.stmp0; + smallpoly *scp = &polybuffer.small.stmp1; + + rho = sk; + tr = sk + SEEDBYTES*2; + key = sk + SEEDBYTES; + + mu = buf; + rnd = mu + CRHBYTES; + rhoprime = mu + CRHBYTES; + unpack_sk_stack(rho, tr, key, sk); + + /* Compute mu = CRH(tr, msg) */ + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, tr, TRBYTES); + shake256_inc_absorb(&state.s256, m, mlen); + shake256_inc_finalize(&state.s256); + shake256_inc_squeeze(mu, CRHBYTES, &state.s256); + + // Note: RNDBYTES < CRHBYTES, so buffer has proper size + for (n = 0; n < RNDBYTES; n++) { + rnd[n] = 0; + } + + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, key, SEEDBYTES); + shake256_inc_absorb(&state.s256, rnd, RNDBYTES); + shake256_inc_absorb(&state.s256, mu, CRHBYTES); + shake256_inc_finalize(&state.s256); + // rnd can be overwritten here + shake256_inc_squeeze(rhoprime, CRHBYTES, &state.s256); + +rej: + for (size_t k_idx = 0; k_idx < K; k_idx++) { + for(size_t i=0;i<768;i++){ + wcomp[k_idx][i] = 0; + } + } + + for (size_t l_idx = 0; l_idx < L; l_idx++) { + /* Sample intermediate vector y */ + poly_uniform_gamma1_stack(tmp0, rhoprime, L*nonce + l_idx, &state.s256); + poly_ntt(tmp0); + + /* Matrix-vector multiplication */ + for (size_t k_idx = 0; k_idx < K; k_idx++) { + // sampling of y and packing into wcomp inlined into the basemul + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp[k_idx], tmp0, rho, (k_idx << 8) + l_idx, &state.s128); + } + } + nonce++; + for (size_t k_idx = 0; k_idx < K; k_idx++) { + polyw_unpack(tmp0, wcomp[k_idx]); + poly_invntt_tomont(tmp0); + poly_caddq(tmp0); + + polyw_pack(wcomp[k_idx], tmp0); + poly_highbits(tmp0, tmp0); + polyw1_pack(&sig[k_idx*POLYW1_PACKEDBYTES], tmp0); + } + + shake256_inc_init(&state.s256); + shake256_inc_absorb(&state.s256, mu, CRHBYTES); + shake256_inc_absorb(&state.s256, sig, K*POLYW1_PACKEDBYTES); + shake256_inc_finalize(&state.s256); + shake256_inc_squeeze(sig, CTILDEBYTES, &state.s256); + poly_challenge(tmp0, sig); + + poly_challenge_compress(ccomp, tmp0); + + /* Compute z, reject if it reveals secret */ + for(size_t l_idx=0;l_idx < L; l_idx++){ + if(l_idx != 0){ + poly_challenge_decompress(tmp0, ccomp); + } + poly_small_ntt_copy(scp, tmp0); + unpack_sk_s1(stmp0, sk, l_idx); + small_ntt(stmp0->coeffs); + poly_small_basemul_invntt(tmp0, scp, stmp0); + + poly_uniform_gamma1_add_stack(tmp0, tmp0, rhoprime, L*(nonce-1) + l_idx, &state.s256); + + poly_reduce(tmp0); + + if(poly_chknorm(tmp0, GAMMA1 - BETA)) + goto rej; + + polyz_pack(sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES, tmp0); + } + + + /* Write signature */ + unsigned int hint_n = 0; + unsigned int hints_written = 0; + /* Check that subtracting cs2 does not change high bits of w and low bits + * do not reveal secret information */ + + for(unsigned int k_idx = 0; k_idx < K; ++k_idx) { + poly_challenge_decompress(tmp0, ccomp); + poly_small_ntt_copy(scp, tmp0); + + unpack_sk_s2(stmp0, sk, k_idx); + small_ntt(stmp0->coeffs); + poly_small_basemul_invntt(tmp0, scp, stmp0); + + polyw_sub(tmp0, wcomp[k_idx], tmp0); + poly_reduce(tmp0); + + polyw_pack(wcomp[k_idx], tmp0); + + poly_lowbits(tmp0, tmp0); + poly_reduce(tmp0); + if(poly_chknorm(tmp0, GAMMA2 - BETA)){ + goto rej; + } + + poly_schoolbook(tmp0, ccomp, sk + SEEDBYTES + TRBYTES + SEEDBYTES + + L*POLYETA_PACKEDBYTES + K*POLYETA_PACKEDBYTES + k_idx*POLYT0_PACKEDBYTES); + + /* Compute hints for w1 */ + + if(poly_chknorm(tmp0, GAMMA2)) { + goto rej; + } + + hint_n += poly_make_hint_stack(tmp0, tmp0, wcomp[k_idx]); + + if (hint_n > OMEGA) { + goto rej; + } + pack_sig_h(sig, tmp0, k_idx, &hints_written); + } + pack_sig_h_zero(sig, &hints_written); + *siglen = CRYPTO_BYTES; + return 0; +} + +/************************************************* +* Name: crypto_sign +* +* Description: Compute signed message. +* +* Arguments: - uint8_t *sm: pointer to output signed message (allocated +* array with CRYPTO_BYTES + mlen bytes), +* can be equal to m +* - size_t *smlen: pointer to output length of signed +* message +* - const uint8_t *m: pointer to message to be signed +* - size_t mlen: length of message +* - const uint8_t *sk: pointer to bit-packed secret key +* +* Returns 0 (success) +**************************************************/ +int crypto_sign(uint8_t *sm, + size_t *smlen, + const uint8_t *m, + size_t mlen, + const uint8_t *sk) +{ + size_t i; + + for(i = 0; i < mlen; ++i) + sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; + crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + *smlen += mlen; + return 0; +} + +/************************************************* +* Name: crypto_sign_verify +* +* Description: Verifies signature. +* +* Arguments: - uint8_t *m: pointer to input signature +* - size_t siglen: length of signature +* - const uint8_t *m: pointer to message +* - size_t mlen: length of message +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signature could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_verify(const uint8_t *sig, + size_t siglen, + const uint8_t *m, + size_t mlen, + const uint8_t *pk) +{ + unsigned int i; + + poly p; + + union { + uint8_t w1_packed[POLYW1_PACKEDBYTES]; + uint8_t wcomp[768]; + } w1_packed_comp; + uint8_t *w1_packed = &w1_packed_comp.w1_packed; + uint8_t *wcomp = &w1_packed_comp.wcomp; + + union { + uint8_t ccomp[68]; + uint8_t mu[CRHBYTES]; + } ccomp_mu; + uint8_t *ccomp = &ccomp_mu.ccomp; + uint8_t *mu = &ccomp_mu.mu; + + shake256incctx s256; + + union { + uint8_t hint_ones[OMEGA]; + shake128incctx s128; + uint8_t c2[CTILDEBYTES]; + } shake_hint; + + uint8_t *hint_ones = &shake_hint.hint_ones; + shake128incctx *s128 = &shake_hint.s128; + uint8_t *c2 = &shake_hint.c2; + + if(siglen != CRYPTO_BYTES) + return -1; + + /* Compute CRH(h(rho, t1), msg) */ + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, pk, CRYPTO_PUBLICKEYBYTES); + shake256_inc_finalize(&s256); + shake256_inc_squeeze(mu, CRHBYTES, &s256); + + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, mu, TRBYTES); + shake256_inc_absorb(&s256, m, mlen); + shake256_inc_finalize(&s256); + shake256_inc_squeeze(mu, CRHBYTES, &s256); + + shake256_inc_init(&s256); + shake256_inc_absorb(&s256, mu, CRHBYTES); + + /* Matrix-vector multiplication; compute Az - c2^dt1 */ + poly_challenge_stack(&p, sig); + poly_challenge_compress(ccomp, &p); + + for (size_t k_idx = 0; k_idx < K; k_idx++) { + for(size_t widx=0;widx<768;widx++){ + wcomp[widx] = 0; + } + + polyz_unpack(&p, sig + CTILDEBYTES); + if(poly_chknorm(&p, GAMMA1 - BETA)) + return -1; + poly_ntt(&p); + + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + 0, s128); + + for (size_t l_idx = 1; l_idx < L; l_idx++) { + polyz_unpack(&p, sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES); + if(poly_chknorm(&p, GAMMA1 - BETA)) + return -1; + poly_ntt(&p); + poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + l_idx, s128); + } + polyw_unpack(&p, wcomp); + poly_reduce(&p); + poly_invntt_tomont(&p); + polyw_pack(wcomp, &p); + + poly_schoolbook_t1(&p, ccomp, pk + SEEDBYTES + k_idx*POLYT1_PACKEDBYTES); + + polyw_sub(&p, wcomp, &p); + poly_reduce(&p); + + /* Reconstruct w1 */ + poly_caddq(&p); + + if (unpack_sig_h_indices(hint_ones, &i, k_idx, sig) != 0) + { + return -1; + } + poly_use_hint_stack(&p, &p, hint_ones, i); + + polyw1_pack(w1_packed, &p); + + shake256_inc_absorb(&s256, w1_packed, POLYW1_PACKEDBYTES); + } + /* Call random oracle and verify challenge */ + shake256_inc_finalize(&s256); + shake256_inc_squeeze(c2, CTILDEBYTES, &s256); + for(i = 0; i < CTILDEBYTES; ++i) + if(sig[i] != c2[i]) + return -1; + + return 0; +} + +/************************************************* +* Name: crypto_sign_open +* +* Description: Verify signed message. +* +* Arguments: - uint8_t *m: pointer to output message (allocated +* array with smlen bytes), can be equal to sm +* - size_t *mlen: pointer to output length of message +* - const uint8_t *sm: pointer to signed message +* - size_t smlen: length of signed message +* - const uint8_t *pk: pointer to bit-packed public key +* +* Returns 0 if signed message could be verified correctly and -1 otherwise +**************************************************/ +int crypto_sign_open(uint8_t *m, + size_t *mlen, + const uint8_t *sm, + size_t smlen, + const uint8_t *pk) +{ + size_t i; + + if(smlen < CRYPTO_BYTES) + goto badsig; + + *mlen = smlen - CRYPTO_BYTES; + if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + goto badsig; + else { + /* All good, copy msg, return 0 */ + for(i = 0; i < *mlen; ++i) + m[i] = sm[CRYPTO_BYTES + i]; + return 0; + } + +badsig: + /* Signature verification failed */ + *mlen = -1; + for(i = 0; i < smlen; ++i) + m[i] = 0; + + return -1; +} diff --git a/crypto_sign/dilithium2/m4fstack/smallntt.h b/crypto_sign/dilithium2/m4fstack/smallntt.h deleted file mode 120000 index cfd626b9..00000000 --- a/crypto_sign/dilithium2/m4fstack/smallntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallntt.h b/crypto_sign/dilithium2/m4fstack/smallntt.h new file mode 100644 index 00000000..244fad24 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallntt.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMALLNTT_H +#define SMALLNTT_H + +#include +#include "params.h" + +#define SMALL_Q 769 + +static const int32_t zetas_769[64] = { + 3138844760, 1334846793, 999738812, 1854264165, 1681125041, 1150537404, 2820492178, 3071823164, 726067294, 2066499220, 3272887953, 1055590142, 4255871365, 1871019564, 2731130050, 1826338500, 513832239, 1792827701, 3373420347, 2993631302, 1161707670, 3306398751, 3518633806, 3406931146, 1586177780, 3853741788, 3317569017, 3825816122, 971813147, 122872927, 217820188, 619949766, 3753209393, 770748358, 4099487641, 765163225, 3630336467, 1742561504, 3479537875, 982983413, 2809321912, 2379266669, 703726762, 681386230, 4110657907, 1457719720, 1217559000, 2474213930, 1195218468, 1089100940, 564098436, 614364633, 3635921600, 2088839752, 3702943196, 1949211426, 2569161192, 374203913, 3982199847, 2083254619, 1513571050, 3647091866, 413299844, 4149753838}; + +static const int32_t zetas_asm_769[128] = { + 346278248, 223405321, 966228013, 759578091, -150798592, 318352582, -1736976371, 1697880440, -2105595150, -804259156, 1675539907, -1016494210, 1401868389, -2005062756, 240160720, 474736307, -1200803600, -1435379187, -1156122536, 1334846793, 999738811, 1854264164, -631120032, -787503756, -1580592646, 1681125040, 1150537403, -1474475119, -1223144132, 1809583100, -100532394, -1938041160, 726067293, 2066499219, -1022079344, 1055590142, 525002504, 273671518, -212235055, -39095931, 1871019563, -1563837247, 1826338499, 139628326, 27925665, 1731391238, 513832238, 1792827701, -921546949, -1301335995, 67021596, 1117026605, 536172770, 1161707669, -988568545, -776333490, -888036151, 1290165729, -497076839, -753992958, 1586177779, -441225509, -977398279, -469151174, -1614103444, 1591762912, -94947261, 971813146, 122872927, 217820188, 619949766, -1709050706, 1010909077, -1748146637, -541757903, 770748357, -195479656, 765163224, 1413038655, 1781657435, -1206388733, -664630830, 1742561504, -815429422, 982983412, 357448514, 44681064, -1524741316, -1485645385, -1915700627, 703726761, 681386229, 686971362, 1787242568, -860110486, -184309390, 1457719719, 1217558999, -1820753366, -502661972, -1921285760, 1139367137, 1195218467, 1089100940, 564098435, 614364633, -1100271206, 457980908, -1669954774, -659045697, 2088839751, -592024101, 1949211426, 1368357591, 698141628, 335107981, -1725806105, 374203913, -312767449, 2083254618, -1061175275, -2139105948, 519417371, 1513571050, -647875431, 413299844, -145213459, 0}; + +// INTT with CT butterfly +static const int32_t zetas_inv_asm_769[256] = { + 5585134, 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 5585134, 1736976371, -966228013, 150798592, -346278248, -318352582, -223405321, -759578091, + // removed first "2285" + LAYER 3+2+1 - 1 - butterfly + 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 636705165, 446810642, 1519156183, 11170266, -821014555, -1932456027, 301597183, -692556495, -240160720, 1061175275, -1368357591, -519417371, -335107981, 2139105948, -698141628, -625534899, -1267825197, 843355087, 290426917, 128458060, 1295750862, -748407825, -826599688, 1736976371, -240160720, 2005062756, 1061175275, 1100271206, -1368357591, 502661972, 915961816, 1396283256, 452395775, -1038834743, -955057747, -670215963, 2016233022, -16755399, -1675539907, 1614103444, -1290165729, 94947261, 753992958, -1591762912, 497076839, -1954796559, 1943626293, -1122611738, -1239899531, 938302348, -245745853, 882451018, -435640376, -966228013, 1736976371, -318352582, -240160720, -1401868389, 2005062756, 1016494210, 714897027, -1005323944, 876865885, 2122350549, -1373942724, -2094424884, 1468889985, 1558252114, -1401868389, -686971362, -357448514, 860110486, 1524741316, -1787242568, -44681064, 1407453522, -368618780, 1323676527, -653460564, -1362772458, 1379527857, -463566041, 1859849297, 150798592, -1675539907, 804259156, 1614103444, -67021596, -1290165729, -139628326, -2060914086, -994153678, 55851330, 189894523, -1072345541, 1507985917, 832184821, 1111441472, 2105595150, -525002504, -1809583100, 212235055, 1938041160, -273671518, 100532394, -2044158687, -78191862, 1452134586, 642290298, -2111180283, 552928169, 161968858, -1167292802, -346278248, -966228013, -223405321, 1736976371, 150798592, -318352582, -759578091, -1608518311, -2032988421, -899206417, -480321440, 943887481, 1491230518, -83776995, -284841784, 2005062756, 1100271206, 502661972, 1669954774, -1139367137, -457980908, 1921285760, 1128196871, -1318091394, -1904530361, 396544445, -1228729265, 117287794, 2116765416, 1184048201, -318352582, -1401868389, 1016494210, -686971362, -1413038655, -357448514, 1709050706, -731652426, 89362128, 2021818155, 1720220972, -1882189829, -1245484665, -798674023, 720482160, 804259156, -67021596, -139628326, -536172770, -1731391238, -1117026605, -27925665, -1843093898, -1971551958, 1027664477, 1776072302, -1692295306, 1977137091, 709311894, 1552666981, -223405321, 150798592, -759578091, -1675539907, 2105595150, 804259156, -1697880440, -675801096, 279256651, 949472614, -1066760408, -1050005009, -134043193, 1262240064, 1714635839, 1016494210, -1413038655, 1709050706, 1206388733, 1748146637, -1781657435, -1010909077, -390959312, -1329261660, -1083515807, -1965966825, -1530326449, 809844289, -1541496715, 1630858843, -759578091, 2105595150, -1697880440, -525002504, 631120032, -1809583100, -474736307, -1575007513, -201064789, 1893360095, 424470110, -1133782004, -418884977, -1424208921, -547343036, -1697880440, 631120032, -474736307, 1580592646, 1435379187, 787503756, 1200803600, 1999477623, -932717215, 1982722224, -1848679031, 586438968, 1993892490, 1625273710, -1346017059, 0}; + +// Q1=769 +void small_ntt_asm_769(int16_t a[N], const int32_t * zetas); +void small_invntt_asm_769(int16_t a[N], const int32_t * zetas); +void small_basemul_asm_769(int16_t *c, const int16_t *a, const int16_t *b, const int32_t *zetas); + +// small NTT for computing cs0 and cs1 +#define small_ntt(a) small_ntt_asm_769(a, zetas_asm_769) +#define small_invntt_tomont(a) small_invntt_asm_769(a, zetas_inv_asm_769) +#define small_basemul(r,a,b) small_basemul_asm_769(r, a, b, zetas_769) + +#endif diff --git a/crypto_sign/dilithium2/m4fstack/smallntt_769.S b/crypto_sign/dilithium2/m4fstack/smallntt_769.S deleted file mode 120000 index 6300683f..00000000 --- a/crypto_sign/dilithium2/m4fstack/smallntt_769.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallntt_769.S b/crypto_sign/dilithium2/m4fstack/smallntt_769.S new file mode 100644 index 00000000..1c3c9a88 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallntt_769.S @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) + * + * Licensed under the Apache License, Version 2.0(the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * NTT and inverse NTT code from: + * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. + * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. + * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. + * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S +*/ + +#include "macros.i" + +.syntax unified +.cpu cortex-m4 +.thumb + +#include "macros_smallntt.i" +// ####### +// ####### +// # NTT # +// ####### +// ####### + +.macro _3_layer_double_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_CT_16_plant_fp c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle1, twiddle2, q, qa, tmp + // layer 3 + vmov \twiddle1, \xi0 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + vmov \twiddle1, \xi1 + vmov \twiddle2, \xi2 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa + + // layer 1 + vmov \twiddle1, \xi3 + vmov \twiddle2, \xi4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + vmov \twiddle1, \xi5 + vmov \twiddle2, \xi6 + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.global small_ntt_asm_769 +.type small_ntt_asm_769, %function +.align 2 +small_ntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s24} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + ### qinv .req r11 ### q^-1 mod 2^2n; n=16 + q .req r12 + ### at the top of r12 + qa .req r0 + ### qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + // movw qa, #24608 + // Why movt? Because we initially placed qa at the bottom of the same register as q; + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 256 + .equ offset, 32 + .equ strincr, 4 + // pre-load 15 twiddle factors to 15 FPU registers + // s0-s7 used to temporary store 16 16-bit polys. + vldm twiddle_ptr!, {s8-s22} + + add tmp, poly, #strincr*8 + // s23: poly addr + // s24: tmp + vmov s24, tmp + 1: + // load a1, a3, ..., a15 + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // 8-NTT on a1, a3, ..., a15 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // s15, s16, s17, s18, s19, s20, s21, s22 left + // multiply coeffs by layer 8 twiddles for later use + vmov twiddle1, s15 + vmov twiddle2, s16 + mul_twiddle_plant poly0, twiddle1, tmp, q, qa + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + + vmov poly, s23 + + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // 8-NTT on a0, a2, ..., a14 + _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle1, s1 // load a3 + uadd16 tmp, poly1, twiddle1 + usub16 poly1, poly1, twiddle1 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle1, s3 // load a7 + uadd16 tmp, poly3, twiddle1 + usub16 poly3, poly3, twiddle1 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle1, s5 // load a11 + uadd16 tmp, poly5, twiddle1 + usub16 poly5, poly5, twiddle1 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle1, s7 // load a15 + uadd16 tmp, poly7, twiddle1 + usub16 poly7, poly7, twiddle1 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle1, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle1, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle1, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle1, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle1, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle1, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle1, poly0, poly1 + str.w twiddle1, [poly, #offset] + str.w tmp, [poly], #4 + + vmov tmp, s24 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance/16 + .equ strincr, 32 + + add.w tmp, poly, #strincr*16 + vmov s13, tmp + 2: + vmov s23, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s23 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #strincr + + vmov tmp, s13 + cmp.w poly, tmp + bne.w 2b + vpop.w {s16-s24} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + + +// ######## +// ######## +// # INTT # +// ######## +// ######## + +// input: 0.5/1q +.macro _3_layer_double_inv_CT_16_plant_light c0, c1, c2, c3, c4, c5, c6, c7, xi2, xi4, xi5, xi6, twiddle1, tmp2, q, qa, tmp + + // layer 1 + sadd16.w \tmp, \c0, \c1 // c0, c1 + ssub16.w \c1, \c0, \c1 + sadd16.w \tmp2, \c2, \c3 // c2, c3 + ssub16.w \c3, \c2, \c3 + // tmp, c1, tmp2, c3: 1q maximum + sadd16.w \c0, \c4, \c5 // c4, c5 + ssub16.w \c5, \c4, \c5 + sadd16.w \c2, \c6, \c7 // c6, c7 + ssub16.w \c7, \c6, \c7 + // c4, c6 are free at this point + // c0,c5,c2,c7 1q maximum + + // layer 2 + sadd16.w \c6, \tmp, \tmp2 // c0, c2 + ssub16.w \tmp2, \tmp, \tmp2 + sadd16.w \c4, \c0, \c2 // c4, c6 + ssub16.w \c2, \c0, \c2 + // c6, tmp2, c4, c2: 2q maximum + + vmov.w \twiddle1, \xi2 + doublebutterfly_plant \c1, \c3, \twiddle1, \tmp, \q, \qa + doublebutterfly_plant \c5, \c7, \twiddle1, \tmp, \q, \qa + // c1, c3, c7, c5: 1.5q maximum; + + // tmp and c0 are free at this point + // layer 3 + sadd16.w \c0, \c6, \c4 // c0, c4 + ssub16.w \c4, \c6, \c4 + // c0, c4: 4q + // c6 are free at this point + vmov.w \twiddle1, \xi4 + doublebutterfly_plant \c1, \c5, \twiddle1, \tmp, \q, \qa + // c1, c5: 2q maximum + + vmov.w \twiddle1, \xi5 + // this block is one doublebutterfly + smulwb \tmp, \twiddle1, \c2 // c2, c6 + smulwt \c2, \twiddle1, \c2 + smlabt \tmp, \tmp, \q, \qa + smlabt \c2, \c2, \q, \qa + pkhtb \tmp, \c2, \tmp, asr#16 + ssub16.w \c6, \tmp2, \tmp + sadd16.w \c2, \tmp2, \tmp + //c6, c2: 4.5q + vmov.w \twiddle1, \xi6 + doublebutterfly_plant \c3, \c7, \twiddle1, \tmp, \q, \qa + //c3, c7: 2.5q maximum +.endm +.macro _3_layer_double_inv_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + // layer 3 + ldr.w \twiddle1, [\twiddle_ptr], #4 + two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa + two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa + + // layer 2 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa + + two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa + + // layer 1 + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle2, \tmp, \q, \qa + + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa +.endm + +.macro _3_layer_double_inv_twist_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c0, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c1, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c2, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c3, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c4, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c5, \twiddle2, \tmp, \q, \qa + ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 + mul_twiddle_plant \c6, \twiddle1, \tmp, \q, \qa + mul_twiddle_plant \c7, \twiddle2, \tmp, \q, \qa +.endm +# input coefficients < 0.5q +.global small_invntt_asm_769 +.type small_invntt_asm_769, %function +.align 2 +small_invntt_asm_769: + push {r4-r11, r14} + vpush.w {s16-s23} + poly .req r0 + twiddle_ptr .req r1 + poly0 .req r2 + poly1 .req r3 + poly2 .req r4 + poly3 .req r5 + poly4 .req r6 + poly5 .req r7 + poly6 .req r8 + poly7 .req r9 + twiddle1 .req r10 + twiddle2 .req r11 + q .req r12 + // at the top of r12 + qa .req r0 + // qa=2^a q;a=3; at the bottom of r12 + tmp .req r14 + + movt q, #769 + + ### LAYER 7+6+5+4 + .equ distance, 16 + .equ offset, 32 + .equ strincr, 64 + + // pre-load twiddle factors to FPU registers + vldm twiddle_ptr!, {s8-s22} + + add.w tmp, poly, #8*strincr + vmov s8, tmp + 1: + vmov s23, poly + // load a1, a3, ..., a15 + load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset + load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset + + movw qa, #24608 + + // NTT on a1, a3, ..., a15 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + + // multiply coeffs by layer 4 twiddles for later use + // vmov twiddle1, s15 + vmov twiddle2, s16 + // mul_twiddle_plant poly0, twiddle1, tmp, q, qa // could be omitted but kept for reduction only + mul_twiddle_plant poly1, twiddle2, tmp, q, qa + + vmov twiddle1, s17 + vmov twiddle2, s18 + mul_twiddle_plant poly2, twiddle1, tmp, q, qa + mul_twiddle_plant poly3, twiddle2, tmp, q, qa + + vmov twiddle1, s19 + vmov twiddle2, s20 + mul_twiddle_plant poly4, twiddle1, tmp, q, qa + mul_twiddle_plant poly5, twiddle2, tmp, q, qa + + vmov twiddle1, s21 + vmov twiddle2, s22 + mul_twiddle_plant poly6, twiddle1, tmp, q, qa + mul_twiddle_plant poly7, twiddle2, tmp, q, qa + + vmov s0, poly0 // a1 + vmov s1, poly1 // a3 + vmov s2, poly2 // a5 + vmov s3, poly3 // a7 + vmov s4, poly4 // a9 + vmov s5, poly5 // a11 + vmov s6, poly6 // a13 + vmov s7, poly7 // a15 + // 0.5q + // ---------- + + vmov poly, s23 + // load a0, a2, ..., a14 + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + // NTT on a0, a2, ..., a14 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp + // 1,3,5,7: <5q; 0,2,4,6:<1q + // layer 4 - 1 + // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) + vmov poly, s23 + vmov twiddle2, s1 // load a3 + uadd16 tmp, poly1, twiddle2 + usub16 poly1, poly1, twiddle2 + str.w tmp, [poly, #1*distance/4] + str.w poly1, [poly, #1*distance/4+offset] + + vmov twiddle2, s3 // load a7 + uadd16 tmp, poly3, twiddle2 + usub16 poly3, poly3, twiddle2 + str.w tmp, [poly, #3*distance/4] + str.w poly3, [poly, #3*distance/4+offset] + + vmov twiddle2, s5 // load a11 + uadd16 tmp, poly5, twiddle2 + usub16 poly5, poly5, twiddle2 + str.w tmp, [poly, #5*distance/4] + str.w poly5, [poly, #5*distance/4+offset] + + vmov twiddle2, s7 // load a15 + uadd16 tmp, poly7, twiddle2 + usub16 poly7, poly7, twiddle2 + str.w tmp, [poly, #7*distance/4] + str.w poly7, [poly, #7*distance/4+offset] + //1,3,5,7: < 5.5q + + // layer 4 - 2 + // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) + vmov poly3, s2 // load a5 + uadd16 tmp, poly2, poly3 + usub16 twiddle2, poly2, poly3 + str.w tmp, [poly, #2*distance/4] + str.w twiddle2, [poly, #2*distance/4+offset] + + vmov poly5, s4 // load a9 + uadd16 tmp, poly4, poly5 + usub16 twiddle2, poly4, poly5 + str.w tmp, [poly, #4*distance/4] + str.w twiddle2, [poly, #4*distance/4+offset] + + vmov poly7, s6 // load a13 + uadd16 tmp, poly6, poly7 + usub16 twiddle2, poly6, poly7 + str.w tmp, [poly, #6*distance/4] + str.w twiddle2, [poly, #6*distance/4+offset] + + vmov poly1, s0 // load a1 + uadd16 tmp, poly0, poly1 + usub16 twiddle2, poly0, poly1 + str.w twiddle2, [poly, #offset] + str.w tmp, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) + //0,2,4,6: < 1.5q + vmov tmp, s8 + cmp.w poly, tmp + bne.w 1b + + sub.w poly, #8*strincr + + ### LAYER 3+2+1 + + .equ distance, distance*16 + .equ strincr, 4 + + // ITER 0 + vmov s6, poly + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + vldm twiddle_ptr!, {s0-s5} + movw qa, #24608 + // twiddle2 is used as tmp2 + _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s1, s3, s4, s5, twiddle1, twiddle2, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + // ITER 1-15 + add.w tmp, poly, #strincr*3*(5) + vmov s14, tmp + 2: + vmov s6, poly + // polys upto 5.5q + load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 + load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + + movw qa, #24608 + _3_layer_double_inv_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + // twisting + _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp + + vmov poly, s6 + store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 + str.w poly1, [poly, #distance/4] + str.w poly2, [poly, #2*distance/4] + str.w poly3, [poly, #3*distance/4] + str.w poly0, [poly], #4 + + vmov tmp, s14 + cmp.w poly, tmp + bne.w 2b + + vpop.w {s16-s23} + pop {r4-r11, pc} + +.unreq poly +.unreq twiddle_ptr +.unreq poly0 +.unreq poly1 +.unreq poly2 +.unreq poly3 +.unreq poly4 +.unreq poly5 +.unreq poly6 +.unreq poly7 +.unreq twiddle1 +.unreq twiddle2 +.unreq q +.unreq qa +.unreq tmp + +// BASEMUL + +/* +* Basemul code (adapted to q=769) from: +* Huang, J. et al. 2022. Improved Plantard Arithmetic for Lattice-based Cryptography. +* IACR Transactions on Cryptographic Hardware and Embedded Systems. 2022, 4 (Aug. 2022), 614–636. +* DOI:https://doi.org/10.46586/tches.v2022.i4.614-636. +* https://github.com/UIC-ESLAS/ImprovedPlantardArithmetic/blob/f3482cfd09dda8f1f55b95e13616147e3b6dd008/crypto_kem/kyber768/m4fstack/fastbasemul.S +*/ + +.global small_basemul_asm_769 +.type small_basemul_asm_769, %function +.align 2 +small_basemul_asm_769: + push {r4-r11, lr} + + rptr .req r0 + aptr .req r1 + bptr .req r2 + zetaptr .req r3 + poly0 .req r4 + poly1 .req r6 + poly2 .req r5 + poly3 .req r7 + q .req r8 + qa .req r14 + qinv .req r9 + tmp .req r10 + tmp2 .req r11 + zeta .req r12 + loop .req r14 + + movt q, #769 + movw qinv, #64769 + movt qinv, #58632 + + movw loop, #64 + 1: + vmov.w s0,loop + movw qa, #24608 + + ldrd poly0, poly2, [aptr], #8 + ldrd poly1, poly3, [bptr], #8 + // ldr poly0, [aptr], #4 + // ldr poly1, [bptr], #4 + // ldr poly2, [aptr], #4 + // ldr poly3, [bptr], #4 + + ldr.w zeta, [zetaptr], #4 + + // basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, zetas[64 + i]); + smulwt tmp, zeta, poly1 + smlabt tmp, tmp, q, qa + smultt tmp, poly0, tmp + smlabb tmp, poly0, poly1, tmp + plant_red q, qa, qinv, tmp + // r[0] in upper half of tmp + + smuadx tmp2, poly0, poly1 + plant_red q, qa, qinv, tmp2 + // r[1] in upper half of tmp2 + pkhtb tmp, tmp2, tmp, asr#16 + str tmp, [rptr], #4 + + neg zeta, zeta + + // basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - zetas[64 + i]); + smulwt tmp, zeta, poly3 + smlabt tmp, tmp, q, qa + smultt tmp, poly2, tmp + smlabb tmp, poly2, poly3, tmp + plant_red q, qa, qinv, tmp + // r[0] in upper half of tmp + + smuadx tmp2, poly2, poly3 + plant_red q, qa, qinv, tmp2 + // r[1] in upper half of tmp2 + pkhtb tmp, tmp2, tmp, asr#16 + str tmp, [rptr], #4 + + vmov.w loop,s0 + subs.w loop, #1 + bne.w 1b + + .unreq rptr + .unreq aptr + .unreq bptr + .unreq zetaptr + .unreq poly0 + .unreq poly1 + .unreq poly2 + .unreq poly3 + .unreq q + .unreq qa + .unreq qinv + .unreq tmp + .unreq tmp2 + .unreq zeta + .unreq loop + + pop {r4-r11, pc} +//-0.5p~0.5p \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.c b/crypto_sign/dilithium2/m4fstack/smallpoly.c deleted file mode 120000 index 7dbf4992..00000000 --- a/crypto_sign/dilithium2/m4fstack/smallpoly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.c b/crypto_sign/dilithium2/m4fstack/smallpoly.c new file mode 100644 index 00000000..433d98af --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallpoly.c @@ -0,0 +1,83 @@ +#include "smallpoly.h" +#include "smallntt.h" + +void poly_small_ntt_copy(smallpoly *out, poly *in) { + for (int i = N - 1; i >= 0; i--) + { + out->coeffs[i] = in->coeffs[i]; + } + small_ntt(out->coeffs); +} + + +void polyvecl_small_ntt(smallpoly v[L]) { + unsigned int i; + + for(i = 0; i < L; ++i) + small_ntt(v[i].coeffs); +} + + +void polyveck_small_ntt(smallpoly v[K]) { + unsigned int i; + + for(i = 0; i < K; ++i) + small_ntt(v[i].coeffs); +} + + + +void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b){ + // re-use the buffer + smallpoly *tmp = (smallpoly *)r; + small_basemul(tmp->coeffs, a->coeffs, b->coeffs); + small_invntt_tomont(tmp->coeffs); + + #ifdef SMALL_POLY_16_BIT + int j; + // buffer is the same, so we neeed to be careful + for(j=N-1;j>=0;j--){ + r->coeffs[j] = tmp->coeffs[j]; + } + #endif +} + +void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]){ + unsigned int i; + for(i=0;ivec[i], a, &b[i]); + } +} + +void small_polyeta_unpack(smallpoly *r, const uint8_t *a) { + unsigned int i; + +#if ETA == 2 + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; + r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; + r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; + r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; + r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; + r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; + r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; + r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; + + r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; + } +#elif ETA == 4 + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[i] & 0x0F; + r->coeffs[2*i+1] = a[i] >> 4; + r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; + } +#endif +} diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.h b/crypto_sign/dilithium2/m4fstack/smallpoly.h deleted file mode 120000 index 366391d9..00000000 --- a/crypto_sign/dilithium2/m4fstack/smallpoly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.h b/crypto_sign/dilithium2/m4fstack/smallpoly.h new file mode 100644 index 00000000..1aac98fa --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/smallpoly.h @@ -0,0 +1,27 @@ +#ifndef SMALLPOLY_H +#define SMALLPOLY_H +#include "params.h" +#include "poly.h" +#include "polyvec.h" + + + +#define SMALL_POLY_16_BIT +typedef struct { + int16_t coeffs[N]; +} smallpoly; + +typedef smallpoly smallhalfpoly; + +void poly_small_ntt_copy(smallpoly*, poly*); + +void polyvecl_small_ntt(smallpoly v[L]); +void polyveck_small_ntt(smallpoly v[K]); + + +void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]); +void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b); + +void small_polyeta_unpack(smallpoly *r, const uint8_t *a); + +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.c b/crypto_sign/dilithium2/m4fstack/stack.c deleted file mode 120000 index c89dc5a0..00000000 --- a/crypto_sign/dilithium2/m4fstack/stack.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.c b/crypto_sign/dilithium2/m4fstack/stack.c new file mode 100644 index 00000000..b45f7021 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/stack.c @@ -0,0 +1,715 @@ +#include "stack.h" +#include "fips202.h" +#include "symmetric.h" +#include "vector.h" +#include "reduce.h" +#include "rounding.h" + +void poly_challenge_compress(uint8_t c[68], const poly *cp){ + unsigned int i, pos; + uint64_t signs; + uint64_t mask; + /* Encode c */ + for(i=0;i<68;i++) c[i] = 0; + signs = 0; + mask = 1; + pos = 0; + for(i = 0; i < N; ++i){ + if(cp->coeffs[i] != 0){ + c[pos++] = i; + if(cp->coeffs[i] == -1){ + signs |= mask; + } + mask <<= 1; + } + } + + for (i = 0; i < 8; ++i) { + c[60+i] = (unsigned char) (signs >> 8 * i); + } +} + +void poly_challenge_decompress(poly *cp, const uint8_t c[68]){ + unsigned int i; + unsigned pos; + uint64_t signs = 0; + for(i = 0; i < N; i++) cp->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)c[60+i]) << (8*i); + } + + for(i = 0; i < TAU; i++){ + pos = c[i]; + if(signs & 1){ + cp->coeffs[pos] = -1; + } else { + cp->coeffs[pos] = 1; + } + signs >>= 1; + } +} + + +// TODO: buffer at most 8 coeffs at once +static inline int32_t polyt0_unpack_idx(const uint8_t *t0, unsigned idx){ + int32_t coeff; + // 8 coefficients are packed in 13 bytes + t0 += 13*(idx >> 3); + + if(idx % 8 == 0){ + coeff = t0[0]; + coeff |= (uint32_t)t0[1] << 8; + } else if(idx % 8 == 1){ + coeff = t0[1] >> 5; + coeff |= (uint32_t)t0[2] << 3; + coeff |= (uint32_t)t0[3] << 11; + } else if(idx % 8 == 2){ + coeff = t0[3] >> 2; + coeff |= (uint32_t)t0[4] << 6; + } else if(idx % 8 == 3){ + coeff = t0[4] >> 7; + coeff |= (uint32_t)t0[5] << 1; + coeff |= (uint32_t)t0[6] << 9; + } else if(idx % 8 == 4){ + coeff = t0[6] >> 4; + coeff |= (uint32_t)t0[7] << 4; + coeff |= (uint32_t)t0[8] << 12; + } else if(idx % 8 == 5){ + coeff = t0[8] >> 1; + coeff |= (uint32_t)t0[9] << 7; + } else if(idx % 8 == 6){ + coeff = t0[9] >> 6; + coeff |= (uint32_t)t0[10] << 2; + coeff |= (uint32_t)t0[11] << 10; + } else if(idx % 8 == 7){ + coeff = t0[11] >> 3; + coeff |= (uint32_t)t0[12] << 5; + } + coeff &= 0x1FFF; + return (1 << (D-1)) - coeff; +} + +static inline int32_t polyt1_unpack_idx(const uint8_t *t1, unsigned idx){ + int32_t coeff; + // 4 coefficients are packed in 5 bytes + t1 += 5*(idx >> 2); + + if(idx % 4 == 0){ + coeff = (t1[0] >> 0); + coeff |= ((uint32_t)t1[1] << 8); + } else if(idx % 4 == 1){ + coeff = (t1[1] >> 2); + coeff |= ((uint32_t)t1[2] << 6); + } else if(idx % 4 == 2){ + coeff = (t1[2] >> 4); + coeff |= ((uint32_t)t1[3] << 4); + } else if(idx % 4 == 3){ + coeff = (t1[3] >> 6); + coeff |= ((uint32_t)t1[4] << 2); + } + coeff &= 0x3FF; + return coeff; +} + +void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0){ + unsigned i,j,idx; + uint64_t signs = 0; + for(i = 0; i < N; i++) c->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)ccomp[60+i]) << (8*i); + } + + for(idx = 0; idx < TAU; idx++){ + i = ccomp[idx]; + if(!(signs & 1)){ + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] += polyt0_unpack_idx(t0, j); + } + for(j = N-i; jcoeffs[i+j-N] -= polyt0_unpack_idx(t0, j); + } + } else { + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] -= polyt0_unpack_idx(t0, j); + } + for(j = N-i; jcoeffs[i+j-N] += polyt0_unpack_idx(t0, j); + } + } + + signs >>= 1; + } +} + +void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1){ + unsigned i,j,idx; + uint64_t signs = 0; + for(i = 0; i < N; i++) c->coeffs[i] = 0; + for(i = 0; i < 8; i++) { + signs |= ((uint64_t)ccomp[60+i]) << (8*i); + } + + for(idx = 0; idx < TAU; idx++){ + i = ccomp[idx]; + if(!(signs & 1)){ + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] += (polyt1_unpack_idx(t1, j) << D); + } + for(j = N-i; jcoeffs[i+j-N] -= (polyt1_unpack_idx(t1, j) << D); + } + } else { + for(j = 0; i+j < N; j++){ + c->coeffs[i+j] -= (polyt1_unpack_idx(t1, j) << D); + } + for(j = N-i; jcoeffs[i+j-N] += (polyt1_unpack_idx(t1, j) << D); + } + } + + signs >>= 1; + } +} + + +void polyw_pack(uint8_t buf[3*256], poly *w){ + poly_reduce(w); + poly_caddq(w); + unsigned int i; + for(i = 0; i < N; i++){ + buf[i*3 + 0] = w->coeffs[i]; + buf[i*3 + 1] = w->coeffs[i] >> 8; + buf[i*3 + 2] = w->coeffs[i] >> 16; + } +} + +void polyw_unpack(poly *w, const uint8_t buf[3*256]) { + unsigned int i; + for(i = 0; i < N; i++){ + w->coeffs[i] = buf[i*3 + 0]; + w->coeffs[i] |= (int32_t)buf[i*3 + 1] << 8; + w->coeffs[i] |= (int32_t)buf[i*3 + 2] << 16; + } +} + + +static void polyw_add_idx(uint8_t buf[3*256], int32_t a, size_t i){ + int32_t coeff; + coeff = buf[i*3 + 0]; + coeff |= (int32_t)buf[i*3 + 1] << 8; + coeff |= (int32_t)buf[i*3 + 2] << 16; + + coeff += a; + + coeff = freeze(coeff); + + buf[i*3 + 0] = coeff; + buf[i*3 + 1] = coeff >> 8; + buf[i*3 + 2] = coeff >> 16; +} + +void polyw_add(uint8_t buf[3*256], poly *p){ + unsigned int i; + for(i = 0; i < N; i++){ + polyw_add_idx(buf, p->coeffs[i], i); + } +} +void polyw_sub(poly* c, uint8_t buf[3*256], poly *a){ + int32_t coeff; + + + for(size_t i=0;icoeffs[i] = coeff - a->coeffs[i]; + } +} + +static int32_t highbits(int32_t a){ + int32_t a1; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + return a1; +} + +void poly_highbits(poly *a1, const poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a1->coeffs[i] = highbits(a->coeffs[i]); +} + +static int32_t lowbits(int32_t a){ + int32_t a1; + int32_t a0; + + a1 = (a + 127) >> 7; +#if GAMMA2 == (Q-1)/32 + a1 = (a1*1025 + (1 << 21)) >> 22; + a1 &= 15; +#elif GAMMA2 == (Q-1)/88 + a1 = (a1*11275 + (1 << 23)) >> 24; + a1 ^= ((43 - a1) >> 31) & a1; +#endif + + a0 = a - a1*2*GAMMA2; + a0 -= (((Q-1)/2 - a0) >> 31) & Q; + return a0; +} + +void poly_lowbits(poly *a0, const poly *a){ + unsigned int i; + + for(i = 0; i < N; ++i) + a0->coeffs[i] = lowbits(a->coeffs[i]); +} + +void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx) { + small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + idx*POLYETA_PACKEDBYTES); +} +void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx) { + small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + L*POLYETA_PACKEDBYTES + idx*POLYETA_PACKEDBYTES); +} + + +// TODO: in the end increase this buffer size as far as possible +#define POLY_UNIFORM_BUFFERSIZE 3 +void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state){ + int32_t t; + uint8_t buf[POLY_UNIFORM_BUFFERSIZE*3]; + { + size_t ctr = 0; + stream128_init(state, seed, nonce); + + do { + shake128_inc_squeeze(buf, sizeof buf, state); + + for(size_t pos=0; pos < sizeof buf && ctr < N; pos += 3){ + t = buf[pos]; + t |= (uint32_t)buf[pos+1] << 8; + t |= (uint32_t)buf[pos+2] << 16; + t &= 0x7FFFFF; + + if(t < Q) { + t = montgomery_reduce((int64_t)t * b->coeffs[ctr]); + polyw_add_idx(wcomp, t, ctr); + ctr++; + } + } + } while(ctr < N); + + } +} + +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE 1 +#if GAMMA1 == (1 << 17) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*4) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*9) +#elif GAMMA1 == (1 << 19) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*2) +#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*5) +#endif + +static void polyz_unpack_inplace(int32_t *r){ + uint8_t *a = (uint8_t *)r; + + unsigned int i,j; + #if GAMMA1 == (1 << 17) + for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { + i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; + int32_t t0; + + + r[4*i+3] = a[9*i+6] >> 6; + r[4*i+3] |= (uint32_t)a[9*i+7] << 2; + r[4*i+3] |= (uint32_t)a[9*i+8] << 10; + r[4*i+3] &= 0x3FFFF; + + r[4*i+2] = a[9*i+4] >> 4; + r[4*i+2] |= (uint32_t)a[9*i+5] << 4; + r[4*i+2] |= (uint32_t)a[9*i+6] << 12; + r[4*i+2] &= 0x3FFFF; + + + r[4*i+1] = (uint32_t)a[9*i+4] << 14; + r[4*i+1] |= a[9*i+2] >> 2; + r[4*i+1] |= (uint32_t)a[9*i+3] << 6; + r[4*i+1] &= 0x3FFFF; + + t0 = a[9*i+0]; + t0 |= (uint32_t)a[9*i+1] << 8; + t0 |= (uint32_t)a[9*i+2] << 16; + t0 &= 0x3FFFF; + + r[4*i+0] = GAMMA1 - t0; + r[4*i+1] = GAMMA1 - r[4*i+1]; + r[4*i+2] = GAMMA1 - r[4*i+2]; + r[4*i+3] = GAMMA1 - r[4*i+3]; + + } +#elif GAMMA1 == (1 << 19) + for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { + i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; + int32_t tmp0, tmp1; + + tmp0 = a[5*i+2] >> 4; + tmp0 |= (uint32_t)a[5*i+3] << 4; + tmp0 |= (uint32_t)a[5*i+4] << 12; + tmp0 &= 0xFFFFF; + + tmp1 = a[5*i+0]; + tmp1 |= (uint32_t)a[5*i+1] << 8; + tmp1 |= (uint32_t)a[5*i+2] << 16; + tmp1 &= 0xFFFFF; + + r[2*i+0] = GAMMA1 - tmp1; + r[2*i+1] = GAMMA1 - tmp0; + } +#endif +} + +void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ + int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; + + stream256_init(state, seed, nonce); + for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ + shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); + polyz_unpack_inplace(buf); + + for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ + a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j]; + } + } +} + +void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ + int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; + + stream256_init(state, seed, nonce); + for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ + shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); + polyz_unpack_inplace(buf); + + for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ + a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j] + b->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j]; + } + } +} + + +static inline int32_t make_hint_stack(int32_t z, int32_t r){ + int32_t r1, v1; + + r1 = highbits(r); + v1 = highbits(r+z); + + if(r1 != v1) return 1; + return 0; +} + +size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]){ + int32_t coeff; + size_t hints_n = 0; + for(size_t i=0;icoeffs[i]; + + a->coeffs[i] = make_hint_stack(-t->coeffs[i], coeff); + if(a->coeffs[i] == 1){ + hints_n++; + } + } + return hints_n; +} + +void unpack_sk_stack(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + key[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < TRBYTES; ++i) + tr[i] = sk[i]; + sk += TRBYTES; +} + +/************************************************* +* Name: unpack_sig_h_indices +* +* Description: Unpack only h from signature sig = (c, z, h). +* +* Arguments: - polyveck *h: pointer to output hint vector h +* - const unsigned char sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]) { + sig += L * POLYZ_PACKEDBYTES; + sig += CTILDEBYTES; + /* Decode h */ + unsigned int k = 0; + unsigned int hidx = 0; + + if (idx > 0) + { + k = sig[OMEGA + (idx - 1)]; + } + + if (sig[OMEGA + idx] < k || sig[OMEGA + idx] > OMEGA) { + return 1; + } + + for (unsigned int j = k; j < sig[OMEGA + idx]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if (j > k && sig[j] <= sig[j - 1]) { + return 1; + } + h_i[hidx++] = sig[j]; + } + + *number_of_hints = hidx; + + /* TODO: extract this check, redundant here */ + k = sig[OMEGA + (K - 1)]; + /* Extra indices are zero for strong unforgeability */ + for (unsigned int j = k; j < OMEGA; ++j) { + if (sig[j]) { + return 1; + } + } + return 0; +} + +/************************************************* +* Name: poly_use_hint_stack +* +* Description: Use hint polynomial to correct the high bits of a polynomial. +* +* Arguments: - poly *b: pointer to output polynomial with corrected high bits +* - const poly *a: pointer to input polynomial +* - const poly *h: pointer to input hint polynomial +**************************************************/ +void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints) { + unsigned int i; + unsigned int in_list; + + for(i = 0; i < N; ++i) + { + in_list = 0; + for (size_t hidx = 0; hidx < number_of_hints; hidx++) + { + if (i == h_i[hidx]) + { + in_list = 1; + break; + } + } + if (in_list) + { + b->coeffs[i] = use_hint(a->coeffs[i], 1); + } + else + { + b->coeffs[i] = use_hint(a->coeffs[i], 0); + } + + } +} + +/************************************************* +* Name: pack_pk_rho +* +* Description: Bit-pack only rho in public key pk = (rho, t1). +* +* Arguments: - unsigned char pk[]: output byte array +* - const unsigned char rho[]: byte array containing rho +**************************************************/ +void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const unsigned char rho[SEEDBYTES]) { + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + pk[i] = rho[i]; + } +} + +/************************************************* +* Name: pack_pk_t1 +* +* Description: Bit-pack only the t1 elem at idx in public key pk = (rho, t1). +* +* Arguments: - unsigned char pk[]: output byte array +* - const polyveck *t1: pointer to vector t1 +* - const unsigned int idx: index to the elem to pack +**************************************************/ +void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const poly *t1, + const unsigned int idx) { + pk += SEEDBYTES; + polyt1_pack(pk + idx * POLYT1_PACKEDBYTES, t1); +} + +/************************************************* +* Name: pack_sk_s1 +* +* Description: Bit-pack only some element of s1 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *s1_elem: pointer to vector element idx in s1 +* - const unisgned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s1_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES; + polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s1_elem); +} + +/************************************************* +* Name: pack_sk_s2 +* +* Description: Bit-pack only some element of s2 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *s2_elem: pointer to vector element idx in s2 +* - const unsigned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s2_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES; + polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s2_elem); +} + +/************************************************* +* Name: pack_sk_t0 +* +* Description: Bit-pack only some element of t0 in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const poly *t0_elem: pointer to vector element idx in s2 +* - const unsigned int idx: index to the element of s1 that should be packed +**************************************************/ +void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *t0_elem, + const unsigned int idx) { + sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES + K * POLYETA_PACKEDBYTES; + polyt0_pack(sk + idx * POLYT0_PACKEDBYTES, t0_elem); +} + +/************************************************* +* Name: pack_sk_rho +* +* Description: Bit-pack only rho in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char rho[]: byte array containing rho +**************************************************/ +void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char rho[SEEDBYTES]) { + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + sk[i] = rho[i]; + } +} + +/************************************************* +* Name: pack_sk_key +* +* Description: Bit-pack only key in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char key[]: byte array containing key +**************************************************/ +void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char key[SEEDBYTES]) { + sk += SEEDBYTES; + for (unsigned int i = 0; i < SEEDBYTES; ++i) { + sk[i] = key[i]; + } +} + +/************************************************* +* Name: pack_sk_tr +* +* Description: Bit-pack only tr in secret key sk = (rho, key, tr, s1, s2, t0). +* +* Arguments: - unsigned char sk[]: output byte array +* - const unsigned char tr[]: byte array containing tr +**************************************************/ +void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char tr[TRBYTES]) { + sk += 2*SEEDBYTES; + for (unsigned int i = 0; i < TRBYTES; ++i) { + sk[i] = tr[i]; + } +} + +/************************************************* +* Name: challenge +* +* Description: Implementation of H. Samples polynomial with TAU nonzero +* coefficients in {-1,1} using the output stream of +* SHAKE256(seed). Stack optimized. +* +* Arguments: - poly *c: pointer to output polynomial +* - const uint8_t mu[]: byte array containing seed of length SEEDBYTES +**************************************************/ +#define CHALLENGE_STACK_BUF_SIZE 8 +void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]) { + unsigned int i, b, pos; + uint64_t signs; + uint8_t buf[CHALLENGE_STACK_BUF_SIZE]; + shake256incctx state; + + shake256_inc_init(&state); + shake256_inc_absorb(&state, seed, SEEDBYTES); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); + signs = 0; + for(i = 0; i < 8; ++i) + { + signs |= (uint64_t)buf[i] << 8*i; + } + pos = 8; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + for(i = N-TAU; i < N; ++i) { + do { + if(pos >= CHALLENGE_STACK_BUF_SIZE) { + shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); + pos = 0; + } + + b = buf[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = 1 - 2*(signs & 1); + signs >>= 1; + } +} \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.h b/crypto_sign/dilithium2/m4fstack/stack.h deleted file mode 120000 index c9aed5d7..00000000 --- a/crypto_sign/dilithium2/m4fstack/stack.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium3/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/stack.h b/crypto_sign/dilithium2/m4fstack/stack.h new file mode 100644 index 00000000..06c8c576 --- /dev/null +++ b/crypto_sign/dilithium2/m4fstack/stack.h @@ -0,0 +1,69 @@ +#ifndef STACK_H +#define STACK_H + +#include "poly.h" +#include "smallpoly.h" +#include +#include +#include "fips202.h" + +void poly_challenge_compress(uint8_t c[68], const poly *cp); +void poly_challenge_decompress(poly *cp, const uint8_t c[68]); + + +void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0); +void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1); +void polyw_pack(uint8_t buf[3*256], poly *w); +void polyw_unpack(poly *w, const uint8_t buf[3*256]); + +void polyw_add(uint8_t buf[3*256], poly *p); +void polyw_sub(poly* c, uint8_t buf[3*256], poly *a); + +void poly_highbits(poly *a1, const poly *a); +void poly_lowbits(poly *a0, const poly *a); + +void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx); +void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx); + +void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state); +void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); +void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); +void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]); + +size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]); +int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]); +void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints); + +void unpack_sk_stack(uint8_t rho[SEEDBYTES], + uint8_t tr[TRBYTES], + uint8_t key[SEEDBYTES], + const uint8_t sk[CRYPTO_SECRETKEYBYTES]); + +void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const unsigned char rho[SEEDBYTES]); + +void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], + const poly *t1, + const unsigned int idx); + +void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s1_elem, + const unsigned int idx); + +void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *s2_elem, + const unsigned int idx); + +void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const poly *t0_elem, + const unsigned int idx); + +void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char rho[SEEDBYTES]); + +void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char key[SEEDBYTES]); + +void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], + const unsigned char tr[TRBYTES]); +#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/api.h b/crypto_sign/dilithium3/m4fstack/api.h deleted file mode 100644 index a289632c..00000000 --- a/crypto_sign/dilithium3/m4fstack/api.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef API_H -#define API_H - -#include -#include -#include "params.h" - -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/api.h b/crypto_sign/dilithium3/m4fstack/api.h new file mode 120000 index 00000000..9d1668d8 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/api.h @@ -0,0 +1 @@ +../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/config.h b/crypto_sign/dilithium3/m4fstack/config.h deleted file mode 100644 index 55724079..00000000 --- a/crypto_sign/dilithium3/m4fstack/config.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define DILITHIUM_MODE 3 -// #define SIGN_STACKSTRATEGY 2 - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/config.h b/crypto_sign/dilithium3/m4fstack/config.h new file mode 120000 index 00000000..f3892d90 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/config.h @@ -0,0 +1 @@ +../m4f/config.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/macros.i b/crypto_sign/dilithium3/m4fstack/macros.i deleted file mode 100644 index 25d98c2b..00000000 --- a/crypto_sign/dilithium3/m4fstack/macros.i +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef MACROS_I -#define MACROS_I -// 3 -.macro montgomery_mul_32 a, b, Qprime, Q, tmp, tmp2 - smull \tmp, \a, \a, \b - mul \tmp2, \tmp, \Qprime - smlal \tmp, \a, \tmp2, \Q -.endm - -// 2 -.macro addSub1 c0, c1 - add.w \c0, \c1 - sub.w \c1, \c0, \c1, lsl #1 -.endm - -// 3 -.macro addSub2 c0, c1, c2, c3 - add \c0, \c1 - add \c2, \c3 - sub.w \c1, \c0, \c1, lsl #1 - sub.w \c3, \c2, \c3, lsl #1 -.endm - -// 6 -.macro addSub4 c0, c1, c2, c3, c4, c5, c6, c7 - add \c0, \c1 - add \c2, \c3 - add \c4, \c5 - add \c6, \c7 - sub.w \c1, \c0, \c1, lsl #1 - sub.w \c3, \c2, \c3, lsl #1 - sub.w \c5, \c4, \c5, lsl #1 - sub.w \c7, \c6, \c7, lsl #1 -.endm - -.macro _2_layer_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 - montgomery_mul_32 \c2, \zeta0, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 - addSub2 \c0, \c2, \c1, \c3 - - montgomery_mul_32 \c1, \zeta1, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 - addSub2 \c0, \c1, \c2, \c3 -.endm - -.macro _2_layer_inv_CT_32 c0, c1, c2, c3, zeta0, zeta1, zeta2, Qprime, Q, tmp, tmp2 - montgomery_mul_32 \c1, \zeta0, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \zeta0, \Qprime, \Q, \tmp, \tmp2 - addSub2 \c0, \c1, \c2, \c3 - - montgomery_mul_32 \c2, \zeta1, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \zeta2, \Qprime, \Q, \tmp, \tmp2 - addSub2 \c0, \c2, \c1, \c3 -.endm - -.macro _3_layer_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 - vmov.w \twiddle, \xi0 - montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 - - vmov.w \twiddle, \xi1 - montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi2 - montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 - - vmov.w \twiddle, \xi3 - montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi4 - montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi5 - montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi6 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 -.endm - -.macro _3_layer_inv_CT_32 c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 - vmov.w \twiddle, \xi0 - montgomery_mul_32 \c1, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c1, \c2, \c3, \c4, \c5, \c6, \c7 - - vmov.w \twiddle, \xi1 - montgomery_mul_32 \c2, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi2 - montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c2, \c1, \c3, \c4, \c6, \c5, \c7 - - vmov.w \twiddle, \xi3 - montgomery_mul_32 \c4, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi4 - montgomery_mul_32 \c5, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi5 - montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 - vmov.w \twiddle, \xi6 - montgomery_mul_32 \c7, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 -.endm - -/************************************************************ -* Name: _3_layer_inv_butterfly_light_fast_first -* -* Description: upper half of 3-layer inverse butterfly -* defined over X^8 - 1 -* -* Input: (c4, c1, c6, c3) = coefficients on the upper half; -* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = -* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in -* Montgomery domain -* -* Symbols: R = 2^32 -* -* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD -* -* Output: -* c4 = c4 + c1 + (c6 + c3) -* c5 = (c4 - c1) w_4 + (c6 + c3) w_8^3 -* c6 = c4 + c1 - (c6 + c3) -* c7 = (c4 - c1) w_8^3 + (c6 + c3) w_4 -************************************************************/ -// 15 -.macro _3_layer_inv_butterfly_light_fast_first c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 - addSub2 \c4, \c1, \c6, \c3 - addSub1 \c4, \c6 - - vmov.w \tmp, \xi4 - vmov.w \tmp2, \xi6 - - smull.w \c0, \c5, \c1, \tmp - smlal.w \c0, \c5, \c3, \tmp2 - mul.w \twiddle, \c0, \Qprime - smlal.w \c0, \c5, \twiddle, \Q - - smull.w \c2, \c7, \c1, \tmp2 - smlal.w \c2, \c7, \c3, \tmp - mul.w \twiddle, \c2, \Qprime - smlal.w \c2, \c7, \twiddle, \Q -.endm - -/************************************************************ -* Name: _3_layer_inv_butterfly_light_fast_second -* -* Description: lower half of 3-layer inverse butterfly -* defined over X^8 - 1, and the 2nd -* layer of butterflies -* -* Input: -* (c4, c5, c6, c7) = results of the upper half; -* (c0, c1, c2, c3) = coefficients on the lower half; -* (xi0, xi1, xi2, xi3, xi4, xi5, xi6) = -* ( 1, 1, w_4, 1, w_8, w_4, w_8^3) in -* Montgomery domain -* -* Symbols: R = 2^32 -* -* Constants: Qprime = -MOD^{-1} mod^{+-} R, Q = MOD -* -* Output: (normal order) -* c0 = c0 + c1 + (c2 + c3) + ( c4 + c5 + (c6 + c7) ) -* c1 = (c0 - c1) w3 + (c2 - c3) w4 + ( (c4 - c5) w5 + (c6 - c7) w6 ) -* c2 = ( c0 + c1 - (c2 + c3)) w1 + (( c4 + c5 - (c6 + c7) ) w2) -* c3 = ((c0 - c1) w3 - (c2 - c3) w4) w1 + (((c4 - c5) w5 - (c6 - c7) w6) w2) -* c4 = c0 + c1 - (c2 + c3) - ( c4 + c5 + (c6 + c7) ) w0 -* c5 = (c0 - c1) w3 + (c2 - c3) w4 - ( (c4 - c5) w5 + (c6 - c7) w6 ) w0 -* c6 = ( c0 + c1 - (c2 + c3)) w1 - (( c4 + c5 - (c6 + c7) ) w2) w0 -* c7 = ((c0 - c1) w3 - (c2 - c3) w4) w1 - (((c4 - c5) w5 - (c6 - c7) w6) w2) w0 -************************************************************/ -// 19 -.macro _3_layer_inv_butterfly_light_fast_second c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle, Qprime, Q, tmp, tmp2 - addSub2 \c0, \c1, \c2, \c3 - - vmov.w \twiddle, \xi2 - montgomery_mul_32 \c3, \twiddle, \Qprime, \Q, \tmp, \tmp2 - addSub2 \c0, \c2, \c1, \c3 - - montgomery_mul_32 \c6, \twiddle, \Qprime, \Q, \tmp, \tmp2 - - addSub4 \c0, \c4, \c1, \c5, \c2, \c6, \c3, \c7 -.endm - -#endif /* MACROS_I */ diff --git a/crypto_sign/dilithium3/m4fstack/macros.i b/crypto_sign/dilithium3/m4fstack/macros.i new file mode 120000 index 00000000..e3f2469a --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/macros.i @@ -0,0 +1 @@ +../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i deleted file mode 100644 index 7c9a387c..00000000 --- a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) - * - * Licensed under the Apache License, Version 2.0(the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * NTT and inverse NTT code from: - * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. - * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. - * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. - * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S -*/ - -#ifndef MACROS_SMALLNTT_I -#define MACROS_SMALLNTT_I - -// general macros -.macro load a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 - ldr.w \a0, [\a, \mem0] - ldr.w \a1, [\a, \mem1] - ldr.w \a2, [\a, \mem2] - ldr.w \a3, [\a, \mem3] -.endm - -.macro store a, a0, a1, a2, a3, mem0, mem1, mem2, mem3 - str.w \a0, [\a, \mem0] - str.w \a1, [\a, \mem1] - str.w \a2, [\a, \mem2] - str.w \a3, [\a, \mem3] -.endm - -.macro doubleplant a, tmp, q, qa, plantconst - smulwb \tmp, \plantconst, \a - smulwt \a, \plantconst, \a - smlabt \tmp, \tmp, \q, \qa - smlabt \a, \a, \q, \qa - pkhtb \a, \a, \tmp, asr#16 -.endm - -.macro doublebarrett a, tmp, tmp2, q, barrettconst - smulbb \tmp, \a, \barrettconst - smultb \tmp2, \a, \barrettconst - asr \tmp, \tmp, #26 - asr \tmp2, \tmp2, #26 - smulbb \tmp, \tmp, \q - smulbb \tmp2, \tmp2, \q - pkhbt \tmp, \tmp, \tmp2, lsl#16 - usub16 \a, \a, \tmp -.endm - -// q locate in the top half of the register -.macro plant_red q, qa, qinv, tmp - mul \tmp, \tmp, \qinv - //tmp*qinv mod 2^2n/ 2^n; in high half - smlatt \tmp, \tmp, \q, \qa - // result in high half -.endm - -.macro mul_twiddle_plant a, twiddle, tmp, q, qa - smulwb \tmp, \twiddle, \a - smulwt \a, \twiddle, \a - smlabt \tmp, \tmp, \q, \qa - smlabt \a, \a, \q, \qa - pkhtb \a, \a, \tmp, asr#16 -.endm - -.macro doublebutterfly_plant a0, a1, twiddle, tmp, q, qa - smulwb \tmp, \twiddle, \a1 - smulwt \a1, \twiddle, \a1 - smlabt \tmp, \tmp, \q, \qa - smlabt \a1, \a1, \q, \qa - pkhtb \tmp, \a1, \tmp, asr#16 - usub16 \a1, \a0, \tmp - uadd16 \a0, \a0, \tmp -.endm - -.macro two_doublebutterfly_plant a0, a1, a2, a3, twiddle0, twiddle1, tmp, q, qa - doublebutterfly_plant \a0, \a1, \twiddle0, \tmp, \q, \qa - doublebutterfly_plant \a2, \a3, \twiddle1, \tmp, \q, \qa -.endm - -#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i new file mode 120000 index 00000000..37838a21 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i @@ -0,0 +1 @@ +../../dilithium2/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/ntt.S b/crypto_sign/dilithium3/m4fstack/ntt.S deleted file mode 100644 index bfd5f7a4..00000000 --- a/crypto_sign/dilithium3/m4fstack/ntt.S +++ /dev/null @@ -1,402 +0,0 @@ -// based on code by: Markus Krausz (18.03.18) -// date 23.07.21: Now licensed under CC0 with permission of the authors. - -.syntax unified -#include "macros.i" - -// This code uses UMULL - which is constant time on the M4, but not on the M3 -// Make sure that this code is never used on an M3 -smlad r0,r0,r0,r0 - -// ############################## -// ########## NTT ########## -// ############################## - -//void pqcrystals_dilithium_ntt(int32_t p[N]); -.global pqcrystals_dilithium_ntt -.type pqcrystals_dilithium_ntt,%function -.align 2 -pqcrystals_dilithium_ntt: - //bind aliases - ptr_p .req R0 - ptr_zeta .req R1 - zeta .req R1 - qinv .req R2 - q .req R3 - cntr .req R4 - pol4 .req R4 - pol0 .req R5 - pol1 .req R6 - pol2 .req R7 - pol3 .req R8 - temp_h .req R9 - temp_l .req R10 - zeta0 .req R11 - zeta1 .req R12 - zeta2 .req R14 - pol5 .req R11 - pol6 .req R12 - pol7 .req R14 - - //preserve registers - push {R4-R11, R14} - - //load constants, ptr - ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed - ldr.w q, inv_ntt_asm_smull_q - - //stage 1 - 3 - .equ distance, 512 - .equ strincr, 4 - - ldr ptr_zeta, =#zetas_new332 - vldm ptr_zeta!, {s2-s8} - vmov s0, ptr_zeta - - add.w temp_l, ptr_p, #32*strincr // 32 iterations - vmov s9, temp_l - 1: - .rept 2 - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #1*distance/4] - ldr.w pol2, [ptr_p, #2*distance/4] - ldr.w pol3, [ptr_p, #3*distance/4] - ldr.w pol4, [ptr_p, #4*distance/4] - ldr.w pol5, [ptr_p, #5*distance/4] - ldr.w pol6, [ptr_p, #6*distance/4] - ldr.w pol7, [ptr_p, #7*distance/4] - - _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #1*distance/4] - str.w pol2, [ptr_p, #2*distance/4] - str.w pol3, [ptr_p, #3*distance/4] - str.w pol4, [ptr_p, #4*distance/4] - str.w pol5, [ptr_p, #5*distance/4] - str.w pol6, [ptr_p, #6*distance/4] - str.w pol7, [ptr_p, #7*distance/4] - str.w pol0, [ptr_p], #strincr - .endr - vmov temp_l, s9 - cmp.w ptr_p, temp_l - bne 1b - - sub ptr_p, #32*4 - - // stage 4 - 6 - .equ distance, 64 - add.w temp_l, ptr_p, #8*112+8*4*4 // 8 iterations - vmov s9, temp_l - 1: - add.w temp_l, ptr_p, #4*strincr // 4 iterations - vmov s10, temp_l - vmov ptr_zeta, s0 - vldm ptr_zeta!, {s2-s8} - vmov s0, ptr_zeta - 2: - .rept 2 - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #1*distance/4] - ldr.w pol2, [ptr_p, #2*distance/4] - ldr.w pol3, [ptr_p, #3*distance/4] - ldr.w pol4, [ptr_p, #4*distance/4] - ldr.w pol5, [ptr_p, #5*distance/4] - ldr.w pol6, [ptr_p, #6*distance/4] - ldr.w pol7, [ptr_p, #7*distance/4] - - _3_layer_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #1*distance/4] - str.w pol2, [ptr_p, #2*distance/4] - str.w pol3, [ptr_p, #3*distance/4] - str.w pol4, [ptr_p, #4*distance/4] - str.w pol5, [ptr_p, #5*distance/4] - str.w pol6, [ptr_p, #6*distance/4] - str.w pol7, [ptr_p, #7*distance/4] - str.w pol0, [ptr_p], #4 - .endr - vmov temp_l, s10 - cmp.w ptr_p, temp_l - bne 2b - - add.w ptr_p, #112 - vmov temp_l, s9 - cmp.w ptr_p, temp_l - bne 1b - - sub ptr_p, #4*4*8+112*8 - vmov ptr_zeta, s0 - //stage 7 and 8 - add cntr, ptr_p, #1024 // 64 iterations - 1: - ldr.w zeta1, [ptr_zeta, #4] //z128,..., z254 - ldr.w zeta2, [ptr_zeta, #8] //z129,..., z255 - ldr zeta0, [ptr_zeta], #12 //z64, ..., z127 - ldr.w pol0, [ptr_p] //1*4 - ldr.w pol1, [ptr_p, #4] - ldr.w pol2, [ptr_p, #8] - ldr.w pol3, [ptr_p, #12] - - _2_layer_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #4] - str.w pol2, [ptr_p, #8] - str.w pol3, [ptr_p, #12] - str pol0, [ptr_p], #16 - - cmp.w cntr, ptr_p - bne.w 1b - - //restore registers - pop {R4-R11, PC} - - //unbind aliases - .unreq ptr_p - .unreq ptr_zeta - .unreq qinv - .unreq q - .unreq cntr - .unreq pol0 - .unreq pol1 - .unreq pol2 - .unreq pol3 - .unreq temp_h - .unreq temp_l - .unreq zeta0 - .unreq zeta1 - .unreq zeta2 - -.ltorg -// ############################## -// ########## NTT^-1 ########## -// ############################## - -//void pqcrystals_dilithium_invntt_tomont(int32_t p[N]); -.global pqcrystals_dilithium_invntt_tomont -.type pqcrystals_dilithium_invntt_tomont,%function -.align 2 -pqcrystals_dilithium_invntt_tomont: - //bind aliases - ptr_p .req R0 - ptr_zeta .req R1 - zeta .req R1 - qinv .req R2 - q .req R3 - cntr .req R4 - pol4 .req R4 - pol0 .req R5 - pol1 .req R6 - pol2 .req R7 - pol3 .req R8 - temp_h .req R9 - temp_l .req R10 - zeta0 .req R11 - zeta1 .req R12 - zeta2 .req R14 - pol5 .req R11 - pol6 .req R12 - pol7 .req R14 - - //preserve registers - push {R4-R11, R14} - - //load constants, ptr - ldr.w qinv, inv_ntt_asm_smull_qinv //-qinv_signed - ldr.w q, inv_ntt_asm_smull_q - - //stage 1 - 3 - .equ distance, 16 - .equ strincr, 32 - - ldr ptr_zeta, =#zetas_new332inv - vldm ptr_zeta!, {s2-s8} - vmov s0, ptr_zeta - - add.w temp_l, ptr_p, #32*strincr // 32 iterations - vmov s9, temp_l - 1: - ldr.w pol4, [ptr_p, #4*distance/4] - ldr.w pol1, [ptr_p, #5*distance/4] - ldr.w pol6, [ptr_p, #6*distance/4] - ldr.w pol3, [ptr_p, #7*distance/4] - _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #1*distance/4] - ldr.w pol2, [ptr_p, #2*distance/4] - ldr.w pol3, [ptr_p, #3*distance/4] - _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #1*distance/4] - str.w pol2, [ptr_p, #2*distance/4] - str.w pol3, [ptr_p, #3*distance/4] - str.w pol4, [ptr_p, #4*distance/4] - str.w pol5, [ptr_p, #5*distance/4] - str.w pol6, [ptr_p, #6*distance/4] - str.w pol7, [ptr_p, #7*distance/4] - str.w pol0, [ptr_p], #strincr - vmov temp_l, s9 - cmp.w ptr_p, temp_l - bne.w 1b - - sub ptr_p, #32*strincr - - // stage 4 - 6 - .equ distance, 128 - .equ strincr, 256 - - // iteration 0 - movw temp_l, #4 - add.w temp_l, ptr_p, #4*256 // 4 iterations - vmov s10, temp_l - - vmov ptr_zeta, s0 - vldm ptr_zeta!, {s2-s8} - vmov s0, ptr_zeta - - 2: - ldr.w pol4, [ptr_p, #4*distance/4] - ldr.w pol1, [ptr_p, #5*distance/4] - ldr.w pol6, [ptr_p, #6*distance/4] - ldr.w pol3, [ptr_p, #7*distance/4] - _3_layer_inv_butterfly_light_fast_first pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #1*distance/4] - ldr.w pol2, [ptr_p, #2*distance/4] - ldr.w pol3, [ptr_p, #3*distance/4] - _3_layer_inv_butterfly_light_fast_second pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #1*distance/4] - str.w pol2, [ptr_p, #2*distance/4] - str.w pol3, [ptr_p, #3*distance/4] - str.w pol4, [ptr_p, #4*distance/4] - str.w pol5, [ptr_p, #5*distance/4] - str.w pol6, [ptr_p, #6*distance/4] - str.w pol7, [ptr_p, #7*distance/4] - str.w pol0, [ptr_p] - add.w ptr_p, #strincr - - vmov temp_l, s10 - cmp.w temp_l, ptr_p - bne.w 2b - - sub.w ptr_p, #4*256-4 - - // iteration 1-7 - add.w temp_l, ptr_p, #7*4 // 7 iterations - vmov s9, temp_l - 1: - add.w temp_l, ptr_p, #4*strincr // 4 iterations - vmov s10, temp_l - - vmov ptr_zeta, s0 - vldm ptr_zeta!, {s2-s8} - vmov s0, ptr_zeta - 2: - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #1*distance/4] - ldr.w pol2, [ptr_p, #2*distance/4] - ldr.w pol3, [ptr_p, #3*distance/4] - ldr.w pol4, [ptr_p, #4*distance/4] - ldr.w pol5, [ptr_p, #5*distance/4] - ldr.w pol6, [ptr_p, #6*distance/4] - ldr.w pol7, [ptr_p, #7*distance/4] - - _3_layer_inv_CT_32 pol0, pol1, pol2, pol3, pol4, pol5, pol6, pol7, s2, s3, s4, s5, s6, s7, s8, zeta, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #1*distance/4] - str.w pol2, [ptr_p, #2*distance/4] - str.w pol3, [ptr_p, #3*distance/4] - str.w pol4, [ptr_p, #4*distance/4] - str.w pol5, [ptr_p, #5*distance/4] - str.w pol6, [ptr_p, #6*distance/4] - str.w pol7, [ptr_p, #7*distance/4] - str.w pol0, [ptr_p] - add.w ptr_p, #strincr - - vmov temp_l, s10 - cmp.w ptr_p, temp_l - bne 2b - sub.w ptr_p, #4*strincr-4 - - vmov temp_l, s9 - cmp.w temp_l, ptr_p - bne 1b - - sub ptr_p, #8*4 - vmov ptr_zeta, s0 - - //stage 7 and 8 - .equ strincr, 4 - - add.w cntr, ptr_p, #64*strincr // 64 iterations - vmov s9, cntr - 1: - ldr.w zeta1, [ptr_zeta, #4] - ldr.w zeta2, [ptr_zeta, #8] - ldr zeta0, [ptr_zeta], #12 - ldr.w pol0, [ptr_p] - ldr.w pol1, [ptr_p, #256] - ldr.w pol2, [ptr_p, #512] - ldr.w pol3, [ptr_p, #768] - - _2_layer_inv_CT_32 pol0, pol1, pol2, pol3, zeta0, zeta1, zeta2, qinv, q, temp_h, temp_l - - ldr.w zeta1, [ptr_zeta, #4] - ldr.w zeta2, [ptr_zeta, #8] - ldr.w zeta0, [ptr_zeta, #12] - ldr.w cntr, [ptr_zeta], #16 - montgomery_mul_32 pol0, cntr, qinv, q, temp_h, temp_l - montgomery_mul_32 pol1, zeta1, qinv, q, temp_h, temp_l - montgomery_mul_32 pol2, zeta2, qinv, q, temp_h, temp_l - montgomery_mul_32 pol3, zeta0, qinv, q, temp_h, temp_l - - str.w pol1, [ptr_p, #256] - str.w pol2, [ptr_p, #512] - str.w pol3, [ptr_p, #768] - str pol0, [ptr_p], #strincr - - vmov cntr, s9 - cmp.w cntr, ptr_p - bne.w 1b - - //restore registers - pop {R4-R11, PC} - - //unbind aliases - .unreq ptr_p - .unreq ptr_zeta - .unreq qinv - .unreq q - .unreq cntr - .unreq pol0 - .unreq pol1 - .unreq pol2 - .unreq pol3 - .unreq temp_h - .unreq temp_l - .unreq zeta0 - .unreq zeta1 - .unreq zeta2 - -.align 2 -inv_ntt_asm_smull_qinv: -.word 0xfc7fdfff -.align 2 -inv_ntt_asm_smull_q: -.word 8380417 - -.section .rodata - -.type zetas_new332, %object -.align 2 -zetas_new332: -.word 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, 2725464, 1024112, 2706023, 95776, 3077325, 3530437, 2353451, -1079900, 3585928, -1661693, -3592148, -2537516, 3915439, -359251, -549488, -1119584, -3861115, -3043716, 3574422, -2867647, -2091905, 2619752, -2108549, 3539968, -300467, 2348700, -539299, 3119733, -2118186, -3859737, -1699267, -1643818, 3505694, -3821735, -2884855, -1399561, -3277672, 3507263, -2140649, -1600420, 3699596, 3111497, 1757237, -19422, 811944, 531354, 954230, 3881043, 2680103, 4010497, 280005, 3900724, -2556880, 2071892, -2797779, -3930395, 2091667, 3407706, -1528703, 2316500, 3817976, -3677745, -3342478, 2244091, -3041255, -2446433, -3562462, -1452451, 266997, 2434439, 3475950, -1235728, 3513181, 2176455, -3520352, -3759364, -1585221, -1197226, -3193378, -1257611, 900702, 1859098, 1939314, 909542, 819034, -4083598, 495491, -1613174, -1000202, -43260, -522500, -3190144, -655327, -3122442, -3157330, 2031748, 3207046, -3632928, -3556995, -525098, 126922, -768622, -3595838, 3412210, 342297, 286988, -983419, -2437823, 4108315, 2147896, 3437287, -3342277, 2715295, 1735879, 203044, -2967645, 2842341, 2691481, -3693493, -2590150, 1265009, -411027, 4055324, 1247620, -2477047, 2486353, 1595974, -671102, -3767016, 1250494, -1228525, 2635921, -3548272, -22981, -2994039, 1869119, -1308169, 1903435, -1050970, -381987, -1333058, 1237275, 1349076, -3318210, -1430225, 1852771, -451100, 1312455, -1430430, 3306115, -1962642, -3343383, -1279661, 1917081, 264944, -2546312, -1374803, 508951, 1500165, 777191, 3097992, 2235880, 3406031, 44288, -542412, -2831860, -1100098, -1671176, -1846953, 904516, -2584293, -3724270, 3958618, 594136, -3776993, -3724342, -2013608, 2432395, -8578, 2454455, -164721, 1653064, 1957272, 3369112, -3249728, 185531, -1207385, 2389356, -3183426, 162844, -210977, 1616392, 3014001, 759969, 810149, 1652634, -1316856, -3694233, -1799107, 189548, -3038916, 3523897, -3553272, 3866901, 269760, 3159746, 2213111, -975884, -1851402, 1717735, 472078, -2409325, -426683, 1723600, -177440, -1803090, 1910376, 1315589, -1667432, -1104333, 1341330, -260646, -3833893, 1285669, -2939036, -2235985, -1584928, -420899, -2286327, -812732, 183443, -976891, -1439742, 1612842, -3545687, -3019102, -554416, 3919660, -3881060, -48306, -1362209, -3628969, 3937738, 1400424, 3839961, -846154, 1976782 -.size zetas_new332,.-zetas_new332 - -.type zetas_new332inv, %object -.align 2 -zetas_new332inv: -.word 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894, 4193792, 4193792, -25847, 4193792, 518909, -25847, 2608894, -466468, -2680103, -3111497, -280005, 19422, -4010497, -1757237, 518909, -466468, 876248, -2680103, 2884855, -3111497, -3119733, 777960, 2091905, 359251, 2108549, 1119584, -2619752, 549488, -25847, 518909, 2608894, -466468, 777960, 876248, -237124, 876248, 2884855, -3119733, 3277672, 3859737, 1399561, 2118186, 2608894, 777960, -237124, 2091905, -2353451, 359251, -1826347, -237124, -2353451, -1826347, -3585928, -1024112, 1079900, -2725464, 4193792, 4193792, -25847, 41978, 3024400, 3975713, -1225192, 2797779, -3839961, 3628969, -1711436, 3835778, 485110, -3954267, -280005, 2797779, -2071892, -2831100, -2698859, -908040, -2292170, 539299, 1430430, -1852771, -3658785, 3512212, 1859141, -1607594, -2680103, -280005, -4010497, 715005, 1483994, -1045894, -980943, -3699596, 1316856, -759969, -955715, 3677139, 3933849, 2719610, 2108549, 539299, -2348700, 1658328, -1403403, 1775852, -2460465, -3915439, -126922, 3632928, 1067023, 3847594, 4179270, 1652689, -466468, -2680103, -3111497, -2953811, -284642, 2507426, -324139, -3881043, -1341330, -1315589, 3990128, -2137097, -4109898, 4092021, 3277672, -3699596, 1600420, 1541634, 3493410, 3487504, 2497815, 2867647, 2477047, 411027, 1654972, 1326223, -2608226, -2752209, 2091905, 2108549, -2619752, 1836700, 2945615, -1908953, 729864, 3821735, -3958618, -904516, 2080615, 1555380, -3471815, -1978758, -3585928, -3915439, 2537516, -892788, -553664, -3095038, 658596, -3530437, 1585221, -2176455, 3355482, -1783485, 2780552, -3623330, 518909, -466468, 876248, -442683, 2523147, -2847660, -3683140, 2556880, 1439742, 812732, 774207, -3168108, 1877157, 3406477, 19422, -3881043, -954230, -214686, -1182619, 2453526, -2201920, 300467, 1308169, 22981, 3614022, 2136260, 1459487, -2233803, 2884855, 3277672, 1399561, 394072, -3933227, 4136064, 156486, 2140649, 3249728, -1653064, 1596950, 633578, 2722529, -554462, 1119584, 2867647, -3574422, 1004840, 191586, 3969463, 1161373, 3592148, 1000202, 4083598, 3189243, 3561667, -3650125, 3490511, 777960, 2091905, 359251, -1829156, -3707725, -661807, 1144558, -531354, 1851402, -3159746, 1543095, -2903948, 1505516, -1500460, 3859737, 3821735, -3505694, -2413330, 3908886, -1203856, 3570263, 3043716, -2715295, -2147896, 758741, 3917553, -2414897, -1613811, -2353451, -3585928, 1079900, 990020, -719638, 2718792, 2260310, 1643818, -3097992, -508951, -783456, -2089539, 2616547, 4060031, -1024112, -3530437, -3077325, -1821861, 1920615, 3988525, 2048419, -95776, 3041255, 3677745, -971504, 2190617, 2311312, -1170082, -25847, 518909, 2608894, 1261528, -2073537, -959585, 3948120, -2071892, 3881060, 3019102, -1342633, -1115066, 3589694, -1929116, -4010497, 2556880, -3900724, 3360006, 1758630, -2306989, -1841637, -2348700, -1349076, 381987, -1699982, 3189673, 3531558, -1210546, -3111497, 19422, -1757237, 2977353, 2612035, -2718155, -1544829, 1600420, 210977, -2389356, 2052582, -2737802, 2383976, -450259, -2619752, 300467, -3539968, 1698289, -4065084, -644023, -1114140, 2537516, 3157330, 3190144, -993399, -2220524, 2920588, 252737, 876248, 2884855, -3119733, 1490985, -34731, -1212610, -3183745, -954230, 177440, 2409325, -3302554, -2390327, -2749545, 653128, 1399561, 2140649, -3507263, -3745105, -1942293, -3367121, 2734884, -3574422, 3693493, 2967645, 1393803, -2467905, 1786029, -1633410, 359251, 1119584, 549488, -2824548, -1325638, -2207625, -2601586, -3505694, 1100098, -44288, 3478676, -2457992, -1617107, 2551364, 1079900, 3592148, 1661693, 1593929, 318899, -3366475, 3118416, -3077325, -3475950, 1452451, 3772814, 1424805, -3391376, 632820, 2608894, 777960, -237124, 2062597, 4064335, 2197148, -1127864, -3900724, 1584928, -1285669, 2525341, -896437, -1915773, 1792087, -1757237, -531354, -811944, 938441, -674578, 2876837, 3959371, -3539968, 1228525, 671102, 1219592, -3853560, 2630979, -2134676, -3119733, 3859737, 2118186, -2432637, 2746655, 718593, -2353280, -3507263, 8578, 3724342, -34852, 1387945, 358956, 1604944, 549488, 3043716, 3861115, 1290746, 3208584, 2538711, -1442830, 1661693, -1939314, 1257611, -367371, -1308058, 264382, 2614173, -237124, -2353451, -1826347, 2050674, 592050, -138487, 2310528, -811944, 3553272, -189548, -2728561, -4168358, -79, 3844932, 2118186, 1643818, 1699267, 500408, 743398, 879633, -3105206, 3861115, 983419, -3412210, 712597, -23479, 3729381, -1010481, -1826347, -1024112, -2725464, -2361217, -1864453, 3850522, 2337144, 1699267, -264944, 3343383, 3842267, 4181974, -4032642, 3983585, -2725464, -95776, -2706023, 260345, 2526550, 2000777, 987079, -2706023, 1528703, 3930395, -3030761, -3082055, -2374824, 1836319 -.size zetas_new332inv,.-zetas_new332inv diff --git a/crypto_sign/dilithium3/m4fstack/ntt.S b/crypto_sign/dilithium3/m4fstack/ntt.S new file mode 120000 index 00000000..6fbceff1 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/ntt.S @@ -0,0 +1 @@ +../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/ntt.h b/crypto_sign/dilithium3/m4fstack/ntt.h deleted file mode 100644 index 731132d5..00000000 --- a/crypto_sign/dilithium3/m4fstack/ntt.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include -#include "params.h" - -#define ntt DILITHIUM_NAMESPACE(ntt) -void ntt(int32_t a[N]); - -#define invntt_tomont DILITHIUM_NAMESPACE(invntt_tomont) -void invntt_tomont(int32_t a[N]); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/ntt.h b/crypto_sign/dilithium3/m4fstack/ntt.h new file mode 120000 index 00000000..43729fef --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/ntt.h @@ -0,0 +1 @@ +../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.c b/crypto_sign/dilithium3/m4fstack/packing.c deleted file mode 100644 index 8aaff2a3..00000000 --- a/crypto_sign/dilithium3/m4fstack/packing.c +++ /dev/null @@ -1,286 +0,0 @@ -#include "params.h" -#include "packing.h" -#include "polyvec.h" -#include "poly.h" - -/************************************************* -* Name: pack_pk -* -* Description: Bit-pack public key pk = (rho, t1). -* -* Arguments: - uint8_t pk[]: output byte array -* - const uint8_t rho[]: byte array containing rho -* - const polyveck *t1: pointer to vector t1 -**************************************************/ -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], - const uint8_t rho[SEEDBYTES], - const polyveck *t1) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - pk[i] = rho[i]; - pk += SEEDBYTES; - - for(i = 0; i < K; ++i) - polyt1_pack(pk + i*POLYT1_PACKEDBYTES, &t1->vec[i]); -} - -/************************************************* -* Name: unpack_pk -* -* Description: Unpack public key pk = (rho, t1). -* -* Arguments: - const uint8_t rho[]: output byte array for rho -* - const polyveck *t1: pointer to output vector t1 -* - uint8_t pk[]: byte array containing bit-packed pk -**************************************************/ -void unpack_pk(uint8_t rho[SEEDBYTES], - polyveck *t1, - const uint8_t pk[CRYPTO_PUBLICKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = pk[i]; - pk += SEEDBYTES; - - for(i = 0; i < K; ++i) - polyt1_unpack(&t1->vec[i], pk + i*POLYT1_PACKEDBYTES); -} - -/************************************************* -* Name: pack_sk -* -* Description: Bit-pack secret key sk = (rho, tr, key, t0, s1, s2). -* -* Arguments: - uint8_t sk[]: output byte array -* - const uint8_t rho[]: byte array containing rho -* - const uint8_t tr[]: byte array containing tr -* - const uint8_t key[]: byte array containing key -* - const polyveck *t0: pointer to vector t0 -* - const polyvecl *s1: pointer to vector s1 -* - const polyveck *s2: pointer to vector s2 -**************************************************/ -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t rho[SEEDBYTES], - const uint8_t tr[TRBYTES], - const uint8_t key[SEEDBYTES], - const polyveck *t0, - const polyvecl *s1, - const polyveck *s2) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - sk[i] = rho[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - sk[i] = key[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - sk[i] = tr[i]; - sk += TRBYTES; - - for(i = 0; i < L; ++i) - polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s1->vec[i]); - sk += L*POLYETA_PACKEDBYTES; - - for(i = 0; i < K; ++i) - polyeta_pack(sk + i*POLYETA_PACKEDBYTES, &s2->vec[i]); - sk += K*POLYETA_PACKEDBYTES; - - for(i = 0; i < K; ++i) - polyt0_pack(sk + i*POLYT0_PACKEDBYTES, &t0->vec[i]); -} - -/************************************************* -* Name: unpack_sk -* -* Description: Unpack secret key sk = (rho, tr, key, t0, s1, s2). -* -* Arguments: - const uint8_t rho[]: output byte array for rho -* - const uint8_t tr[]: output byte array for tr -* - const uint8_t key[]: output byte array for key -* - const polyveck *t0: pointer to output vector t0 -* - const polyvecl *s1: pointer to output vector s1 -* - const polyveck *s2: pointer to output vector s2 -* - uint8_t sk[]: byte array containing bit-packed sk -**************************************************/ -void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - polyveck *t0, - smallpoly s1[L], - smallpoly s2[K], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - key[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - tr[i] = sk[i]; - sk += TRBYTES; - - for(i=0; i < L; ++i) - small_polyeta_unpack(&s1[i], sk + i*POLYETA_PACKEDBYTES); - sk += L*POLYETA_PACKEDBYTES; - - for(i=0; i < K; ++i) - small_polyeta_unpack(&s2[i], sk + i*POLYETA_PACKEDBYTES); - sk += K*POLYETA_PACKEDBYTES; - - for(i=0; i < K; ++i) - polyt0_unpack(&t0->vec[i], sk + i*POLYT0_PACKEDBYTES); -} - - -/************************************************* -* Name: pack_sig -* -* Description: Bit-pack signature sig = (c, z, h). -* -* Arguments: - uint8_t sig[]: output byte array -* - const uint8_t *c: pointer to challenge hash length SEEDBYTES -* - const polyvecl *z: pointer to vector z -* - const polyveck *h: pointer to hint vector h -**************************************************/ -void pack_sig(uint8_t sig[CRYPTO_BYTES], - const uint8_t c[CTILDEBYTES], - const polyvecl *z, - const polyveck *h) -{ - unsigned int i, j, k; - - for(i=0; i < CTILDEBYTES; ++i) - sig[i] = c[i]; - sig += CTILDEBYTES; - - for(i = 0; i < L; ++i) - polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); - sig += L*POLYZ_PACKEDBYTES; - - /* Encode h */ - for(i = 0; i < OMEGA + K; ++i) - sig[i] = 0; - - k = 0; - for(i = 0; i < K; ++i) { - for(j = 0; j < N; ++j) - if(h->vec[i].coeffs[j] != 0) - sig[k++] = j; - - sig[OMEGA + i] = k; - } -} - -void pack_sig_c(uint8_t sig[CRYPTO_BYTES], - const uint8_t c[CTILDEBYTES]) -{ - unsigned int i; - - for(i=0; i < CTILDEBYTES; ++i) - sig[i] = c[i]; - sig += CTILDEBYTES; -} - -void pack_sig_z(uint8_t sig[CRYPTO_BYTES], - const polyvecl *z) -{ - unsigned int i; - sig += CTILDEBYTES; - for(i = 0; i < L; ++i) - polyz_pack(sig + i*POLYZ_PACKEDBYTES, &z->vec[i]); -} - - -void pack_sig_h(unsigned char sig[CRYPTO_BYTES], - const poly *h_elem, - const unsigned int idx, - unsigned int *hints_written) -{ - sig += CTILDEBYTES; - sig += L*POLYZ_PACKEDBYTES; - - // Encode h - for (unsigned int j = 0; j < N; j++) { - if (h_elem->coeffs[j] != 0) { - sig[*hints_written] = (uint8_t)j; - (*hints_written)++; - } - } - sig[OMEGA + idx] = (uint8_t)*hints_written; -} - -void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], - unsigned int *hints_written) { - sig += CTILDEBYTES; - sig += L * POLYZ_PACKEDBYTES; - while (*hints_written < OMEGA) { - sig[*hints_written] = 0; - (*hints_written)++; - } -} - -/************************************************* -* Name: unpack_sig -* -* Description: Unpack signature sig = (c, z, h). -* -* Arguments: - uint8_t *c: pointer to output challenge hash -* - polyvecl *z: pointer to output vector z -* - polyveck *h: pointer to output hint vector h -* - const uint8_t sig[]: byte array containing -* bit-packed signature -* -* Returns 1 in case of malformed signature; otherwise 0. -**************************************************/ -int unpack_sig(uint8_t c[CTILDEBYTES], - polyvecl *z, - polyveck *h, - const uint8_t sig[CRYPTO_BYTES]) -{ - unsigned int i, j, k; - - for(i = 0; i < CTILDEBYTES; ++i) - c[i] = sig[i]; - sig += CTILDEBYTES; - - for(i = 0; i < L; ++i) - polyz_unpack(&z->vec[i], sig + i*POLYZ_PACKEDBYTES); - sig += L*POLYZ_PACKEDBYTES; - - /* Decode h */ - k = 0; - for(i = 0; i < K; ++i) { - for(j = 0; j < N; ++j) - h->vec[i].coeffs[j] = 0; - - if(sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) - return 1; - - for(j = k; j < sig[OMEGA + i]; ++j) { - /* Coefficients are ordered for strong unforgeability */ - if(j > k && sig[j] <= sig[j-1]) return 1; - h->vec[i].coeffs[sig[j]] = 1; - } - - k = sig[OMEGA + i]; - } - - /* Extra indices are zero for strong unforgeability */ - for(j = k; j < OMEGA; ++j) - if(sig[j]) - return 1; - - return 0; -} \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.c b/crypto_sign/dilithium3/m4fstack/packing.c new file mode 120000 index 00000000..b41782c2 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/packing.c @@ -0,0 +1 @@ +../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.h b/crypto_sign/dilithium3/m4fstack/packing.h deleted file mode 100644 index 35553545..00000000 --- a/crypto_sign/dilithium3/m4fstack/packing.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef PACKING_H -#define PACKING_H - -#include -#include "params.h" -#include "polyvec.h" -#include "smallpoly.h" - -#define pack_pk DILITHIUM_NAMESPACE(pack_pk) -void pack_pk(uint8_t pk[CRYPTO_PUBLICKEYBYTES], const uint8_t rho[SEEDBYTES], const polyveck *t1); - -#define pack_sk DILITHIUM_NAMESPACE(pack_sk) -void pack_sk(uint8_t sk[CRYPTO_SECRETKEYBYTES], - const uint8_t rho[SEEDBYTES], - const uint8_t tr[TRBYTES], - const uint8_t key[SEEDBYTES], - const polyveck *t0, - const polyvecl *s1, - const polyveck *s2); - -#define pack_sig DILITHIUM_NAMESPACE(pack_sig) -void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const polyvecl *z, const polyveck *h); - -#define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) -void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); - -#define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) -void unpack_sk(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - polyveck *t0, - smallpoly s1[L], - smallpoly s2[K], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - -#define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) -int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); - -#define pack_sig_c DILITHIUM_NAMESPACE(pack_sig_c) -void pack_sig_c(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES]); - -#define pack_sig_z DILITHIUM_NAMESPACE(pack_sig_z) -void pack_sig_z(uint8_t sig[CRYPTO_BYTES], const polyvecl *z); - -#define pack_sig_h DILITHIUM_NAMESPACE(pack_sig_h) -void pack_sig_h(unsigned char sig[CRYPTO_BYTES], - const poly *h_elem, - const unsigned int idx, - unsigned int *hints_written); - -#define pack_sig_h_zero DILITHIUM_NAMESPACE(pack_sig_h_zero) -void pack_sig_h_zero(unsigned char sig[CRYPTO_BYTES], - unsigned int *hints_written); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/packing.h b/crypto_sign/dilithium3/m4fstack/packing.h new file mode 120000 index 00000000..ba1a6b3b --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/packing.h @@ -0,0 +1 @@ +../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/params.h b/crypto_sign/dilithium3/m4fstack/params.h deleted file mode 100644 index 507de467..00000000 --- a/crypto_sign/dilithium3/m4fstack/params.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef PARAMS_H -#define PARAMS_H - -#include "config.h" - -#define DILITHIUM_NAMESPACE(s) pqcrystals_dilithium_##s - - -#define SEEDBYTES 32 -#define CRHBYTES 64 -#define TRBYTES 64 -#define RNDBYTES 32 -#define N 256 -#define Q 8380417 -#define D 13 -#define ROOT_OF_UNITY 1753 - -#if DILITHIUM_MODE == 2 -#define K 4 -#define L 4 -#define ETA 2 -#define TAU 39 -#define BETA 78 -#define GAMMA1 (1 << 17) -#define GAMMA2 ((Q-1)/88) -#define OMEGA 80 -#define CTILDEBYTES 32 - -#elif DILITHIUM_MODE == 3 -#define K 6 -#define L 5 -#define ETA 4 -#define TAU 49 -#define BETA 196 -#define GAMMA1 (1 << 19) -#define GAMMA2 ((Q-1)/32) -#define OMEGA 55 -#define CTILDEBYTES 48 - -#elif DILITHIUM_MODE == 5 -#define K 8 -#define L 7 -#define ETA 2 -#define TAU 60 -#define BETA 120 -#define GAMMA1 (1 << 19) -#define GAMMA2 ((Q-1)/32) -#define OMEGA 75 -#define CTILDEBYTES 64 - -#endif - -#define POLYT1_PACKEDBYTES 320 -#define POLYT0_PACKEDBYTES 416 -#define POLYVECH_PACKEDBYTES (OMEGA + K) - -#if GAMMA1 == (1 << 17) -#define POLYZ_PACKEDBYTES 576 -#elif GAMMA1 == (1 << 19) -#define POLYZ_PACKEDBYTES 640 -#endif - -#if GAMMA2 == (Q-1)/88 -#define POLYW1_PACKEDBYTES 192 -#elif GAMMA2 == (Q-1)/32 -#define POLYW1_PACKEDBYTES 128 -#endif - -#if ETA == 2 -#define POLYETA_PACKEDBYTES 96 -#elif ETA == 4 -#define POLYETA_PACKEDBYTES 128 -#endif - -#define CRYPTO_PUBLICKEYBYTES (SEEDBYTES + K*POLYT1_PACKEDBYTES) -#define CRYPTO_SECRETKEYBYTES (2*SEEDBYTES \ - + TRBYTES \ - + L*POLYETA_PACKEDBYTES \ - + K*POLYETA_PACKEDBYTES \ - + K*POLYT0_PACKEDBYTES) -#define CRYPTO_BYTES (CTILDEBYTES + L*POLYZ_PACKEDBYTES + POLYVECH_PACKEDBYTES) - -#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/params.h b/crypto_sign/dilithium3/m4fstack/params.h new file mode 120000 index 00000000..a6a4d8b6 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/params.h @@ -0,0 +1 @@ +../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h deleted file mode 100644 index 2647a110..00000000 --- a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef POINTWISE_MONT_H -#define POINTWISE_MONT_H - -#include -#include "params.h" - - -#define asm_pointwise_montgomery DILITHIUM_NAMESPACE(asm_pointwise_montgomery) -void asm_pointwise_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); -#define asm_pointwise_acc_montgomery DILITHIUM_NAMESPACE(asm_pointwise_acc_montgomery) -void asm_pointwise_acc_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h new file mode 120000 index 00000000..0a6f8b9f --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h @@ -0,0 +1 @@ +../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s deleted file mode 100644 index e21125d7..00000000 --- a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s +++ /dev/null @@ -1,128 +0,0 @@ -.syntax unified -.thumb - -.macro montgomery_multiplication res, pa, pb, q, qinv - smull \pa, \res, \pa, \pb - mul \pb, \pa, \qinv - smlal \pa, \res, \pb, \q -.endm - - -// void asm_pointwise_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); -.global pqcrystals_dilithium_asm_pointwise_montgomery -.type pqcrystals_dilithium_asm_pointwise_montgomery,%function -.align 2 -pqcrystals_dilithium_asm_pointwise_montgomery: - push.w {r4-r11, r14} - c_ptr .req r0 - a_ptr .req r1 - b_ptr .req r2 - qinv .req r3 - q .req r4 - pa0 .req r5 - pa1 .req r6 - pa2 .req r7 - pb0 .req r8 - pb1 .req r9 - pb2 .req r10 - tmp0 .req r11 - ctr .req r12 - res .req r14 - - movw qinv, #:lower16:0xfc7fdfff - movt qinv, #:upper16:0xfc7fdfff - movw q, #0xE001 - movt q, #0x7F - - - // 85x3 = 255 coefficients - movw ctr, #85 - 1: - ldr.w pa1, [a_ptr, #4] - ldr.w pa2, [a_ptr, #8] - ldr pa0, [a_ptr], #12 - ldr.w pb1, [b_ptr, #4] - ldr.w pb2, [b_ptr, #8] - ldr pb0, [b_ptr], #12 - - montgomery_multiplication res, pa0, pb0, q, qinv - str res, [c_ptr], #4 - montgomery_multiplication res, pa1, pb1, q, qinv - str res, [c_ptr], #4 - montgomery_multiplication res, pa2, pb2, q, qinv - str res, [c_ptr], #4 - subs ctr, #1 - bne.w 1b - - // final coefficient - ldr.w pa0, [a_ptr] - ldr.w pb0, [b_ptr] - montgomery_multiplication res, pa0, pb0, q, qinv - str.w res, [c_ptr] - - pop.w {r4-r11, pc} -.size pqcrystals_dilithium_asm_pointwise_montgomery, .-pqcrystals_dilithium_asm_pointwise_montgomery - -// void asm_pointwise_acc_montgomery(int32_t c[N], const int32_t a[N], const int32_t b[N]); -.global pqcrystals_dilithium_asm_pointwise_acc_montgomery -.type pqcrystals_dilithium_asm_pointwise_acc_montgomery,%function -.align 2 -pqcrystals_dilithium_asm_pointwise_acc_montgomery: - push.w {r4-r11, r14} - c_ptr .req r0 - a_ptr .req r1 - b_ptr .req r2 - qinv .req r3 - q .req r4 - pa0 .req r5 - pa1 .req r6 - pa2 .req r7 - pb0 .req r8 - pb1 .req r9 - pb2 .req r10 - tmp0 .req r11 - ctr .req r12 - res .req r14 - - movw qinv, #:lower16:0xfc7fdfff - movt qinv, #:upper16:0xfc7fdfff - movw q, #0xE001 - movt q, #0x7F - - - // 85x3 = 255 coefficients - movw ctr, #85 - 1: - ldr.w pa1, [a_ptr, #4] - ldr.w pa2, [a_ptr, #8] - ldr pa0, [a_ptr], #12 - ldr.w pb1, [b_ptr, #4] - ldr.w pb2, [b_ptr, #8] - ldr pb0, [b_ptr], #12 - - montgomery_multiplication res, pa0, pb0, q, qinv - montgomery_multiplication pa0, pa1, pb1, q, qinv - montgomery_multiplication pa1, pa2, pb2, q, qinv - - ldr.w pb0, [c_ptr] - ldr.w pb1, [c_ptr, #4] - ldr.w pb2, [c_ptr, #8] - add.w res, res, pb0 - str res, [c_ptr], #12 - add.w pa0, pa0, pb1 - str pa0, [c_ptr, #-8] - add.w pa1, pa1, pb2 - str pa1, [c_ptr, #-4] - subs ctr, #1 - bne.w 1b - - // final coefficient - ldr.w pa0, [a_ptr] - ldr.w pb0, [b_ptr] - ldr.w pa1, [c_ptr] - montgomery_multiplication res, pa0, pb0, q, qinv - add.w res, res, pa1 - str.w res, [c_ptr] - - pop.w {r4-r11, pc} -.size pqcrystals_dilithium_asm_pointwise_acc_montgomery, .-pqcrystals_dilithium_asm_pointwise_acc_montgomery diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s new file mode 120000 index 00000000..c4ddb96c --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s @@ -0,0 +1 @@ +../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/poly.c b/crypto_sign/dilithium3/m4fstack/poly.c deleted file mode 100644 index 0d40fda3..00000000 --- a/crypto_sign/dilithium3/m4fstack/poly.c +++ /dev/null @@ -1,851 +0,0 @@ -#include -#include "params.h" -#include "poly.h" -#include "vector.h" -#include "ntt.h" -#include "pointwise_mont.h" -#include "rounding.h" -#include "symmetric.h" - -#include -#include "hal.h" - -#ifdef DBENCH -#include "test/cpucycles.h" -extern const uint64_t timing_overhead; -extern uint64_t *tred, *tadd, *tmul, *tround, *tsample, *tpack; -#define DBENCH_START() uint64_t time = cpucycles() -#define DBENCH_STOP(t) t += cpucycles() - time - timing_overhead -#else -#define DBENCH_START() -#define DBENCH_STOP(t) -#endif - -/************************************************* -* Name: poly_reduce -* -* Description: Inplace reduction of all coefficients of polynomial to -* representative in [-6283009,6283007]. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_reduce(poly *a) { - asm_reduce32(a->coeffs); -} - -/************************************************* -* Name: poly_caddq -* -* Description: For all coefficients of in/out polynomial add Q if -* coefficient is negative. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_caddq(poly *a) { - asm_caddq(a->coeffs); -} - -#if 0 -/************************************************* -* Name: poly_freeze -* -* Description: Inplace reduction of all coefficients of polynomial to -* standard representatives. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_freeze(poly *a) { - asm_freeze(a->coeffs); -} -#endif - -/************************************************* -* Name: poly_add -* -* Description: Add polynomials. No modular reduction is performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first summand -* - const poly *b: pointer to second summand -**************************************************/ -void poly_add(poly *c, const poly *a, const poly *b) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_sub -* -* Description: Subtract polynomials. No modular reduction is -* performed. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial to be -* subtraced from first input polynomial -**************************************************/ -void poly_sub(poly *c, const poly *a, const poly *b) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - c->coeffs[i] = a->coeffs[i] - b->coeffs[i]; - - DBENCH_STOP(*tadd); -} - -/************************************************* -* Name: poly_shiftl -* -* Description: Multiply polynomial by 2^D without modular reduction. Assumes -* input coefficients to be less than 2^{31-D} in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_shiftl(poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a->coeffs[i] <<= D; - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_ntt -* -* Description: Inplace forward NTT. Coefficients can grow by -* 8*Q in absolute value. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_ntt(poly *a) { - DBENCH_START(); - - ntt(a->coeffs); - - DBENCH_STOP(*tmul); -} - - -/************************************************* -* Name: poly_invntt_tomont -* -* Description: Inplace inverse NTT and multiplication by 2^{32}. -* Input coefficients need to be less than Q in absolute -* value and output coefficients are again bounded by Q. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_invntt_tomont(poly *a) { - DBENCH_START(); - - invntt_tomont(a->coeffs); - - DBENCH_STOP(*tmul); -} - - -/************************************************* -* Name: poly_pointwise_montgomery -* -* Description: Pointwise multiplication of polynomials in NTT domain -* representation and multiplication of resulting polynomial -* by 2^{-32}. -* -* Arguments: - poly *c: pointer to output polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial -**************************************************/ -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b) { - DBENCH_START(); - - asm_pointwise_montgomery(c->coeffs, a->coeffs, b->coeffs); - - DBENCH_STOP(*tmul); -} - -/************************************************* -* Name: poly_pointwise_acc_montgomery -* -* Description: Pointwise multiplication of polynomials in NTT domain -* representation, multiplication of resulting polynomial -* by 2^{-32} and accumulate. -* -* Arguments: - poly *c: pointer to output (accumulating) polynomial -* - const poly *a: pointer to first input polynomial -* - const poly *b: pointer to second input polynomial -**************************************************/ -void poly_pointwise_acc_montgomery(poly *c, const poly *a, const poly *b) { - DBENCH_START(); - - asm_pointwise_acc_montgomery(c->coeffs, a->coeffs, b->coeffs); - - DBENCH_STOP(*tmul); -} - - -/************************************************* -* Name: poly_power2round -* -* Description: For all coefficients c of the input polynomial, -* compute c0, c1 such that c mod Q = c1*2^D + c0 -* with -2^{D-1} < c0 <= 2^{D-1}. Assumes coefficients to be -* standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_power2round(poly *a1, poly *a0, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a1->coeffs[i] = power2round(&a0->coeffs[i], a->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_decompose -* -* Description: For all coefficients c of the input polynomial, -* compute high and low bits c0, c1 such c mod Q = c1*ALPHA + c0 -* with -ALPHA/2 < c0 <= ALPHA/2 except c1 = (Q-1)/ALPHA where we -* set c1 = 0 and -ALPHA/2 <= c0 = c mod Q - Q < 0. -* Assumes coefficients to be standard representatives. -* -* Arguments: - poly *a1: pointer to output polynomial with coefficients c1 -* - poly *a0: pointer to output polynomial with coefficients c0 -* - const poly *a: pointer to input polynomial -**************************************************/ -void poly_decompose(poly *a1, poly *a0, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - a1->coeffs[i] = decompose(&a0->coeffs[i], a->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_make_hint -* -* Description: Compute hint polynomial. The coefficients of which indicate -* whether the low bits of the corresponding coefficient of -* the input polynomial overflow into the high bits. -* -* Arguments: - poly *h: pointer to output hint polynomial -* - const poly *a0: pointer to low part of input polynomial -* - const poly *a1: pointer to high part of input polynomial -* -* Returns number of 1 bits. -**************************************************/ -unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1) { - unsigned int i, s = 0; - DBENCH_START(); - - for(i = 0; i < N; ++i) { - h->coeffs[i] = make_hint(a0->coeffs[i], a1->coeffs[i]); - s += h->coeffs[i]; - } - - DBENCH_STOP(*tround); - return s; -} - -/************************************************* -* Name: poly_use_hint -* -* Description: Use hint polynomial to correct the high bits of a polynomial. -* -* Arguments: - poly *b: pointer to output polynomial with corrected high bits -* - const poly *a: pointer to input polynomial -* - const poly *h: pointer to input hint polynomial -**************************************************/ -void poly_use_hint(poly *b, const poly *a, const poly *h) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N; ++i) - b->coeffs[i] = use_hint(a->coeffs[i], h->coeffs[i]); - - DBENCH_STOP(*tround); -} - -/************************************************* -* Name: poly_chknorm -* -* Description: Check infinity norm of polynomial against given bound. -* Assumes input coefficients were reduced by reduce32(). -* -* Arguments: - const poly *a: pointer to polynomial -* - int32_t B: norm bound -* -* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise. -**************************************************/ -int poly_chknorm(const poly *a, int32_t B) { - unsigned int i; - int32_t t; - DBENCH_START(); - - if(B > (Q-1)/8) - return 1; - - /* It is ok to leak which coefficient violates the bound since - the probability for each coefficient is independent of secret - data but we must not leak the sign of the centralized representative. */ - for(i = 0; i < N; ++i) { - /* Absolute value */ - t = a->coeffs[i] >> 31; - t = a->coeffs[i] - (t & 2*a->coeffs[i]); - - if(t >= B) { - DBENCH_STOP(*tsample); - return 1; - } - } - - DBENCH_STOP(*tsample); - return 0; -} - -/************************************************* -* Name: poly_uniform -* -* Description: Sample polynomial with uniformly random coefficients -* in [0,Q-1] by performing rejection sampling on the -* output stream of SHAKE256(seed|nonce). -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length SEEDBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -#define POLY_UNIFORM_NBLOCKS ((768 + STREAM128_BLOCKBYTES - 1)/STREAM128_BLOCKBYTES) -void poly_uniform(poly *a, - const uint8_t seed[SEEDBYTES], - uint16_t nonce) -{ - unsigned int i, ctr, off; - unsigned int buflen = POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_NBLOCKS*STREAM128_BLOCKBYTES + 2]; - stream128_state state; - - stream128_init(&state, seed, nonce); - stream128_squeezeblocks(buf, POLY_UNIFORM_NBLOCKS, &state); - - ctr = asm_rej_uniform(a->coeffs, N, buf, buflen); - - while(ctr < N) { - off = buflen % 3; - for(i = 0; i < off; ++i) - buf[i] = buf[buflen - off + i]; - - stream128_squeezeblocks(buf + off, 1, &state); - buflen = STREAM128_BLOCKBYTES + off; - ctr += asm_rej_uniform(a->coeffs + ctr, N - ctr, buf, buflen); - } -} - -/************************************************* -* Name: rej_eta -* -* Description: Sample uniformly random coefficients in [-ETA, ETA] by -* performing rejection sampling on array of random bytes. -* -* Arguments: - int32_t *a: pointer to output array (allocated) -* - unsigned int len: number of coefficients to be sampled -* - const uint8_t *buf: array of random bytes -* - unsigned int buflen: length of array of random bytes -* -* Returns number of sampled coefficients. Can be smaller than len if not enough -* random bytes were given. -**************************************************/ -static unsigned int rej_eta(int32_t *a, - unsigned int len, - const uint8_t *buf, - unsigned int buflen) -{ - unsigned int ctr, pos; - uint32_t t0, t1; - DBENCH_START(); - - ctr = pos = 0; - while(ctr < len && pos < buflen) { - t0 = buf[pos] & 0x0F; - t1 = buf[pos++] >> 4; - -#if ETA == 2 - if(t0 < 15) { - t0 = t0 - (205*t0 >> 10)*5; - a[ctr++] = 2 - t0; - } - if(t1 < 15 && ctr < len) { - t1 = t1 - (205*t1 >> 10)*5; - a[ctr++] = 2 - t1; - } -#elif ETA == 4 - if(t0 < 9) - a[ctr++] = 4 - t0; - if(t1 < 9 && ctr < len) - a[ctr++] = 4 - t1; -#endif - } - - DBENCH_STOP(*tsample); - return ctr; -} - -/************************************************* -* Name: poly_uniform_eta -* -* Description: Sample polynomial with uniformly random coefficients -* in [-ETA,ETA] by performing rejection sampling on the -* output stream from SHAKE256(seed|nonce). -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length SEEDBYTES -* - uint16_t nonce: 2-byte nonce -**************************************************/ -#if ETA == 2 -#define POLY_UNIFORM_ETA_NBLOCKS ((136 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -#elif ETA == 4 -#define POLY_UNIFORM_ETA_NBLOCKS ((227 + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -#endif -void poly_uniform_eta(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce) { - unsigned int ctr; - unsigned int buflen = POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES; - uint8_t buf[POLY_UNIFORM_ETA_NBLOCKS * STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_ETA_NBLOCKS, &state); - - ctr = rej_eta(a->coeffs, N, buf, buflen); - - while(ctr < N) { - stream256_squeezeblocks(buf, 1, &state); - ctr += rej_eta(a->coeffs + ctr, N - ctr, buf, STREAM256_BLOCKBYTES); - } -} - -/************************************************* -* Name: poly_uniform_gamma1m1 -* -* Description: Sample polynomial with uniformly random coefficients -* in [-(GAMMA1 - 1), GAMMA1] by unpacking output stream -* of SHAKE256(seed|nonce). -* -* Arguments: - poly *a: pointer to output polynomial -* - const uint8_t seed[]: byte array with seed of length CRHBYTES -* - uint16_t nonce: 16-bit nonce -**************************************************/ -#define POLY_UNIFORM_GAMMA1_NBLOCKS ((POLYZ_PACKEDBYTES + STREAM256_BLOCKBYTES - 1)/STREAM256_BLOCKBYTES) -void poly_uniform_gamma1(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce) -{ - uint8_t buf[POLY_UNIFORM_GAMMA1_NBLOCKS*STREAM256_BLOCKBYTES]; - stream256_state state; - - stream256_init(&state, seed, nonce); - stream256_squeezeblocks(buf, POLY_UNIFORM_GAMMA1_NBLOCKS, &state); - polyz_unpack(a, buf); -} - -/************************************************* -* Name: challenge -* -* Description: Implementation of H. Samples polynomial with TAU nonzero -* coefficients in {-1,1} using the output stream of -* SHAKE256(seed). -* -* Arguments: - poly *c: pointer to output polynomial -* - const uint8_t mu[]: byte array containing seed of length SEEDBYTES -**************************************************/ -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { - unsigned int i, b, pos; - uint64_t signs; - uint8_t buf[SHAKE256_RATE]; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, seed, SEEDBYTES); - shake256_inc_finalize(&state); - shake256_inc_squeezeblocks(buf, 1, &state); - - signs = 0; - for(i = 0; i < 8; ++i) - signs |= (uint64_t)buf[i] << 8*i; - pos = 8; - - for(i = 0; i < N; ++i) - c->coeffs[i] = 0; - for(i = N-TAU; i < N; ++i) { - do { - if(pos >= SHAKE256_RATE) { - shake256_inc_squeezeblocks(buf, 1, &state); - pos = 0; - } - - b = buf[pos++]; - } while(b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1 - 2*(signs & 1); - signs >>= 1; - } -} - -/************************************************* -* Name: polyeta_pack -* -* Description: Bit-pack polynomial with coefficients in [-ETA,ETA]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYETA_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyeta_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint8_t t[8]; - DBENCH_START(); - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - t[0] = ETA - a->coeffs[8*i+0]; - t[1] = ETA - a->coeffs[8*i+1]; - t[2] = ETA - a->coeffs[8*i+2]; - t[3] = ETA - a->coeffs[8*i+3]; - t[4] = ETA - a->coeffs[8*i+4]; - t[5] = ETA - a->coeffs[8*i+5]; - t[6] = ETA - a->coeffs[8*i+6]; - t[7] = ETA - a->coeffs[8*i+7]; - - r[3*i+0] = (t[0] >> 0) | (t[1] << 3) | (t[2] << 6); - r[3*i+1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[3*i+2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - t[0] = ETA - a->coeffs[2*i+0]; - t[1] = ETA - a->coeffs[2*i+1]; - r[i] = t[0] | (t[1] << 4); - } -#endif - - DBENCH_STOP(*tpack); -} - - -/************************************************* -* Name: polyt1_pack -* -* Description: Bit-pack polynomial t1 with coefficients fitting in 10 bits. -* Input coefficients are assumed to be standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt1_pack(uint8_t *r, const poly *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r[5*i+0] = (a->coeffs[4*i+0] >> 0); - r[5*i+1] = (a->coeffs[4*i+0] >> 8) | (a->coeffs[4*i+1] << 2); - r[5*i+2] = (a->coeffs[4*i+1] >> 6) | (a->coeffs[4*i+2] << 4); - r[5*i+3] = (a->coeffs[4*i+2] >> 4) | (a->coeffs[4*i+3] << 6); - r[5*i+4] = (a->coeffs[4*i+3] >> 2); - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt1_unpack -* -* Description: Unpack polynomial t1 with 10-bit coefficients. -* Output coefficients are standard representatives. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt1_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/4; ++i) { - r->coeffs[4*i+0] = ((a[5*i+0] >> 0) | ((uint32_t)a[5*i+1] << 8)) & 0x3FF; - r->coeffs[4*i+1] = ((a[5*i+1] >> 2) | ((uint32_t)a[5*i+2] << 6)) & 0x3FF; - r->coeffs[4*i+2] = ((a[5*i+2] >> 4) | ((uint32_t)a[5*i+3] << 4)) & 0x3FF; - r->coeffs[4*i+3] = ((a[5*i+3] >> 6) | ((uint32_t)a[5*i+4] << 2)) & 0x3FF; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_pack -* -* Description: Bit-pack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYT0_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyt0_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint32_t t[8]; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - t[0] = (1 << (D-1)) - a->coeffs[8*i+0]; - t[1] = (1 << (D-1)) - a->coeffs[8*i+1]; - t[2] = (1 << (D-1)) - a->coeffs[8*i+2]; - t[3] = (1 << (D-1)) - a->coeffs[8*i+3]; - t[4] = (1 << (D-1)) - a->coeffs[8*i+4]; - t[5] = (1 << (D-1)) - a->coeffs[8*i+5]; - t[6] = (1 << (D-1)) - a->coeffs[8*i+6]; - t[7] = (1 << (D-1)) - a->coeffs[8*i+7]; - - r[13*i+ 0] = t[0]; - r[13*i+ 1] = t[0] >> 8; - r[13*i+ 1] |= t[1] << 5; - r[13*i+ 2] = t[1] >> 3; - r[13*i+ 3] = t[1] >> 11; - r[13*i+ 3] |= t[2] << 2; - r[13*i+ 4] = t[2] >> 6; - r[13*i+ 4] |= t[3] << 7; - r[13*i+ 5] = t[3] >> 1; - r[13*i+ 6] = t[3] >> 9; - r[13*i+ 6] |= t[4] << 4; - r[13*i+ 7] = t[4] >> 4; - r[13*i+ 8] = t[4] >> 12; - r[13*i+ 8] |= t[5] << 1; - r[13*i+ 9] = t[5] >> 7; - r[13*i+ 9] |= t[6] << 6; - r[13*i+10] = t[6] >> 2; - r[13*i+11] = t[6] >> 10; - r[13*i+11] |= t[7] << 3; - r[13*i+12] = t[7] >> 5; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyt0_unpack -* -* Description: Unpack polynomial t0 with coefficients in ]-2^{D-1}, 2^{D-1}]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyt0_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = a[13*i+0]; - r->coeffs[8*i+0] |= (uint32_t)a[13*i+1] << 8; - r->coeffs[8*i+0] &= 0x1FFF; - - r->coeffs[8*i+1] = a[13*i+1] >> 5; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+2] << 3; - r->coeffs[8*i+1] |= (uint32_t)a[13*i+3] << 11; - r->coeffs[8*i+1] &= 0x1FFF; - - r->coeffs[8*i+2] = a[13*i+3] >> 2; - r->coeffs[8*i+2] |= (uint32_t)a[13*i+4] << 6; - r->coeffs[8*i+2] &= 0x1FFF; - - r->coeffs[8*i+3] = a[13*i+4] >> 7; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+5] << 1; - r->coeffs[8*i+3] |= (uint32_t)a[13*i+6] << 9; - r->coeffs[8*i+3] &= 0x1FFF; - - r->coeffs[8*i+4] = a[13*i+6] >> 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+7] << 4; - r->coeffs[8*i+4] |= (uint32_t)a[13*i+8] << 12; - r->coeffs[8*i+4] &= 0x1FFF; - - r->coeffs[8*i+5] = a[13*i+8] >> 1; - r->coeffs[8*i+5] |= (uint32_t)a[13*i+9] << 7; - r->coeffs[8*i+5] &= 0x1FFF; - - r->coeffs[8*i+6] = a[13*i+9] >> 6; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+10] << 2; - r->coeffs[8*i+6] |= (uint32_t)a[13*i+11] << 10; - r->coeffs[8*i+6] &= 0x1FFF; - - r->coeffs[8*i+7] = a[13*i+11] >> 3; - r->coeffs[8*i+7] |= (uint32_t)a[13*i+12] << 5; - r->coeffs[8*i+7] &= 0x1FFF; - - r->coeffs[8*i+0] = (1 << (D-1)) - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = (1 << (D-1)) - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = (1 << (D-1)) - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = (1 << (D-1)) - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = (1 << (D-1)) - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = (1 << (D-1)) - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = (1 << (D-1)) - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = (1 << (D-1)) - r->coeffs[8*i+7]; - } - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_pack -* -* Description: Bit-pack polynomial with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYZ_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyz_pack(uint8_t *r, const poly *a) { - unsigned int i; - uint32_t t[4]; - DBENCH_START(); - -#if GAMMA1 == (1 << 17) - for(i = 0; i < N/4; ++i) { - t[0] = GAMMA1 - a->coeffs[4*i+0]; - t[1] = GAMMA1 - a->coeffs[4*i+1]; - t[2] = GAMMA1 - a->coeffs[4*i+2]; - t[3] = GAMMA1 - a->coeffs[4*i+3]; - - r[9*i+0] = t[0]; - r[9*i+1] = t[0] >> 8; - r[9*i+2] = t[0] >> 16; - r[9*i+2] |= t[1] << 2; - r[9*i+3] = t[1] >> 6; - r[9*i+4] = t[1] >> 14; - r[9*i+4] |= t[2] << 4; - r[9*i+5] = t[2] >> 4; - r[9*i+6] = t[2] >> 12; - r[9*i+6] |= t[3] << 6; - r[9*i+7] = t[3] >> 2; - r[9*i+8] = t[3] >> 10; - } -#elif GAMMA1 == (1 << 19) - for(i = 0; i < N/2; ++i) { - t[0] = GAMMA1 - a->coeffs[2*i+0]; - t[1] = GAMMA1 - a->coeffs[2*i+1]; - - r[5*i+0] = t[0]; - r[5*i+1] = t[0] >> 8; - r[5*i+2] = t[0] >> 16; - r[5*i+2] |= t[1] << 4; - r[5*i+3] = t[1] >> 4; - r[5*i+4] = t[1] >> 12; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyz_unpack -* -* Description: Unpack polynomial z with coefficients -* in [-(GAMMA1 - 1), GAMMA1]. -* -* Arguments: - poly *r: pointer to output polynomial -* - const uint8_t *a: byte array with bit-packed polynomial -**************************************************/ -void polyz_unpack(poly *r, const uint8_t *a) { - unsigned int i; - DBENCH_START(); - -#if GAMMA1 == (1 << 17) - for(i = 0; i < N/4; ++i) { - r->coeffs[4*i+0] = a[9*i+0]; - r->coeffs[4*i+0] |= (uint32_t)a[9*i+1] << 8; - r->coeffs[4*i+0] |= (uint32_t)a[9*i+2] << 16; - r->coeffs[4*i+0] &= 0x3FFFF; - - r->coeffs[4*i+1] = a[9*i+2] >> 2; - r->coeffs[4*i+1] |= (uint32_t)a[9*i+3] << 6; - r->coeffs[4*i+1] |= (uint32_t)a[9*i+4] << 14; - r->coeffs[4*i+1] &= 0x3FFFF; - - r->coeffs[4*i+2] = a[9*i+4] >> 4; - r->coeffs[4*i+2] |= (uint32_t)a[9*i+5] << 4; - r->coeffs[4*i+2] |= (uint32_t)a[9*i+6] << 12; - r->coeffs[4*i+2] &= 0x3FFFF; - - r->coeffs[4*i+3] = a[9*i+6] >> 6; - r->coeffs[4*i+3] |= (uint32_t)a[9*i+7] << 2; - r->coeffs[4*i+3] |= (uint32_t)a[9*i+8] << 10; - r->coeffs[4*i+3] &= 0x3FFFF; - - r->coeffs[4*i+0] = GAMMA1 - r->coeffs[4*i+0]; - r->coeffs[4*i+1] = GAMMA1 - r->coeffs[4*i+1]; - r->coeffs[4*i+2] = GAMMA1 - r->coeffs[4*i+2]; - r->coeffs[4*i+3] = GAMMA1 - r->coeffs[4*i+3]; - } -#elif GAMMA1 == (1 << 19) - for(i = 0; i < N/2; ++i) { - r->coeffs[2*i+0] = a[5*i+0]; - r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; - r->coeffs[2*i+0] |= (uint32_t)a[5*i+2] << 16; - r->coeffs[2*i+0] &= 0xFFFFF; - - r->coeffs[2*i+1] = a[5*i+2] >> 4; - r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; - r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; - r->coeffs[2*i+0] &= 0xFFFFF; - - r->coeffs[2*i+0] = GAMMA1 - r->coeffs[2*i+0]; - r->coeffs[2*i+1] = GAMMA1 - r->coeffs[2*i+1]; - } -#endif - - DBENCH_STOP(*tpack); -} - -/************************************************* -* Name: polyw1_pack -* -* Description: Bit-pack polynomial w1 with coefficients in [0,15] or [0,43]. -* Input coefficients are assumed to be standard representatives. -* -* Arguments: - uint8_t *r: pointer to output byte array with at least -* POLYW1_PACKEDBYTES bytes -* - const poly *a: pointer to input polynomial -**************************************************/ -void polyw1_pack(uint8_t *r, const poly *a) { - unsigned int i; - DBENCH_START(); - -#if GAMMA2 == (Q-1)/88 - for(i = 0; i < N/4; ++i) { - r[3*i+0] = a->coeffs[4*i+0]; - r[3*i+0] |= a->coeffs[4*i+1] << 6; - r[3*i+1] = a->coeffs[4*i+1] >> 2; - r[3*i+1] |= a->coeffs[4*i+2] << 4; - r[3*i+2] = a->coeffs[4*i+2] >> 4; - r[3*i+2] |= a->coeffs[4*i+3] << 2; - } -#elif GAMMA2 == (Q-1)/32 - for(i = 0; i < N/2; ++i) - r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); -#endif - - DBENCH_STOP(*tpack); -} diff --git a/crypto_sign/dilithium3/m4fstack/poly.c b/crypto_sign/dilithium3/m4fstack/poly.c new file mode 120000 index 00000000..2544e75b --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/poly.c @@ -0,0 +1 @@ +../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/poly.h b/crypto_sign/dilithium3/m4fstack/poly.h deleted file mode 100644 index 8f8819b0..00000000 --- a/crypto_sign/dilithium3/m4fstack/poly.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef POLY_H -#define POLY_H - -#include -#include "params.h" - -typedef struct { - int32_t coeffs[N]; -} poly; - -#define poly_reduce DILITHIUM_NAMESPACE(poly_reduce) -void poly_reduce(poly *a); -#define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) -void poly_caddq(poly *a); -#define poly_freeze DILITHIUM_NAMESPACE(poly_freeze) -void poly_freeze(poly *a); - -#define poly_add DILITHIUM_NAMESPACE(poly_add) -void poly_add(poly *c, const poly *a, const poly *b); -#define poly_sub DILITHIUM_NAMESPACE(poly_sub) -void poly_sub(poly *c, const poly *a, const poly *b); -#define poly_shiftl DILITHIUM_NAMESPACE(poly_shiftl) -void poly_shiftl(poly *a); - -#define poly_ntt DILITHIUM_NAMESPACE(poly_ntt) -void poly_ntt(poly *a); - -#define poly_invntt_tomont DILITHIUM_NAMESPACE(poly_invntt_tomont) -void poly_invntt_tomont(poly *a); -#define poly_pointwise_montgomery DILITHIUM_NAMESPACE(poly_pointwise_montgomery) -void poly_pointwise_montgomery(poly *c, const poly *a, const poly *b); -#define poly_pointwise_acc_montgomery DILITHIUM_NAMESPACE(poly_pointwise_acc_montgomery) -void poly_pointwise_acc_montgomery(poly *c, const poly *a, const poly *b); - -#define poly_power2round DILITHIUM_NAMESPACE(poly_power2round) -void poly_power2round(poly *a1, poly *a0, const poly *a); -#define poly_decompose DILITHIUM_NAMESPACE(poly_decompose) -void poly_decompose(poly *a1, poly *a0, const poly *a); -#define poly_make_hint DILITHIUM_NAMESPACE(poly_make_hint) -unsigned int poly_make_hint(poly *h, const poly *a0, const poly *a1); -#define poly_use_hint DILITHIUM_NAMESPACE(poly_use_hint) -void poly_use_hint(poly *b, const poly *a, const poly *h); - -#define poly_chknorm DILITHIUM_NAMESPACE(poly_chknorm) -int poly_chknorm(const poly *a, int32_t B); -#define poly_uniform DILITHIUM_NAMESPACE(poly_uniform) -void poly_uniform(poly *a, - const uint8_t seed[SEEDBYTES], - uint16_t nonce); -#define poly_uniform_eta DILITHIUM_NAMESPACE(poly_uniform_eta) -void poly_uniform_eta(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce); -#define poly_uniform_gamma1 DILITHIUM_NAMESPACE(poly_uniform_gamma1) -void poly_uniform_gamma1(poly *a, - const uint8_t seed[CRHBYTES], - uint16_t nonce); -#define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); - -#define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) -void polyeta_pack(uint8_t *r, const poly *a); - -#define polyt1_pack DILITHIUM_NAMESPACE(polyt1_pack) -void polyt1_pack(uint8_t *r, const poly *a); -#define polyt1_unpack DILITHIUM_NAMESPACE(polyt1_unpack) -void polyt1_unpack(poly *r, const uint8_t *a); - -#define polyt0_pack DILITHIUM_NAMESPACE(polyt0_pack) -void polyt0_pack(uint8_t *r, const poly *a); -#define polyt0_unpack DILITHIUM_NAMESPACE(polyt0_unpack) -void polyt0_unpack(poly *r, const uint8_t *a); - -#define polyz_pack DILITHIUM_NAMESPACE(polyz_pack) -void polyz_pack(uint8_t *r, const poly *a); -#define polyz_unpack DILITHIUM_NAMESPACE(polyz_unpack) -void polyz_unpack(poly *r, const uint8_t *a); - -#define polyw1_pack DILITHIUM_NAMESPACE(polyw1_pack) -void polyw1_pack(uint8_t *r, const poly *a); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/poly.h b/crypto_sign/dilithium3/m4fstack/poly.h new file mode 120000 index 00000000..7ef70e53 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/poly.h @@ -0,0 +1 @@ +../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.c b/crypto_sign/dilithium3/m4fstack/polyvec.c deleted file mode 100644 index e20749c0..00000000 --- a/crypto_sign/dilithium3/m4fstack/polyvec.c +++ /dev/null @@ -1,429 +0,0 @@ -#include -#include "params.h" -#include "polyvec.h" -#include "poly.h" - -#include -#include "hal.h" - -/************************************************* -* Name: expand_mat -* -* Description: Implementation of ExpandA. Generates matrix A with uniformly -* random coefficients a_{i,j} by performing rejection -* sampling on the output stream of SHAKE128(rho|j|i). -* -* Arguments: - polyvecl mat[K]: output matrix -* - const uint8_t rho[]: byte array containing seed rho -**************************************************/ -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) { - unsigned int i, j; - - for(i = 0; i < K; ++i) - for(j = 0; j < L; ++j) - poly_uniform(&mat[i].vec[j], rho, (i << 8) + j); -} - -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v); -} - -/**************************************************************/ -/************ Vectors of polynomials of length L **************/ -/**************************************************************/ - -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i); -} - -void polyvecl_reduce(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_reduce(&v->vec[i]); -} - -#if 0 -/************************************************* -* Name: polyvecl_freeze -* -* Description: Reduce coefficients of polynomials in vector of length L -* to standard representatives. -* -* Arguments: - polyvecl *v: pointer to input/output vector -**************************************************/ -void polyvecl_freeze(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_freeze(&v->vec[i]); -} -#endif - -/************************************************* -* Name: polyvecl_add -* -* Description: Add vectors of polynomials of length L. -* No modular reduction is performed. -* -* Arguments: - polyvecl *w: pointer to output vector -* - const polyvecl *u: pointer to first summand -* - const polyvecl *v: pointer to second summand -**************************************************/ -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyvecl_ntt -* -* Description: Forward NTT of all polynomials in vector of length L. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyvecl *v: pointer to input/output vector -**************************************************/ -void polyvecl_ntt(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_ntt(&v->vec[i]); -} - -void polyvecl_invntt_tomont(polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_invntt_tomont(&v->vec[i]); -} - -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) { - unsigned int i; - - for(i = 0; i < L; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - - - -/************************************************* -* Name: polyvecl_pointwise_acc_montgomery -* -* Description: Pointwise multiply vectors of polynomials of length L, multiply -* resulting vector by 2^{-32} and add (accumulate) polynomials -* in it. Input/output vectors are in NTT domain representation. -* -* Arguments: - poly *w: output polynomial -* - const polyvecl *u: pointer to first input vector -* - const polyvecl *v: pointer to second input vector -**************************************************/ -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v) -{ - unsigned int i; - - poly_pointwise_montgomery(w, &u->vec[0], &v->vec[0]); - for(i = 1; i < L; ++i) { - poly_pointwise_acc_montgomery(w, &u->vec[i], &v->vec[i]); - } -} - -/************************************************* -* Name: polyvecl_chknorm -* -* Description: Check infinity norm of polynomials in vector of length L. -* Assumes input polyvecl to be reduced by polyvecl_reduce(). -* -* Arguments: - const polyvecl *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyvecl_chknorm(const polyvecl *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < L; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/**************************************************************/ -/************ Vectors of polynomials of length K **************/ -/**************************************************************/ - -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_uniform_eta(&v->vec[i], seed, nonce++); -} - -/************************************************* -* Name: polyveck_reduce -* -* Description: Reduce coefficients of polynomials in vector of length K -* to representatives in [-6283009,6283007]. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_reduce(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_reduce(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_caddq -* -* Description: For all coefficients of polynomials in vector of length K -* add Q if coefficient is negative. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_caddq(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_caddq(&v->vec[i]); -} - -#if 0 -/************************************************* -* Name: polyveck_freeze -* -* Description: Reduce coefficients of polynomials in vector of length K -* to standard representatives. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_freeze(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_freeze(&v->vec[i]); -} -#endif - -/************************************************* -* Name: polyveck_add -* -* Description: Add vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first summand -* - const polyveck *v: pointer to second summand -**************************************************/ -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_add(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_sub -* -* Description: Subtract vectors of polynomials of length K. -* No modular reduction is performed. -* -* Arguments: - polyveck *w: pointer to output vector -* - const polyveck *u: pointer to first input vector -* - const polyveck *v: pointer to second input vector to be -* subtracted from first input vector -**************************************************/ -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_shiftl -* -* Description: Multiply vector of polynomials of Length K by 2^D without modular -* reduction. Assumes input coefficients to be less than 2^{31-D}. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_shiftl(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_shiftl(&v->vec[i]); -} - -/************************************************* -* Name: polyveck_ntt -* -* Description: Forward NTT of all polynomials in vector of length K. Output -* coefficients can be up to 16*Q larger than input coefficients. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_ntt(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_ntt(&v->vec[i]); -} - - - -/************************************************* -* Name: polyveck_invntt_tomont -* -* Description: Inverse NTT and multiplication by 2^{32} of polynomials -* in vector of length K. Input coefficients need to be less -* than 2*Q. -* -* Arguments: - polyveck *v: pointer to input/output vector -**************************************************/ -void polyveck_invntt_tomont(polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_invntt_tomont(&v->vec[i]); -} - - -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]); -} - - -/************************************************* -* Name: polyveck_chknorm -* -* Description: Check infinity norm of polynomials in vector of length K. -* Assumes input polyveck to be reduced by polyveck_reduce(). -* -* Arguments: - const polyveck *v: pointer to vector -* - int32_t B: norm bound -* -* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8 -* and 1 otherwise. -**************************************************/ -int polyveck_chknorm(const polyveck *v, int32_t bound) { - unsigned int i; - - for(i = 0; i < K; ++i) - if(poly_chknorm(&v->vec[i], bound)) - return 1; - - return 0; -} - -/************************************************* -* Name: polyveck_power2round -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute a0, a1 such that a mod^+ Q = a1*2^D + a0 -* with -2^{D-1} < a0 <= 2^{D-1}. Assumes coefficients to be -* standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_decompose -* -* Description: For all coefficients a of polynomials in vector of length K, -* compute high and low bits a0, a1 such a mod^+ Q = a1*ALPHA + a0 -* with -ALPHA/2 < a0 <= ALPHA/2 except a1 = (Q-1)/ALPHA where we -* set a1 = 0 and -ALPHA/2 <= a0 = a mod Q - Q < 0. -* Assumes coefficients to be standard representatives. -* -* Arguments: - polyveck *v1: pointer to output vector of polynomials with -* coefficients a1 -* - polyveck *v0: pointer to output vector of polynomials with -* coefficients a0 -* - const polyveck *v: pointer to input vector -**************************************************/ -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]); -} - -/************************************************* -* Name: polyveck_make_hint -* -* Description: Compute hint vector. -* -* Arguments: - polyveck *h: pointer to output vector -* - const polyveck *v0: pointer to low part of input vector -* - const polyveck *v1: pointer to high part of input vector -* -* Returns number of 1 bits. -**************************************************/ -unsigned int polyveck_make_hint(polyveck *h, - const polyveck *v0, - const polyveck *v1) -{ - unsigned int i, s = 0; - - for(i = 0; i < K; ++i) - s += poly_make_hint(&h->vec[i], &v0->vec[i], &v1->vec[i]); - - return s; -} - -/************************************************* -* Name: polyveck_use_hint -* -* Description: Use hint vector to correct the high bits of input vector. -* -* Arguments: - polyveck *w: pointer to output vector of polynomials with -* corrected high bits -* - const polyveck *u: pointer to input vector -* - const polyveck *h: pointer to input hint vector -**************************************************/ -void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) { - unsigned int i; - - for(i = 0; i < K; ++i) - poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]); -} - -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) { - unsigned int i; - - for(i = 0; i < K; ++i) - polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]); -} diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.c b/crypto_sign/dilithium3/m4fstack/polyvec.c new file mode 120000 index 00000000..a8edd0d0 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/polyvec.c @@ -0,0 +1 @@ +../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.h b/crypto_sign/dilithium3/m4fstack/polyvec.h deleted file mode 100644 index d92cd753..00000000 --- a/crypto_sign/dilithium3/m4fstack/polyvec.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef POLYVEC_H -#define POLYVEC_H - -#include -#include "params.h" -#include "poly.h" - -/* Vectors of polynomials of length L */ -typedef struct { - poly vec[L]; -} polyvecl; - -#define polyvecl_uniform_eta DILITHIUM_NAMESPACE(polyvecl_uniform_eta) -void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_uniform_gamma1 DILITHIUM_NAMESPACE(polyvecl_uniform_gamma1) -void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyvecl_reduce DILITHIUM_NAMESPACE(polyvecl_reduce) -void polyvecl_reduce(polyvecl *v); - -#define polyvecl_freeze DILITHIUM_NAMESPACE(polyvecl_freeze) -void polyvecl_freeze(polyvecl *v); - -#define polyvecl_add DILITHIUM_NAMESPACE(polyvecl_add) -void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v); - -#define polyvecl_ntt DILITHIUM_NAMESPACE(polyvecl_ntt) -void polyvecl_ntt(polyvecl *v); -#define polyvecl_invntt_tomont DILITHIUM_NAMESPACE(polyvecl_invntt_tomont) -void polyvecl_invntt_tomont(polyvecl *v); -#define polyvecl_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyvecl_pointwise_poly_montgomery) -void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v); -#define polyvecl_pointwise_acc_montgomery \ - DILITHIUM_NAMESPACE(polyvecl_pointwise_acc_montgomery) -void polyvecl_pointwise_acc_montgomery(poly *w, - const polyvecl *u, - const polyvecl *v); - - -#define polyvecl_chknorm DILITHIUM_NAMESPACE(polyvecl_chknorm) -int polyvecl_chknorm(const polyvecl *v, int32_t B); - - - -/* Vectors of polynomials of length K */ -typedef struct { - poly vec[K]; -} polyveck; - -#define polyveck_uniform_eta DILITHIUM_NAMESPACE(polyveck_uniform_eta) -void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce); - -#define polyveck_reduce DILITHIUM_NAMESPACE(polyveck_reduce) -void polyveck_reduce(polyveck *v); -#define polyveck_caddq DILITHIUM_NAMESPACE(polyveck_caddq) -void polyveck_caddq(polyveck *v); -#define polyveck_freeze DILITHIUM_NAMESPACE(polyveck_freeze) -void polyveck_freeze(polyveck *v); - -#define polyveck_add DILITHIUM_NAMESPACE(polyveck_add) -void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_sub DILITHIUM_NAMESPACE(polyveck_sub) -void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v); -#define polyveck_shiftl DILITHIUM_NAMESPACE(polyveck_shiftl) -void polyveck_shiftl(polyveck *v); - -#define polyveck_ntt DILITHIUM_NAMESPACE(polyveck_ntt) -void polyveck_ntt(polyveck *v); -#define polyveck_invntt_tomont DILITHIUM_NAMESPACE(polyveck_invntt_tomont) -void polyveck_invntt_tomont(polyveck *v); -#define polyveck_pointwise_poly_montgomery DILITHIUM_NAMESPACE(polyveck_pointwise_poly_montgomery) -void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v); - - -#define polyveck_chknorm DILITHIUM_NAMESPACE(polyveck_chknorm) -int polyveck_chknorm(const polyveck *v, int32_t B); - -#define polyveck_power2round DILITHIUM_NAMESPACE(polyveck_power2round) -void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_decompose DILITHIUM_NAMESPACE(polyveck_decompose) -void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v); -#define polyveck_make_hint DILITHIUM_NAMESPACE(polyveck_make_hint) -unsigned int polyveck_make_hint(polyveck *h, - const polyveck *v0, - const polyveck *v1); -#define polyveck_use_hint DILITHIUM_NAMESPACE(polyveck_use_hint) -void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h); - -#define polyveck_pack_w1 DILITHIUM_NAMESPACE(polyveck_pack_w1) -void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1); - -#define polyvec_matrix_expand DILITHIUM_NAMESPACE(polyvec_matrix_expand) -void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]); - -#define polyvec_matrix_pointwise_montgomery DILITHIUM_NAMESPACE(polyvec_matrix_pointwise_montgomery) -void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.h b/crypto_sign/dilithium3/m4fstack/polyvec.h new file mode 120000 index 00000000..cabd6a93 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/polyvec.h @@ -0,0 +1 @@ +../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/reduce.h b/crypto_sign/dilithium3/m4fstack/reduce.h deleted file mode 100644 index 5990918a..00000000 --- a/crypto_sign/dilithium3/m4fstack/reduce.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef REDUCE_H -#define REDUCE_H - -#include -#include "params.h" - -#define MONT -4186625 // 2^32 % Q -#define QINV 58728449 // q^(-1) mod 2^32 - -#define montgomery_reduce DILITHIUM_NAMESPACE(montgomery_reduce) -/************************************************* -* Name: montgomery_reduce -* -* Description: For finite field element a with -2^{31}Q <= a <= Q*2^31, -* compute r \equiv a*2^{-32} (mod Q) such that -Q < r < Q. -* -* Arguments: - int64_t: finite field element a -* -* Returns r. -**************************************************/ -static inline int32_t montgomery_reduce(int64_t a) { - int32_t t; - - t = (int64_t)(int32_t)a*QINV; - t = (a - (int64_t)t*Q) >> 32; - return t; -} - -/************************************************* -* Name: reduce32 -* -* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1, -* compute r \equiv a (mod Q) such that -6283009 <= r <= 6283007. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -static int32_t reduce32(int32_t a) { - int32_t t; - - t = (a + (1 << 22)) >> 23; - t = a - t*Q; - return t; -} - -/************************************************* -* Name: caddq -* -* Description: Add Q if input coefficient is negative. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -static int32_t caddq(int32_t a) { - a += (a >> 31) & Q; - return a; -} - -/************************************************* -* Name: freeze -* -* Description: For finite field element a, compute standard -* representative r = a mod^+ Q. -* -* Arguments: - int32_t: finite field element a -* -* Returns r. -**************************************************/ -static int32_t freeze(int32_t a) { - a = reduce32(a); - a = caddq(a); - return a; -} - - - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/reduce.h b/crypto_sign/dilithium3/m4fstack/reduce.h new file mode 120000 index 00000000..f1e2b389 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/reduce.h @@ -0,0 +1 @@ +../../dilithium2/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/rounding.c b/crypto_sign/dilithium3/m4fstack/rounding.c deleted file mode 100644 index 889f0a29..00000000 --- a/crypto_sign/dilithium3/m4fstack/rounding.c +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include "params.h" -#include "rounding.h" - -/************************************************* -* Name: power2round -* -* Description: For finite field element a, compute a0, a1 such that -* a mod^+ Q = a1*2^D + a0 with -2^{D-1} < a0 <= 2^{D-1}. -* Assumes a to be standard representative. -* -* Arguments: - int32_t a: input element -* - int32_t *a0: pointer to output element a0 -* -* Returns a1. -**************************************************/ -int32_t power2round(int32_t *a0, int32_t a) { - int32_t a1; - - a1 = (a + (1 << (D-1)) - 1) >> D; - *a0 = a - (a1 << D); - return a1; -} - -/************************************************* -* Name: decompose -* -* Description: For finite field element a, compute high and low bits a0, a1 such -* that a mod^+ Q = a1*ALPHA + a0 with -ALPHA/2 < a0 <= ALPHA/2 except -* if a1 = (Q-1)/ALPHA where we set a1 = 0 and -* -ALPHA/2 <= a0 = a mod^+ Q - Q < 0. Assumes a to be standard -* representative. -* -* Arguments: - int32_t a: input element -* - int32_t *a0: pointer to output element a0 -* -* Returns a1. -**************************************************/ -int32_t decompose(int32_t *a0, int32_t a) { - int32_t a1; - - a1 = (a + 127) >> 7; -#if GAMMA2 == (Q-1)/32 - a1 = (a1*1025 + (1 << 21)) >> 22; - a1 &= 15; -#elif GAMMA2 == (Q-1)/88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; -#endif - - *a0 = a - a1*2*GAMMA2; - *a0 -= (((Q-1)/2 - *a0) >> 31) & Q; - return a1; -} - -/************************************************* -* Name: make_hint -* -* Description: Compute hint bit indicating whether the low bits of the -* input element overflow into the high bits. -* -* Arguments: - int32_t a0: low bits of input element -* - int32_t a1: high bits of input element -* -* Returns 1 if overflow. -**************************************************/ -unsigned int make_hint(int32_t a0, int32_t a1) { - if(a0 > GAMMA2 || a0 < -GAMMA2 || (a0 == -GAMMA2 && a1 != 0)) - return 1; - - return 0; -} - -/************************************************* -* Name: use_hint -* -* Description: Correct high bits according to hint. -* -* Arguments: - int32_t a: input element -* - unsigned int hint: hint bit -* -* Returns corrected high bits. -**************************************************/ -int32_t use_hint(int32_t a, unsigned int hint) { - int32_t a0, a1; - - a1 = decompose(&a0, a); - if(hint == 0) - return a1; - -#if GAMMA2 == (Q-1)/32 - if(a0 > 0) - return (a1 + 1) & 15; - else - return (a1 - 1) & 15; -#elif GAMMA2 == (Q-1)/88 - if(a0 > 0) - return (a1 == 43) ? 0 : a1 + 1; - else - return (a1 == 0) ? 43 : a1 - 1; -#endif -} diff --git a/crypto_sign/dilithium3/m4fstack/rounding.c b/crypto_sign/dilithium3/m4fstack/rounding.c new file mode 120000 index 00000000..80b8dce2 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/rounding.c @@ -0,0 +1 @@ +../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/rounding.h b/crypto_sign/dilithium3/m4fstack/rounding.h deleted file mode 100644 index b72e8e8d..00000000 --- a/crypto_sign/dilithium3/m4fstack/rounding.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ROUNDING_H -#define ROUNDING_H - -#include -#include "params.h" - -#define power2round DILITHIUM_NAMESPACE(power2round) -int32_t power2round(int32_t *a0, int32_t a); - -#define decompose DILITHIUM_NAMESPACE(decompose) -int32_t decompose(int32_t *a0, int32_t a); - -#define make_hint DILITHIUM_NAMESPACE(make_hint) -unsigned int make_hint(int32_t a0, int32_t a1); - -#define use_hint DILITHIUM_NAMESPACE(use_hint) -int32_t use_hint(int32_t a, unsigned int hint); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/rounding.h b/crypto_sign/dilithium3/m4fstack/rounding.h new file mode 120000 index 00000000..74c40c5e --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/rounding.h @@ -0,0 +1 @@ +../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/sign.c b/crypto_sign/dilithium3/m4fstack/sign.c deleted file mode 100644 index 71cff9bb..00000000 --- a/crypto_sign/dilithium3/m4fstack/sign.c +++ /dev/null @@ -1,484 +0,0 @@ -#include -#include "params.h" -#include "sign.h" -#include "packing.h" -#include "polyvec.h" -#include "poly.h" -#include "randombytes.h" -#include "symmetric.h" -#include "smallpoly.h" -#include "stack.h" - -#include "smallntt.h" - -/************************************************* -* Name: crypto_sign_keypair -* -* Description: Generates public and private key. -* -* Arguments: - uint8_t *pk: pointer to output public key (allocated -* array of CRYPTO_PUBLICKEYBYTES bytes) -* - uint8_t *sk: pointer to output private key (allocated -* array of CRYPTO_SECRETKEYBYTES bytes) -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - unsigned int i, j; - uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; - const uint8_t *rho, *rhoprime, *key; - - poly tA, tB; - - union { - uint8_t tr[TRBYTES]; - shake256incctx s256; - poly tC; - } data; - - shake256incctx *s256 = &data.s256; - uint8_t *tr = &data.tr; - poly *tC = &data.tC; - - /* Get randomness for rho, rhoprime and key */ - randombytes(seedbuf, SEEDBYTES); - shake256_inc_init(s256); - shake256_inc_absorb(s256, seedbuf, SEEDBYTES); - shake256_inc_finalize(s256); - shake256_inc_squeeze(seedbuf, 2*SEEDBYTES + CRHBYTES, s256); - - rho = seedbuf; - rhoprime = rho + SEEDBYTES; - key = rhoprime + CRHBYTES; - - pack_sk_rho(sk, rho); - pack_sk_key(sk, key); - pack_pk_rho(pk, rho); - - /* Matrix-vector multiplication */ - for (i = 0; i < K; i++) - { - /* Expand part of s1 */ - poly_uniform_eta(tC, rhoprime, 0); - if (i == 0) - { - pack_sk_s1(sk, tC, 0); - } - poly_ntt(tC); - /* expand part of the matrix */ - poly_uniform(&tB, rho, (i << 8) + 0); - /* partial matrix-vector multiplication */ - poly_pointwise_montgomery(&tA, &tB, tC); - for(j = 1; j < L; j++) - { - /* Expand part of s1 */ - poly_uniform_eta(tC, rhoprime, j); - if (i == 0) - { - pack_sk_s1(sk, tC, j); - } - poly_ntt(tC); - poly_uniform(&tB, rho, (i << 8) + j); - poly_pointwise_acc_montgomery(&tA, &tB, tC); - } - - poly_reduce(&tA); - poly_invntt_tomont(&tA); - - /* Add error vector s2 */ - /* Sample short vector s2 */ - poly_uniform_eta(&tB, rhoprime, L + i); - pack_sk_s2(sk, &tB, i); - poly_add(&tA, &tA, &tB); - - /* Compute t{0,1} */ - poly_caddq(&tA); - poly_power2round(tC, &tB, &tA); - pack_sk_t0(sk, &tB, i); - pack_pk_t1(pk, tC, i); - - } - - /* Compute H(rho, t1) and write secret key */ - shake256(tr, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); - pack_sk_tr(sk, tr); - - return 0; -} - - -/************************************************* -* Name: crypto_sign_signature -* -* Description: Computes signature. -* -* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES) -* - size_t *siglen: pointer to output length of signature -* - uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) -**************************************************/ -int crypto_sign_signature(uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *sk) -{ - uint8_t buf[2 * CRHBYTES]; - uint8_t *mu, *rhoprime, *rnd; - const uint8_t *rho, *tr, *key; - uint16_t nonce = 0; - unsigned int n; - uint8_t wcomp[K][768]; - uint8_t ccomp[68]; - - union { - shake128incctx s128; - shake256incctx s256; - } state; - - union { - poly full; - struct { - smallpoly stmp0; - smallpoly stmp1; - } small; - } polybuffer; - - poly *tmp0 = &polybuffer.full; - smallpoly *stmp0 = &polybuffer.small.stmp0; - smallpoly *scp = &polybuffer.small.stmp1; - - rho = sk; - tr = sk + SEEDBYTES*2; - key = sk + SEEDBYTES; - - mu = buf; - rnd = mu + CRHBYTES; - rhoprime = mu + CRHBYTES; - unpack_sk_stack(rho, tr, key, sk); - - /* Compute mu = CRH(tr, msg) */ - shake256_inc_init(&state.s256); - shake256_inc_absorb(&state.s256, tr, TRBYTES); - shake256_inc_absorb(&state.s256, m, mlen); - shake256_inc_finalize(&state.s256); - shake256_inc_squeeze(mu, CRHBYTES, &state.s256); - - // Note: RNDBYTES < CRHBYTES, so buffer has proper size - for (n = 0; n < RNDBYTES; n++) { - rnd[n] = 0; - } - - shake256_inc_init(&state.s256); - shake256_inc_absorb(&state.s256, key, SEEDBYTES); - shake256_inc_absorb(&state.s256, rnd, RNDBYTES); - shake256_inc_absorb(&state.s256, mu, CRHBYTES); - shake256_inc_finalize(&state.s256); - // rnd can be overwritten here - shake256_inc_squeeze(rhoprime, CRHBYTES, &state.s256); - -rej: - for (size_t k_idx = 0; k_idx < K; k_idx++) { - for(size_t i=0;i<768;i++){ - wcomp[k_idx][i] = 0; - } - } - - for (size_t l_idx = 0; l_idx < L; l_idx++) { - /* Sample intermediate vector y */ - poly_uniform_gamma1_stack(tmp0, rhoprime, L*nonce + l_idx, &state.s256); - poly_ntt(tmp0); - - /* Matrix-vector multiplication */ - for (size_t k_idx = 0; k_idx < K; k_idx++) { - // sampling of y and packing into wcomp inlined into the basemul - poly_uniform_pointwise_montgomery_polywadd_stack(wcomp[k_idx], tmp0, rho, (k_idx << 8) + l_idx, &state.s128); - } - } - nonce++; - for (size_t k_idx = 0; k_idx < K; k_idx++) { - polyw_unpack(tmp0, wcomp[k_idx]); - poly_invntt_tomont(tmp0); - poly_caddq(tmp0); - - polyw_pack(wcomp[k_idx], tmp0); - poly_highbits(tmp0, tmp0); - polyw1_pack(&sig[k_idx*POLYW1_PACKEDBYTES], tmp0); - } - - shake256_inc_init(&state.s256); - shake256_inc_absorb(&state.s256, mu, CRHBYTES); - shake256_inc_absorb(&state.s256, sig, K*POLYW1_PACKEDBYTES); - shake256_inc_finalize(&state.s256); - shake256_inc_squeeze(sig, CTILDEBYTES, &state.s256); - poly_challenge(tmp0, sig); - - poly_challenge_compress(ccomp, tmp0); - - /* Compute z, reject if it reveals secret */ - for(size_t l_idx=0;l_idx < L; l_idx++){ - if(l_idx != 0){ - poly_challenge_decompress(tmp0, ccomp); - } - poly_small_ntt_copy(scp, tmp0); - unpack_sk_s1(stmp0, sk, l_idx); - small_ntt(stmp0->coeffs); - poly_small_basemul_invntt(tmp0, scp, stmp0); - - poly_uniform_gamma1_add_stack(tmp0, tmp0, rhoprime, L*(nonce-1) + l_idx, &state.s256); - - poly_reduce(tmp0); - - if(poly_chknorm(tmp0, GAMMA1 - BETA)) - goto rej; - - polyz_pack(sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES, tmp0); - } - - - /* Write signature */ - unsigned int hint_n = 0; - unsigned int hints_written = 0; - /* Check that subtracting cs2 does not change high bits of w and low bits - * do not reveal secret information */ - - for(unsigned int k_idx = 0; k_idx < K; ++k_idx) { - poly_challenge_decompress(tmp0, ccomp); - poly_small_ntt_copy(scp, tmp0); - - unpack_sk_s2(stmp0, sk, k_idx); - small_ntt(stmp0->coeffs); - poly_small_basemul_invntt(tmp0, scp, stmp0); - - polyw_sub(tmp0, wcomp[k_idx], tmp0); - poly_reduce(tmp0); - - polyw_pack(wcomp[k_idx], tmp0); - - poly_lowbits(tmp0, tmp0); - poly_reduce(tmp0); - if(poly_chknorm(tmp0, GAMMA2 - BETA)){ - goto rej; - } - - poly_schoolbook(tmp0, ccomp, sk + SEEDBYTES + TRBYTES + SEEDBYTES + - L*POLYETA_PACKEDBYTES + K*POLYETA_PACKEDBYTES + k_idx*POLYT0_PACKEDBYTES); - - /* Compute hints for w1 */ - - if(poly_chknorm(tmp0, GAMMA2)) { - goto rej; - } - - hint_n += poly_make_hint_stack(tmp0, tmp0, wcomp[k_idx]); - - if (hint_n > OMEGA) { - goto rej; - } - pack_sig_h(sig, tmp0, k_idx, &hints_written); - } - pack_sig_h_zero(sig, &hints_written); - *siglen = CRYPTO_BYTES; - return 0; -} - -/************************************************* -* Name: crypto_sign -* -* Description: Compute signed message. -* -* Arguments: - uint8_t *sm: pointer to output signed message (allocated -* array with CRYPTO_BYTES + mlen bytes), -* can be equal to m -* - size_t *smlen: pointer to output length of signed -* message -* - const uint8_t *m: pointer to message to be signed -* - size_t mlen: length of message -* - const uint8_t *sk: pointer to bit-packed secret key -* -* Returns 0 (success) -**************************************************/ -int crypto_sign(uint8_t *sm, - size_t *smlen, - const uint8_t *m, - size_t mlen, - const uint8_t *sk) -{ - size_t i; - - for(i = 0; i < mlen; ++i) - sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); - *smlen += mlen; - return 0; -} - -/************************************************* -* Name: crypto_sign_verify -* -* Description: Verifies signature. -* -* Arguments: - uint8_t *m: pointer to input signature -* - size_t siglen: length of signature -* - const uint8_t *m: pointer to message -* - size_t mlen: length of message -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signature could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_verify(const uint8_t *sig, - size_t siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pk) -{ - unsigned int i; - - poly p; - - union { - uint8_t w1_packed[POLYW1_PACKEDBYTES]; - uint8_t wcomp[768]; - } w1_packed_comp; - uint8_t *w1_packed = &w1_packed_comp.w1_packed; - uint8_t *wcomp = &w1_packed_comp.wcomp; - - union { - uint8_t ccomp[68]; - uint8_t mu[CRHBYTES]; - } ccomp_mu; - uint8_t *ccomp = &ccomp_mu.ccomp; - uint8_t *mu = &ccomp_mu.mu; - - shake256incctx s256; - - union { - uint8_t hint_ones[OMEGA]; - shake128incctx s128; - uint8_t c2[CTILDEBYTES]; - } shake_hint; - - uint8_t *hint_ones = &shake_hint.hint_ones; - shake128incctx *s128 = &shake_hint.s128; - uint8_t *c2 = &shake_hint.c2; - - if(siglen != CRYPTO_BYTES) - return -1; - - /* Compute CRH(h(rho, t1), msg) */ - shake256_inc_init(&s256); - shake256_inc_absorb(&s256, pk, CRYPTO_PUBLICKEYBYTES); - shake256_inc_finalize(&s256); - shake256_inc_squeeze(mu, CRHBYTES, &s256); - - shake256_inc_init(&s256); - shake256_inc_absorb(&s256, mu, TRBYTES); - shake256_inc_absorb(&s256, m, mlen); - shake256_inc_finalize(&s256); - shake256_inc_squeeze(mu, CRHBYTES, &s256); - - shake256_inc_init(&s256); - shake256_inc_absorb(&s256, mu, CRHBYTES); - - /* Matrix-vector multiplication; compute Az - c2^dt1 */ - poly_challenge_stack(&p, sig); - poly_challenge_compress(ccomp, &p); - - for (size_t k_idx = 0; k_idx < K; k_idx++) { - for(size_t widx=0;widx<768;widx++){ - wcomp[widx] = 0; - } - - polyz_unpack(&p, sig + CTILDEBYTES); - if(poly_chknorm(&p, GAMMA1 - BETA)) - return -1; - poly_ntt(&p); - - poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + 0, s128); - - for (size_t l_idx = 1; l_idx < L; l_idx++) { - polyz_unpack(&p, sig + CTILDEBYTES + l_idx*POLYZ_PACKEDBYTES); - if(poly_chknorm(&p, GAMMA1 - BETA)) - return -1; - poly_ntt(&p); - poly_uniform_pointwise_montgomery_polywadd_stack(wcomp, &p, pk, (k_idx << 8) + l_idx, s128); - } - polyw_unpack(&p, wcomp); - poly_reduce(&p); - poly_invntt_tomont(&p); - polyw_pack(wcomp, &p); - - poly_schoolbook_t1(&p, ccomp, pk + SEEDBYTES + k_idx*POLYT1_PACKEDBYTES); - - polyw_sub(&p, wcomp, &p); - poly_reduce(&p); - - /* Reconstruct w1 */ - poly_caddq(&p); - - if (unpack_sig_h_indices(hint_ones, &i, k_idx, sig) != 0) - { - return -1; - } - poly_use_hint_stack(&p, &p, hint_ones, i); - - polyw1_pack(w1_packed, &p); - - shake256_inc_absorb(&s256, w1_packed, POLYW1_PACKEDBYTES); - } - /* Call random oracle and verify challenge */ - shake256_inc_finalize(&s256); - shake256_inc_squeeze(c2, CTILDEBYTES, &s256); - for(i = 0; i < CTILDEBYTES; ++i) - if(sig[i] != c2[i]) - return -1; - - return 0; -} - -/************************************************* -* Name: crypto_sign_open -* -* Description: Verify signed message. -* -* Arguments: - uint8_t *m: pointer to output message (allocated -* array with smlen bytes), can be equal to sm -* - size_t *mlen: pointer to output length of message -* - const uint8_t *sm: pointer to signed message -* - size_t smlen: length of signed message -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signed message could be verified correctly and -1 otherwise -**************************************************/ -int crypto_sign_open(uint8_t *m, - size_t *mlen, - const uint8_t *sm, - size_t smlen, - const uint8_t *pk) -{ - size_t i; - - if(smlen < CRYPTO_BYTES) - goto badsig; - - *mlen = smlen - CRYPTO_BYTES; - if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) - goto badsig; - else { - /* All good, copy msg, return 0 */ - for(i = 0; i < *mlen; ++i) - m[i] = sm[CRYPTO_BYTES + i]; - return 0; - } - -badsig: - /* Signature verification failed */ - *mlen = -1; - for(i = 0; i < smlen; ++i) - m[i] = 0; - - return -1; -} diff --git a/crypto_sign/dilithium3/m4fstack/sign.c b/crypto_sign/dilithium3/m4fstack/sign.c new file mode 120000 index 00000000..39f6ec48 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/sign.c @@ -0,0 +1 @@ +../../dilithium2/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/sign.h b/crypto_sign/dilithium3/m4fstack/sign.h deleted file mode 100644 index 42240b30..00000000 --- a/crypto_sign/dilithium3/m4fstack/sign.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SIGN_H -#define SIGN_H - -#include -#include -#include "params.h" -#include "api.h" -#include "polyvec.h" -#include "poly.h" - -#define challenge DILITHIUM_NAMESPACE(challenge) -void challenge(poly *c, const uint8_t seed[SEEDBYTES]); - -// #define crypto_sign_keypair DILITHIUM_NAMESPACE(crypto_sign_keypair) -// int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -// #define crypto_sign_signature DILITHIUM_NAMESPACE(signature) -// int crypto_sign_signature(uint8_t *sig, size_t *siglen, -// const uint8_t *m, size_t mlen, -// const uint8_t *sk); - -// #define crypto_sign DILITHIUM_NAMESPACE(crypto_sign) -// int crypto_sign(uint8_t *sm, size_t *smlen, -// const uint8_t *m, size_t mlen, -// const uint8_t *sk); - -// #define crypto_sign_verify DILITHIUM_NAMESPACE(verify) -// int crypto_sign_verify(const uint8_t *sig, size_t siglen, -// const uint8_t *m, size_t mlen, -// const uint8_t *pk); - -// #define crypto_sign_open DILITHIUM_NAMESPACE(crypto_sign_open) -// int crypto_sign_open(uint8_t *m, size_t *mlen, -// const uint8_t *sm, size_t smlen, -// const uint8_t *pk); - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/sign.h b/crypto_sign/dilithium3/m4fstack/sign.h new file mode 120000 index 00000000..b7f1e89c --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/sign.h @@ -0,0 +1 @@ +../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallntt.h b/crypto_sign/dilithium3/m4fstack/smallntt.h deleted file mode 100644 index 244fad24..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallntt.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) - * - * Licensed under the Apache License, Version 2.0(the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SMALLNTT_H -#define SMALLNTT_H - -#include -#include "params.h" - -#define SMALL_Q 769 - -static const int32_t zetas_769[64] = { - 3138844760, 1334846793, 999738812, 1854264165, 1681125041, 1150537404, 2820492178, 3071823164, 726067294, 2066499220, 3272887953, 1055590142, 4255871365, 1871019564, 2731130050, 1826338500, 513832239, 1792827701, 3373420347, 2993631302, 1161707670, 3306398751, 3518633806, 3406931146, 1586177780, 3853741788, 3317569017, 3825816122, 971813147, 122872927, 217820188, 619949766, 3753209393, 770748358, 4099487641, 765163225, 3630336467, 1742561504, 3479537875, 982983413, 2809321912, 2379266669, 703726762, 681386230, 4110657907, 1457719720, 1217559000, 2474213930, 1195218468, 1089100940, 564098436, 614364633, 3635921600, 2088839752, 3702943196, 1949211426, 2569161192, 374203913, 3982199847, 2083254619, 1513571050, 3647091866, 413299844, 4149753838}; - -static const int32_t zetas_asm_769[128] = { - 346278248, 223405321, 966228013, 759578091, -150798592, 318352582, -1736976371, 1697880440, -2105595150, -804259156, 1675539907, -1016494210, 1401868389, -2005062756, 240160720, 474736307, -1200803600, -1435379187, -1156122536, 1334846793, 999738811, 1854264164, -631120032, -787503756, -1580592646, 1681125040, 1150537403, -1474475119, -1223144132, 1809583100, -100532394, -1938041160, 726067293, 2066499219, -1022079344, 1055590142, 525002504, 273671518, -212235055, -39095931, 1871019563, -1563837247, 1826338499, 139628326, 27925665, 1731391238, 513832238, 1792827701, -921546949, -1301335995, 67021596, 1117026605, 536172770, 1161707669, -988568545, -776333490, -888036151, 1290165729, -497076839, -753992958, 1586177779, -441225509, -977398279, -469151174, -1614103444, 1591762912, -94947261, 971813146, 122872927, 217820188, 619949766, -1709050706, 1010909077, -1748146637, -541757903, 770748357, -195479656, 765163224, 1413038655, 1781657435, -1206388733, -664630830, 1742561504, -815429422, 982983412, 357448514, 44681064, -1524741316, -1485645385, -1915700627, 703726761, 681386229, 686971362, 1787242568, -860110486, -184309390, 1457719719, 1217558999, -1820753366, -502661972, -1921285760, 1139367137, 1195218467, 1089100940, 564098435, 614364633, -1100271206, 457980908, -1669954774, -659045697, 2088839751, -592024101, 1949211426, 1368357591, 698141628, 335107981, -1725806105, 374203913, -312767449, 2083254618, -1061175275, -2139105948, 519417371, 1513571050, -647875431, 413299844, -145213459, 0}; - -// INTT with CT butterfly -static const int32_t zetas_inv_asm_769[256] = { - 5585134, 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 5585134, 1736976371, -966228013, 150798592, -346278248, -318352582, -223405321, -759578091, - // removed first "2285" + LAYER 3+2+1 - 1 - butterfly - 5585134, -346278248, 5585134, -966228013, -346278248, -223405321, 636705165, 446810642, 1519156183, 11170266, -821014555, -1932456027, 301597183, -692556495, -240160720, 1061175275, -1368357591, -519417371, -335107981, 2139105948, -698141628, -625534899, -1267825197, 843355087, 290426917, 128458060, 1295750862, -748407825, -826599688, 1736976371, -240160720, 2005062756, 1061175275, 1100271206, -1368357591, 502661972, 915961816, 1396283256, 452395775, -1038834743, -955057747, -670215963, 2016233022, -16755399, -1675539907, 1614103444, -1290165729, 94947261, 753992958, -1591762912, 497076839, -1954796559, 1943626293, -1122611738, -1239899531, 938302348, -245745853, 882451018, -435640376, -966228013, 1736976371, -318352582, -240160720, -1401868389, 2005062756, 1016494210, 714897027, -1005323944, 876865885, 2122350549, -1373942724, -2094424884, 1468889985, 1558252114, -1401868389, -686971362, -357448514, 860110486, 1524741316, -1787242568, -44681064, 1407453522, -368618780, 1323676527, -653460564, -1362772458, 1379527857, -463566041, 1859849297, 150798592, -1675539907, 804259156, 1614103444, -67021596, -1290165729, -139628326, -2060914086, -994153678, 55851330, 189894523, -1072345541, 1507985917, 832184821, 1111441472, 2105595150, -525002504, -1809583100, 212235055, 1938041160, -273671518, 100532394, -2044158687, -78191862, 1452134586, 642290298, -2111180283, 552928169, 161968858, -1167292802, -346278248, -966228013, -223405321, 1736976371, 150798592, -318352582, -759578091, -1608518311, -2032988421, -899206417, -480321440, 943887481, 1491230518, -83776995, -284841784, 2005062756, 1100271206, 502661972, 1669954774, -1139367137, -457980908, 1921285760, 1128196871, -1318091394, -1904530361, 396544445, -1228729265, 117287794, 2116765416, 1184048201, -318352582, -1401868389, 1016494210, -686971362, -1413038655, -357448514, 1709050706, -731652426, 89362128, 2021818155, 1720220972, -1882189829, -1245484665, -798674023, 720482160, 804259156, -67021596, -139628326, -536172770, -1731391238, -1117026605, -27925665, -1843093898, -1971551958, 1027664477, 1776072302, -1692295306, 1977137091, 709311894, 1552666981, -223405321, 150798592, -759578091, -1675539907, 2105595150, 804259156, -1697880440, -675801096, 279256651, 949472614, -1066760408, -1050005009, -134043193, 1262240064, 1714635839, 1016494210, -1413038655, 1709050706, 1206388733, 1748146637, -1781657435, -1010909077, -390959312, -1329261660, -1083515807, -1965966825, -1530326449, 809844289, -1541496715, 1630858843, -759578091, 2105595150, -1697880440, -525002504, 631120032, -1809583100, -474736307, -1575007513, -201064789, 1893360095, 424470110, -1133782004, -418884977, -1424208921, -547343036, -1697880440, 631120032, -474736307, 1580592646, 1435379187, 787503756, 1200803600, 1999477623, -932717215, 1982722224, -1848679031, 586438968, 1993892490, 1625273710, -1346017059, 0}; - -// Q1=769 -void small_ntt_asm_769(int16_t a[N], const int32_t * zetas); -void small_invntt_asm_769(int16_t a[N], const int32_t * zetas); -void small_basemul_asm_769(int16_t *c, const int16_t *a, const int16_t *b, const int32_t *zetas); - -// small NTT for computing cs0 and cs1 -#define small_ntt(a) small_ntt_asm_769(a, zetas_asm_769) -#define small_invntt_tomont(a) small_invntt_asm_769(a, zetas_inv_asm_769) -#define small_basemul(r,a,b) small_basemul_asm_769(r, a, b, zetas_769) - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/smallntt.h b/crypto_sign/dilithium3/m4fstack/smallntt.h new file mode 120000 index 00000000..60f2d18a --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallntt.h @@ -0,0 +1 @@ +../../dilithium2/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallntt_769.S b/crypto_sign/dilithium3/m4fstack/smallntt_769.S deleted file mode 100644 index 1c3c9a88..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallntt_769.S +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Copyright (c) 2023 Junhao Huang (jhhuang_nuaa@126.com) - * - * Licensed under the Apache License, Version 2.0(the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * NTT and inverse NTT code from: - * Huang, J. et al. 2024. Revisiting Keccak and Dilithium Implementations on ARMv7-M. - * IACR Transactions on Cryptographic Hardware and Embedded Systems. 2024, 2 (Mar. 2024), 1–24. - * DOI:https://doi.org/10.46586/tches.v2024.i2.1-24. - * https://github.com/UIC-ESLAS/Dilithium-Multi-Moduli/blob/332a32cc02d407020e48a4f9b3a0dc78d4c8b0bc/M4/crypto_sign/dilithium3/m4plant/smallntt_769.S -*/ - -#include "macros.i" - -.syntax unified -.cpu cortex-m4 -.thumb - -#include "macros_smallntt.i" -// ####### -// ####### -// # NTT # -// ####### -// ####### - -.macro _3_layer_double_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - // layer 3 - ldr.w \twiddle1, [\twiddle_ptr], #4 - two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa - two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa - - // layer 2 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa - - two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa - - // layer 1 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa - - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa -.endm - -.macro _3_layer_double_CT_16_plant_fp c0, c1, c2, c3, c4, c5, c6, c7, xi0, xi1, xi2, xi3, xi4, xi5, xi6, twiddle1, twiddle2, q, qa, tmp - // layer 3 - vmov \twiddle1, \xi0 - two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle1, \tmp, \q, \qa - two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa - - // layer 2 - vmov \twiddle1, \xi1 - vmov \twiddle2, \xi2 - two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa - - two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle2, \twiddle2, \tmp, \q, \qa - - // layer 1 - vmov \twiddle1, \xi3 - vmov \twiddle2, \xi4 - two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa - - vmov \twiddle1, \xi5 - vmov \twiddle2, \xi6 - two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa -.endm - -.global small_ntt_asm_769 -.type small_ntt_asm_769, %function -.align 2 -small_ntt_asm_769: - push {r4-r11, r14} - vpush.w {s16-s24} - poly .req r0 - twiddle_ptr .req r1 - poly0 .req r2 - poly1 .req r3 - poly2 .req r4 - poly3 .req r5 - poly4 .req r6 - poly5 .req r7 - poly6 .req r8 - poly7 .req r9 - twiddle1 .req r10 - twiddle2 .req r11 - ### qinv .req r11 ### q^-1 mod 2^2n; n=16 - q .req r12 - ### at the top of r12 - qa .req r0 - ### qa=2^a q;a=3; at the bottom of r12 - tmp .req r14 - - // movw qa, #24608 - // Why movt? Because we initially placed qa at the bottom of the same register as q; - movt q, #769 - - ### LAYER 7+6+5+4 - .equ distance, 256 - .equ offset, 32 - .equ strincr, 4 - // pre-load 15 twiddle factors to 15 FPU registers - // s0-s7 used to temporary store 16 16-bit polys. - vldm twiddle_ptr!, {s8-s22} - - add tmp, poly, #strincr*8 - // s23: poly addr - // s24: tmp - vmov s24, tmp - 1: - // load a1, a3, ..., a15 - vmov s23, poly - load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset - load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset - - movw qa, #24608 - - // 8-NTT on a1, a3, ..., a15 - _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - - // s15, s16, s17, s18, s19, s20, s21, s22 left - // multiply coeffs by layer 8 twiddles for later use - vmov twiddle1, s15 - vmov twiddle2, s16 - mul_twiddle_plant poly0, twiddle1, tmp, q, qa - mul_twiddle_plant poly1, twiddle2, tmp, q, qa - - vmov twiddle1, s17 - vmov twiddle2, s18 - mul_twiddle_plant poly2, twiddle1, tmp, q, qa - mul_twiddle_plant poly3, twiddle2, tmp, q, qa - - vmov twiddle1, s19 - vmov twiddle2, s20 - mul_twiddle_plant poly4, twiddle1, tmp, q, qa - mul_twiddle_plant poly5, twiddle2, tmp, q, qa - - vmov twiddle1, s21 - vmov twiddle2, s22 - mul_twiddle_plant poly6, twiddle1, tmp, q, qa - mul_twiddle_plant poly7, twiddle2, tmp, q, qa - - vmov s0, poly0 // a1 - vmov s1, poly1 // a3 - vmov s2, poly2 // a5 - vmov s3, poly3 // a7 - vmov s4, poly4 // a9 - vmov s5, poly5 // a11 - vmov s6, poly6 // a13 - vmov s7, poly7 // a15 - - vmov poly, s23 - - // load a0, a2, ..., a14 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #24608 - // 8-NTT on a0, a2, ..., a14 - _3_layer_double_CT_16_plant_fp poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s8, s9, s10, s11, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - - - // layer 4 - 1 - // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) - vmov poly, s23 - vmov twiddle1, s1 // load a3 - uadd16 tmp, poly1, twiddle1 - usub16 poly1, poly1, twiddle1 - str.w tmp, [poly, #1*distance/4] - str.w poly1, [poly, #1*distance/4+offset] - - vmov twiddle1, s3 // load a7 - uadd16 tmp, poly3, twiddle1 - usub16 poly3, poly3, twiddle1 - str.w tmp, [poly, #3*distance/4] - str.w poly3, [poly, #3*distance/4+offset] - - vmov twiddle1, s5 // load a11 - uadd16 tmp, poly5, twiddle1 - usub16 poly5, poly5, twiddle1 - str.w tmp, [poly, #5*distance/4] - str.w poly5, [poly, #5*distance/4+offset] - - vmov twiddle1, s7 // load a15 - uadd16 tmp, poly7, twiddle1 - usub16 poly7, poly7, twiddle1 - str.w tmp, [poly, #7*distance/4] - str.w poly7, [poly, #7*distance/4+offset] - - // layer 4 - 2 - // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) - vmov poly3, s2 // load a5 - uadd16 tmp, poly2, poly3 - usub16 twiddle1, poly2, poly3 - str.w tmp, [poly, #2*distance/4] - str.w twiddle1, [poly, #2*distance/4+offset] - - vmov poly5, s4 // load a9 - uadd16 tmp, poly4, poly5 - usub16 twiddle1, poly4, poly5 - str.w tmp, [poly, #4*distance/4] - str.w twiddle1, [poly, #4*distance/4+offset] - - vmov poly7, s6 // load a13 - uadd16 tmp, poly6, poly7 - usub16 twiddle1, poly6, poly7 - str.w tmp, [poly, #6*distance/4] - str.w twiddle1, [poly, #6*distance/4+offset] - - vmov poly1, s0 // load a1 - uadd16 tmp, poly0, poly1 - usub16 twiddle1, poly0, poly1 - str.w twiddle1, [poly, #offset] - str.w tmp, [poly], #4 - - vmov tmp, s24 - cmp.w poly, tmp - bne.w 1b - - sub.w poly, #8*strincr - - ### LAYER 3+2+1 - - .equ distance, distance/16 - .equ strincr, 32 - - add.w tmp, poly, #strincr*16 - vmov s13, tmp - 2: - vmov s23, poly - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #24608 - _3_layer_double_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - vmov poly, s23 - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #strincr - - vmov tmp, s13 - cmp.w poly, tmp - bne.w 2b - vpop.w {s16-s24} - pop {r4-r11, pc} - -.unreq poly -.unreq twiddle_ptr -.unreq poly0 -.unreq poly1 -.unreq poly2 -.unreq poly3 -.unreq poly4 -.unreq poly5 -.unreq poly6 -.unreq poly7 -.unreq twiddle1 -.unreq twiddle2 -.unreq q -.unreq qa -.unreq tmp - - -// ######## -// ######## -// # INTT # -// ######## -// ######## - -// input: 0.5/1q -.macro _3_layer_double_inv_CT_16_plant_light c0, c1, c2, c3, c4, c5, c6, c7, xi2, xi4, xi5, xi6, twiddle1, tmp2, q, qa, tmp - - // layer 1 - sadd16.w \tmp, \c0, \c1 // c0, c1 - ssub16.w \c1, \c0, \c1 - sadd16.w \tmp2, \c2, \c3 // c2, c3 - ssub16.w \c3, \c2, \c3 - // tmp, c1, tmp2, c3: 1q maximum - sadd16.w \c0, \c4, \c5 // c4, c5 - ssub16.w \c5, \c4, \c5 - sadd16.w \c2, \c6, \c7 // c6, c7 - ssub16.w \c7, \c6, \c7 - // c4, c6 are free at this point - // c0,c5,c2,c7 1q maximum - - // layer 2 - sadd16.w \c6, \tmp, \tmp2 // c0, c2 - ssub16.w \tmp2, \tmp, \tmp2 - sadd16.w \c4, \c0, \c2 // c4, c6 - ssub16.w \c2, \c0, \c2 - // c6, tmp2, c4, c2: 2q maximum - - vmov.w \twiddle1, \xi2 - doublebutterfly_plant \c1, \c3, \twiddle1, \tmp, \q, \qa - doublebutterfly_plant \c5, \c7, \twiddle1, \tmp, \q, \qa - // c1, c3, c7, c5: 1.5q maximum; - - // tmp and c0 are free at this point - // layer 3 - sadd16.w \c0, \c6, \c4 // c0, c4 - ssub16.w \c4, \c6, \c4 - // c0, c4: 4q - // c6 are free at this point - vmov.w \twiddle1, \xi4 - doublebutterfly_plant \c1, \c5, \twiddle1, \tmp, \q, \qa - // c1, c5: 2q maximum - - vmov.w \twiddle1, \xi5 - // this block is one doublebutterfly - smulwb \tmp, \twiddle1, \c2 // c2, c6 - smulwt \c2, \twiddle1, \c2 - smlabt \tmp, \tmp, \q, \qa - smlabt \c2, \c2, \q, \qa - pkhtb \tmp, \c2, \tmp, asr#16 - ssub16.w \c6, \tmp2, \tmp - sadd16.w \c2, \tmp2, \tmp - //c6, c2: 4.5q - vmov.w \twiddle1, \xi6 - doublebutterfly_plant \c3, \c7, \twiddle1, \tmp, \q, \qa - //c3, c7: 2.5q maximum -.endm -.macro _3_layer_double_inv_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - // layer 3 - ldr.w \twiddle1, [\twiddle_ptr], #4 - two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa - two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa - - // layer 2 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa - - two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa - - // layer 1 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle2, \tmp, \q, \qa - - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa -.endm - -.macro _3_layer_double_inv_twist_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c0, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c1, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c2, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c3, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c4, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c5, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c6, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c7, \twiddle2, \tmp, \q, \qa -.endm -# input coefficients < 0.5q -.global small_invntt_asm_769 -.type small_invntt_asm_769, %function -.align 2 -small_invntt_asm_769: - push {r4-r11, r14} - vpush.w {s16-s23} - poly .req r0 - twiddle_ptr .req r1 - poly0 .req r2 - poly1 .req r3 - poly2 .req r4 - poly3 .req r5 - poly4 .req r6 - poly5 .req r7 - poly6 .req r8 - poly7 .req r9 - twiddle1 .req r10 - twiddle2 .req r11 - q .req r12 - // at the top of r12 - qa .req r0 - // qa=2^a q;a=3; at the bottom of r12 - tmp .req r14 - - movt q, #769 - - ### LAYER 7+6+5+4 - .equ distance, 16 - .equ offset, 32 - .equ strincr, 64 - - // pre-load twiddle factors to FPU registers - vldm twiddle_ptr!, {s8-s22} - - add.w tmp, poly, #8*strincr - vmov s8, tmp - 1: - vmov s23, poly - // load a1, a3, ..., a15 - load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset - load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset - - movw qa, #24608 - - // NTT on a1, a3, ..., a15 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - - // multiply coeffs by layer 4 twiddles for later use - // vmov twiddle1, s15 - vmov twiddle2, s16 - // mul_twiddle_plant poly0, twiddle1, tmp, q, qa // could be omitted but kept for reduction only - mul_twiddle_plant poly1, twiddle2, tmp, q, qa - - vmov twiddle1, s17 - vmov twiddle2, s18 - mul_twiddle_plant poly2, twiddle1, tmp, q, qa - mul_twiddle_plant poly3, twiddle2, tmp, q, qa - - vmov twiddle1, s19 - vmov twiddle2, s20 - mul_twiddle_plant poly4, twiddle1, tmp, q, qa - mul_twiddle_plant poly5, twiddle2, tmp, q, qa - - vmov twiddle1, s21 - vmov twiddle2, s22 - mul_twiddle_plant poly6, twiddle1, tmp, q, qa - mul_twiddle_plant poly7, twiddle2, tmp, q, qa - - vmov s0, poly0 // a1 - vmov s1, poly1 // a3 - vmov s2, poly2 // a5 - vmov s3, poly3 // a7 - vmov s4, poly4 // a9 - vmov s5, poly5 // a11 - vmov s6, poly6 // a13 - vmov s7, poly7 // a15 - // 0.5q - // ---------- - - vmov poly, s23 - // load a0, a2, ..., a14 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #24608 - // NTT on a0, a2, ..., a14 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - // 1,3,5,7: <5q; 0,2,4,6:<1q - // layer 4 - 1 - // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) - vmov poly, s23 - vmov twiddle2, s1 // load a3 - uadd16 tmp, poly1, twiddle2 - usub16 poly1, poly1, twiddle2 - str.w tmp, [poly, #1*distance/4] - str.w poly1, [poly, #1*distance/4+offset] - - vmov twiddle2, s3 // load a7 - uadd16 tmp, poly3, twiddle2 - usub16 poly3, poly3, twiddle2 - str.w tmp, [poly, #3*distance/4] - str.w poly3, [poly, #3*distance/4+offset] - - vmov twiddle2, s5 // load a11 - uadd16 tmp, poly5, twiddle2 - usub16 poly5, poly5, twiddle2 - str.w tmp, [poly, #5*distance/4] - str.w poly5, [poly, #5*distance/4+offset] - - vmov twiddle2, s7 // load a15 - uadd16 tmp, poly7, twiddle2 - usub16 poly7, poly7, twiddle2 - str.w tmp, [poly, #7*distance/4] - str.w poly7, [poly, #7*distance/4+offset] - //1,3,5,7: < 5.5q - - // layer 4 - 2 - // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) - vmov poly3, s2 // load a5 - uadd16 tmp, poly2, poly3 - usub16 twiddle2, poly2, poly3 - str.w tmp, [poly, #2*distance/4] - str.w twiddle2, [poly, #2*distance/4+offset] - - vmov poly5, s4 // load a9 - uadd16 tmp, poly4, poly5 - usub16 twiddle2, poly4, poly5 - str.w tmp, [poly, #4*distance/4] - str.w twiddle2, [poly, #4*distance/4+offset] - - vmov poly7, s6 // load a13 - uadd16 tmp, poly6, poly7 - usub16 twiddle2, poly6, poly7 - str.w tmp, [poly, #6*distance/4] - str.w twiddle2, [poly, #6*distance/4+offset] - - vmov poly1, s0 // load a1 - uadd16 tmp, poly0, poly1 - usub16 twiddle2, poly0, poly1 - str.w twiddle2, [poly, #offset] - str.w tmp, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) - //0,2,4,6: < 1.5q - vmov tmp, s8 - cmp.w poly, tmp - bne.w 1b - - sub.w poly, #8*strincr - - ### LAYER 3+2+1 - - .equ distance, distance*16 - .equ strincr, 4 - - // ITER 0 - vmov s6, poly - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - vldm twiddle_ptr!, {s0-s5} - movw qa, #24608 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s1, s3, s4, s5, twiddle1, twiddle2, q, qa, tmp - - // twisting - _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - vmov poly, s6 - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - // ITER 1-15 - add.w tmp, poly, #strincr*3*(5) - vmov s14, tmp - 2: - vmov s6, poly - // polys upto 5.5q - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #24608 - _3_layer_double_inv_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - // twisting - _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - vmov poly, s6 - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - vmov tmp, s14 - cmp.w poly, tmp - bne.w 2b - - vpop.w {s16-s23} - pop {r4-r11, pc} - -.unreq poly -.unreq twiddle_ptr -.unreq poly0 -.unreq poly1 -.unreq poly2 -.unreq poly3 -.unreq poly4 -.unreq poly5 -.unreq poly6 -.unreq poly7 -.unreq twiddle1 -.unreq twiddle2 -.unreq q -.unreq qa -.unreq tmp - -// BASEMUL - -/* -* Basemul code (adapted to q=769) from: -* Huang, J. et al. 2022. Improved Plantard Arithmetic for Lattice-based Cryptography. -* IACR Transactions on Cryptographic Hardware and Embedded Systems. 2022, 4 (Aug. 2022), 614–636. -* DOI:https://doi.org/10.46586/tches.v2022.i4.614-636. -* https://github.com/UIC-ESLAS/ImprovedPlantardArithmetic/blob/f3482cfd09dda8f1f55b95e13616147e3b6dd008/crypto_kem/kyber768/m4fstack/fastbasemul.S -*/ - -.global small_basemul_asm_769 -.type small_basemul_asm_769, %function -.align 2 -small_basemul_asm_769: - push {r4-r11, lr} - - rptr .req r0 - aptr .req r1 - bptr .req r2 - zetaptr .req r3 - poly0 .req r4 - poly1 .req r6 - poly2 .req r5 - poly3 .req r7 - q .req r8 - qa .req r14 - qinv .req r9 - tmp .req r10 - tmp2 .req r11 - zeta .req r12 - loop .req r14 - - movt q, #769 - movw qinv, #64769 - movt qinv, #58632 - - movw loop, #64 - 1: - vmov.w s0,loop - movw qa, #24608 - - ldrd poly0, poly2, [aptr], #8 - ldrd poly1, poly3, [bptr], #8 - // ldr poly0, [aptr], #4 - // ldr poly1, [bptr], #4 - // ldr poly2, [aptr], #4 - // ldr poly3, [bptr], #4 - - ldr.w zeta, [zetaptr], #4 - - // basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, zetas[64 + i]); - smulwt tmp, zeta, poly1 - smlabt tmp, tmp, q, qa - smultt tmp, poly0, tmp - smlabb tmp, poly0, poly1, tmp - plant_red q, qa, qinv, tmp - // r[0] in upper half of tmp - - smuadx tmp2, poly0, poly1 - plant_red q, qa, qinv, tmp2 - // r[1] in upper half of tmp2 - pkhtb tmp, tmp2, tmp, asr#16 - str tmp, [rptr], #4 - - neg zeta, zeta - - // basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - zetas[64 + i]); - smulwt tmp, zeta, poly3 - smlabt tmp, tmp, q, qa - smultt tmp, poly2, tmp - smlabb tmp, poly2, poly3, tmp - plant_red q, qa, qinv, tmp - // r[0] in upper half of tmp - - smuadx tmp2, poly2, poly3 - plant_red q, qa, qinv, tmp2 - // r[1] in upper half of tmp2 - pkhtb tmp, tmp2, tmp, asr#16 - str tmp, [rptr], #4 - - vmov.w loop,s0 - subs.w loop, #1 - bne.w 1b - - .unreq rptr - .unreq aptr - .unreq bptr - .unreq zetaptr - .unreq poly0 - .unreq poly1 - .unreq poly2 - .unreq poly3 - .unreq q - .unreq qa - .unreq qinv - .unreq tmp - .unreq tmp2 - .unreq zeta - .unreq loop - - pop {r4-r11, pc} -//-0.5p~0.5p \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallntt_769.S b/crypto_sign/dilithium3/m4fstack/smallntt_769.S new file mode 120000 index 00000000..4ae2f9bb --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallntt_769.S @@ -0,0 +1 @@ +../../dilithium2/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.c b/crypto_sign/dilithium3/m4fstack/smallpoly.c deleted file mode 100644 index 433d98af..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallpoly.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "smallpoly.h" -#include "smallntt.h" - -void poly_small_ntt_copy(smallpoly *out, poly *in) { - for (int i = N - 1; i >= 0; i--) - { - out->coeffs[i] = in->coeffs[i]; - } - small_ntt(out->coeffs); -} - - -void polyvecl_small_ntt(smallpoly v[L]) { - unsigned int i; - - for(i = 0; i < L; ++i) - small_ntt(v[i].coeffs); -} - - -void polyveck_small_ntt(smallpoly v[K]) { - unsigned int i; - - for(i = 0; i < K; ++i) - small_ntt(v[i].coeffs); -} - - - -void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b){ - // re-use the buffer - smallpoly *tmp = (smallpoly *)r; - small_basemul(tmp->coeffs, a->coeffs, b->coeffs); - small_invntt_tomont(tmp->coeffs); - - #ifdef SMALL_POLY_16_BIT - int j; - // buffer is the same, so we neeed to be careful - for(j=N-1;j>=0;j--){ - r->coeffs[j] = tmp->coeffs[j]; - } - #endif -} - -void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]){ - unsigned int i; - for(i=0;ivec[i], a, &b[i]); - } -} - -void small_polyeta_unpack(smallpoly *r, const uint8_t *a) { - unsigned int i; - -#if ETA == 2 - for(i = 0; i < N/8; ++i) { - r->coeffs[8*i+0] = (a[3*i+0] >> 0) & 7; - r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 7; - r->coeffs[8*i+2] = ((a[3*i+0] >> 6) | (a[3*i+1] << 2)) & 7; - r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 7; - r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 7; - r->coeffs[8*i+5] = ((a[3*i+1] >> 7) | (a[3*i+2] << 1)) & 7; - r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 7; - r->coeffs[8*i+7] = (a[3*i+2] >> 5) & 7; - - r->coeffs[8*i+0] = ETA - r->coeffs[8*i+0]; - r->coeffs[8*i+1] = ETA - r->coeffs[8*i+1]; - r->coeffs[8*i+2] = ETA - r->coeffs[8*i+2]; - r->coeffs[8*i+3] = ETA - r->coeffs[8*i+3]; - r->coeffs[8*i+4] = ETA - r->coeffs[8*i+4]; - r->coeffs[8*i+5] = ETA - r->coeffs[8*i+5]; - r->coeffs[8*i+6] = ETA - r->coeffs[8*i+6]; - r->coeffs[8*i+7] = ETA - r->coeffs[8*i+7]; - } -#elif ETA == 4 - for(i = 0; i < N/2; ++i) { - r->coeffs[2*i+0] = a[i] & 0x0F; - r->coeffs[2*i+1] = a[i] >> 4; - r->coeffs[2*i+0] = ETA - r->coeffs[2*i+0]; - r->coeffs[2*i+1] = ETA - r->coeffs[2*i+1]; - } -#endif -} diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.c b/crypto_sign/dilithium3/m4fstack/smallpoly.c new file mode 120000 index 00000000..9c350567 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallpoly.c @@ -0,0 +1 @@ +../../dilithium2/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.h b/crypto_sign/dilithium3/m4fstack/smallpoly.h deleted file mode 100644 index 1aac98fa..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallpoly.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SMALLPOLY_H -#define SMALLPOLY_H -#include "params.h" -#include "poly.h" -#include "polyvec.h" - - - -#define SMALL_POLY_16_BIT -typedef struct { - int16_t coeffs[N]; -} smallpoly; - -typedef smallpoly smallhalfpoly; - -void poly_small_ntt_copy(smallpoly*, poly*); - -void polyvecl_small_ntt(smallpoly v[L]); -void polyveck_small_ntt(smallpoly v[K]); - - -void polyvecl_small_basemul_invntt(polyvecl *r, const smallpoly *a, const smallpoly b[L]); -void poly_small_basemul_invntt(poly *r, const smallpoly *a, const smallpoly *b); - -void small_polyeta_unpack(smallpoly *r, const uint8_t *a); - -#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.h b/crypto_sign/dilithium3/m4fstack/smallpoly.h new file mode 120000 index 00000000..45701a42 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/smallpoly.h @@ -0,0 +1 @@ +../../dilithium2/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.c b/crypto_sign/dilithium3/m4fstack/stack.c deleted file mode 100644 index b45f7021..00000000 --- a/crypto_sign/dilithium3/m4fstack/stack.c +++ /dev/null @@ -1,715 +0,0 @@ -#include "stack.h" -#include "fips202.h" -#include "symmetric.h" -#include "vector.h" -#include "reduce.h" -#include "rounding.h" - -void poly_challenge_compress(uint8_t c[68], const poly *cp){ - unsigned int i, pos; - uint64_t signs; - uint64_t mask; - /* Encode c */ - for(i=0;i<68;i++) c[i] = 0; - signs = 0; - mask = 1; - pos = 0; - for(i = 0; i < N; ++i){ - if(cp->coeffs[i] != 0){ - c[pos++] = i; - if(cp->coeffs[i] == -1){ - signs |= mask; - } - mask <<= 1; - } - } - - for (i = 0; i < 8; ++i) { - c[60+i] = (unsigned char) (signs >> 8 * i); - } -} - -void poly_challenge_decompress(poly *cp, const uint8_t c[68]){ - unsigned int i; - unsigned pos; - uint64_t signs = 0; - for(i = 0; i < N; i++) cp->coeffs[i] = 0; - for(i = 0; i < 8; i++) { - signs |= ((uint64_t)c[60+i]) << (8*i); - } - - for(i = 0; i < TAU; i++){ - pos = c[i]; - if(signs & 1){ - cp->coeffs[pos] = -1; - } else { - cp->coeffs[pos] = 1; - } - signs >>= 1; - } -} - - -// TODO: buffer at most 8 coeffs at once -static inline int32_t polyt0_unpack_idx(const uint8_t *t0, unsigned idx){ - int32_t coeff; - // 8 coefficients are packed in 13 bytes - t0 += 13*(idx >> 3); - - if(idx % 8 == 0){ - coeff = t0[0]; - coeff |= (uint32_t)t0[1] << 8; - } else if(idx % 8 == 1){ - coeff = t0[1] >> 5; - coeff |= (uint32_t)t0[2] << 3; - coeff |= (uint32_t)t0[3] << 11; - } else if(idx % 8 == 2){ - coeff = t0[3] >> 2; - coeff |= (uint32_t)t0[4] << 6; - } else if(idx % 8 == 3){ - coeff = t0[4] >> 7; - coeff |= (uint32_t)t0[5] << 1; - coeff |= (uint32_t)t0[6] << 9; - } else if(idx % 8 == 4){ - coeff = t0[6] >> 4; - coeff |= (uint32_t)t0[7] << 4; - coeff |= (uint32_t)t0[8] << 12; - } else if(idx % 8 == 5){ - coeff = t0[8] >> 1; - coeff |= (uint32_t)t0[9] << 7; - } else if(idx % 8 == 6){ - coeff = t0[9] >> 6; - coeff |= (uint32_t)t0[10] << 2; - coeff |= (uint32_t)t0[11] << 10; - } else if(idx % 8 == 7){ - coeff = t0[11] >> 3; - coeff |= (uint32_t)t0[12] << 5; - } - coeff &= 0x1FFF; - return (1 << (D-1)) - coeff; -} - -static inline int32_t polyt1_unpack_idx(const uint8_t *t1, unsigned idx){ - int32_t coeff; - // 4 coefficients are packed in 5 bytes - t1 += 5*(idx >> 2); - - if(idx % 4 == 0){ - coeff = (t1[0] >> 0); - coeff |= ((uint32_t)t1[1] << 8); - } else if(idx % 4 == 1){ - coeff = (t1[1] >> 2); - coeff |= ((uint32_t)t1[2] << 6); - } else if(idx % 4 == 2){ - coeff = (t1[2] >> 4); - coeff |= ((uint32_t)t1[3] << 4); - } else if(idx % 4 == 3){ - coeff = (t1[3] >> 6); - coeff |= ((uint32_t)t1[4] << 2); - } - coeff &= 0x3FF; - return coeff; -} - -void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0){ - unsigned i,j,idx; - uint64_t signs = 0; - for(i = 0; i < N; i++) c->coeffs[i] = 0; - for(i = 0; i < 8; i++) { - signs |= ((uint64_t)ccomp[60+i]) << (8*i); - } - - for(idx = 0; idx < TAU; idx++){ - i = ccomp[idx]; - if(!(signs & 1)){ - for(j = 0; i+j < N; j++){ - c->coeffs[i+j] += polyt0_unpack_idx(t0, j); - } - for(j = N-i; jcoeffs[i+j-N] -= polyt0_unpack_idx(t0, j); - } - } else { - for(j = 0; i+j < N; j++){ - c->coeffs[i+j] -= polyt0_unpack_idx(t0, j); - } - for(j = N-i; jcoeffs[i+j-N] += polyt0_unpack_idx(t0, j); - } - } - - signs >>= 1; - } -} - -void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1){ - unsigned i,j,idx; - uint64_t signs = 0; - for(i = 0; i < N; i++) c->coeffs[i] = 0; - for(i = 0; i < 8; i++) { - signs |= ((uint64_t)ccomp[60+i]) << (8*i); - } - - for(idx = 0; idx < TAU; idx++){ - i = ccomp[idx]; - if(!(signs & 1)){ - for(j = 0; i+j < N; j++){ - c->coeffs[i+j] += (polyt1_unpack_idx(t1, j) << D); - } - for(j = N-i; jcoeffs[i+j-N] -= (polyt1_unpack_idx(t1, j) << D); - } - } else { - for(j = 0; i+j < N; j++){ - c->coeffs[i+j] -= (polyt1_unpack_idx(t1, j) << D); - } - for(j = N-i; jcoeffs[i+j-N] += (polyt1_unpack_idx(t1, j) << D); - } - } - - signs >>= 1; - } -} - - -void polyw_pack(uint8_t buf[3*256], poly *w){ - poly_reduce(w); - poly_caddq(w); - unsigned int i; - for(i = 0; i < N; i++){ - buf[i*3 + 0] = w->coeffs[i]; - buf[i*3 + 1] = w->coeffs[i] >> 8; - buf[i*3 + 2] = w->coeffs[i] >> 16; - } -} - -void polyw_unpack(poly *w, const uint8_t buf[3*256]) { - unsigned int i; - for(i = 0; i < N; i++){ - w->coeffs[i] = buf[i*3 + 0]; - w->coeffs[i] |= (int32_t)buf[i*3 + 1] << 8; - w->coeffs[i] |= (int32_t)buf[i*3 + 2] << 16; - } -} - - -static void polyw_add_idx(uint8_t buf[3*256], int32_t a, size_t i){ - int32_t coeff; - coeff = buf[i*3 + 0]; - coeff |= (int32_t)buf[i*3 + 1] << 8; - coeff |= (int32_t)buf[i*3 + 2] << 16; - - coeff += a; - - coeff = freeze(coeff); - - buf[i*3 + 0] = coeff; - buf[i*3 + 1] = coeff >> 8; - buf[i*3 + 2] = coeff >> 16; -} - -void polyw_add(uint8_t buf[3*256], poly *p){ - unsigned int i; - for(i = 0; i < N; i++){ - polyw_add_idx(buf, p->coeffs[i], i); - } -} -void polyw_sub(poly* c, uint8_t buf[3*256], poly *a){ - int32_t coeff; - - - for(size_t i=0;icoeffs[i] = coeff - a->coeffs[i]; - } -} - -static int32_t highbits(int32_t a){ - int32_t a1; - - a1 = (a + 127) >> 7; -#if GAMMA2 == (Q-1)/32 - a1 = (a1*1025 + (1 << 21)) >> 22; - a1 &= 15; -#elif GAMMA2 == (Q-1)/88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; -#endif - - return a1; -} - -void poly_highbits(poly *a1, const poly *a) { - unsigned int i; - - for(i = 0; i < N; ++i) - a1->coeffs[i] = highbits(a->coeffs[i]); -} - -static int32_t lowbits(int32_t a){ - int32_t a1; - int32_t a0; - - a1 = (a + 127) >> 7; -#if GAMMA2 == (Q-1)/32 - a1 = (a1*1025 + (1 << 21)) >> 22; - a1 &= 15; -#elif GAMMA2 == (Q-1)/88 - a1 = (a1*11275 + (1 << 23)) >> 24; - a1 ^= ((43 - a1) >> 31) & a1; -#endif - - a0 = a - a1*2*GAMMA2; - a0 -= (((Q-1)/2 - a0) >> 31) & Q; - return a0; -} - -void poly_lowbits(poly *a0, const poly *a){ - unsigned int i; - - for(i = 0; i < N; ++i) - a0->coeffs[i] = lowbits(a->coeffs[i]); -} - -void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx) { - small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + idx*POLYETA_PACKEDBYTES); -} -void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx) { - small_polyeta_unpack(a, sk + 2*SEEDBYTES + TRBYTES + L*POLYETA_PACKEDBYTES + idx*POLYETA_PACKEDBYTES); -} - - -// TODO: in the end increase this buffer size as far as possible -#define POLY_UNIFORM_BUFFERSIZE 3 -void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state){ - int32_t t; - uint8_t buf[POLY_UNIFORM_BUFFERSIZE*3]; - { - size_t ctr = 0; - stream128_init(state, seed, nonce); - - do { - shake128_inc_squeeze(buf, sizeof buf, state); - - for(size_t pos=0; pos < sizeof buf && ctr < N; pos += 3){ - t = buf[pos]; - t |= (uint32_t)buf[pos+1] << 8; - t |= (uint32_t)buf[pos+2] << 16; - t &= 0x7FFFFF; - - if(t < Q) { - t = montgomery_reduce((int64_t)t * b->coeffs[ctr]); - polyw_add_idx(wcomp, t, ctr); - ctr++; - } - } - } while(ctr < N); - - } -} - -#define POLY_UNIFORM_GAMMA1_BUFFERSIZE 1 -#if GAMMA1 == (1 << 17) -#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*4) -#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*9) -#elif GAMMA1 == (1 << 19) -#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS (POLY_UNIFORM_GAMMA1_BUFFERSIZE*2) -#define POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES (POLY_UNIFORM_GAMMA1_BUFFERSIZE*5) -#endif - -static void polyz_unpack_inplace(int32_t *r){ - uint8_t *a = (uint8_t *)r; - - unsigned int i,j; - #if GAMMA1 == (1 << 17) - for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { - i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; - int32_t t0; - - - r[4*i+3] = a[9*i+6] >> 6; - r[4*i+3] |= (uint32_t)a[9*i+7] << 2; - r[4*i+3] |= (uint32_t)a[9*i+8] << 10; - r[4*i+3] &= 0x3FFFF; - - r[4*i+2] = a[9*i+4] >> 4; - r[4*i+2] |= (uint32_t)a[9*i+5] << 4; - r[4*i+2] |= (uint32_t)a[9*i+6] << 12; - r[4*i+2] &= 0x3FFFF; - - - r[4*i+1] = (uint32_t)a[9*i+4] << 14; - r[4*i+1] |= a[9*i+2] >> 2; - r[4*i+1] |= (uint32_t)a[9*i+3] << 6; - r[4*i+1] &= 0x3FFFF; - - t0 = a[9*i+0]; - t0 |= (uint32_t)a[9*i+1] << 8; - t0 |= (uint32_t)a[9*i+2] << 16; - t0 &= 0x3FFFF; - - r[4*i+0] = GAMMA1 - t0; - r[4*i+1] = GAMMA1 - r[4*i+1]; - r[4*i+2] = GAMMA1 - r[4*i+2]; - r[4*i+3] = GAMMA1 - r[4*i+3]; - - } -#elif GAMMA1 == (1 << 19) - for(j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE; ++j) { - i = POLY_UNIFORM_GAMMA1_BUFFERSIZE-1-j; - int32_t tmp0, tmp1; - - tmp0 = a[5*i+2] >> 4; - tmp0 |= (uint32_t)a[5*i+3] << 4; - tmp0 |= (uint32_t)a[5*i+4] << 12; - tmp0 &= 0xFFFFF; - - tmp1 = a[5*i+0]; - tmp1 |= (uint32_t)a[5*i+1] << 8; - tmp1 |= (uint32_t)a[5*i+2] << 16; - tmp1 &= 0xFFFFF; - - r[2*i+0] = GAMMA1 - tmp1; - r[2*i+1] = GAMMA1 - tmp0; - } -#endif -} - -void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ - int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; - - stream256_init(state, seed, nonce); - for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ - shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); - polyz_unpack_inplace(buf); - - for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ - a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j]; - } - } -} - -void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state){ - int32_t buf[POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS]; - - stream256_init(state, seed, nonce); - for(size_t i = 0; i < N/POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; i++){ - shake256_inc_squeeze((uint8_t *)buf, POLY_UNIFORM_GAMMA1_BUFFERSIZE_BYTES, state); - polyz_unpack_inplace(buf); - - for(size_t j = 0; j < POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS; j++){ - a->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j] = buf[j] + b->coeffs[i*POLY_UNIFORM_GAMMA1_BUFFERSIZE_COEFFS + j]; - } - } -} - - -static inline int32_t make_hint_stack(int32_t z, int32_t r){ - int32_t r1, v1; - - r1 = highbits(r); - v1 = highbits(r+z); - - if(r1 != v1) return 1; - return 0; -} - -size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]){ - int32_t coeff; - size_t hints_n = 0; - for(size_t i=0;icoeffs[i]; - - a->coeffs[i] = make_hint_stack(-t->coeffs[i], coeff); - if(a->coeffs[i] == 1){ - hints_n++; - } - } - return hints_n; -} - -void unpack_sk_stack(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - key[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - tr[i] = sk[i]; - sk += TRBYTES; -} - -/************************************************* -* Name: unpack_sig_h_indices -* -* Description: Unpack only h from signature sig = (c, z, h). -* -* Arguments: - polyveck *h: pointer to output hint vector h -* - const unsigned char sig[]: byte array containing -* bit-packed signature -* -* Returns 1 in case of malformed signature; otherwise 0. -**************************************************/ -int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]) { - sig += L * POLYZ_PACKEDBYTES; - sig += CTILDEBYTES; - /* Decode h */ - unsigned int k = 0; - unsigned int hidx = 0; - - if (idx > 0) - { - k = sig[OMEGA + (idx - 1)]; - } - - if (sig[OMEGA + idx] < k || sig[OMEGA + idx] > OMEGA) { - return 1; - } - - for (unsigned int j = k; j < sig[OMEGA + idx]; ++j) { - /* Coefficients are ordered for strong unforgeability */ - if (j > k && sig[j] <= sig[j - 1]) { - return 1; - } - h_i[hidx++] = sig[j]; - } - - *number_of_hints = hidx; - - /* TODO: extract this check, redundant here */ - k = sig[OMEGA + (K - 1)]; - /* Extra indices are zero for strong unforgeability */ - for (unsigned int j = k; j < OMEGA; ++j) { - if (sig[j]) { - return 1; - } - } - return 0; -} - -/************************************************* -* Name: poly_use_hint_stack -* -* Description: Use hint polynomial to correct the high bits of a polynomial. -* -* Arguments: - poly *b: pointer to output polynomial with corrected high bits -* - const poly *a: pointer to input polynomial -* - const poly *h: pointer to input hint polynomial -**************************************************/ -void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints) { - unsigned int i; - unsigned int in_list; - - for(i = 0; i < N; ++i) - { - in_list = 0; - for (size_t hidx = 0; hidx < number_of_hints; hidx++) - { - if (i == h_i[hidx]) - { - in_list = 1; - break; - } - } - if (in_list) - { - b->coeffs[i] = use_hint(a->coeffs[i], 1); - } - else - { - b->coeffs[i] = use_hint(a->coeffs[i], 0); - } - - } -} - -/************************************************* -* Name: pack_pk_rho -* -* Description: Bit-pack only rho in public key pk = (rho, t1). -* -* Arguments: - unsigned char pk[]: output byte array -* - const unsigned char rho[]: byte array containing rho -**************************************************/ -void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], - const unsigned char rho[SEEDBYTES]) { - for (unsigned int i = 0; i < SEEDBYTES; ++i) { - pk[i] = rho[i]; - } -} - -/************************************************* -* Name: pack_pk_t1 -* -* Description: Bit-pack only the t1 elem at idx in public key pk = (rho, t1). -* -* Arguments: - unsigned char pk[]: output byte array -* - const polyveck *t1: pointer to vector t1 -* - const unsigned int idx: index to the elem to pack -**************************************************/ -void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], - const poly *t1, - const unsigned int idx) { - pk += SEEDBYTES; - polyt1_pack(pk + idx * POLYT1_PACKEDBYTES, t1); -} - -/************************************************* -* Name: pack_sk_s1 -* -* Description: Bit-pack only some element of s1 in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const poly *s1_elem: pointer to vector element idx in s1 -* - const unisgned int idx: index to the element of s1 that should be packed -**************************************************/ -void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *s1_elem, - const unsigned int idx) { - sk += 2 * SEEDBYTES + TRBYTES; - polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s1_elem); -} - -/************************************************* -* Name: pack_sk_s2 -* -* Description: Bit-pack only some element of s2 in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const poly *s2_elem: pointer to vector element idx in s2 -* - const unsigned int idx: index to the element of s1 that should be packed -**************************************************/ -void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *s2_elem, - const unsigned int idx) { - sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES; - polyeta_pack(sk + idx * POLYETA_PACKEDBYTES, s2_elem); -} - -/************************************************* -* Name: pack_sk_t0 -* -* Description: Bit-pack only some element of t0 in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const poly *t0_elem: pointer to vector element idx in s2 -* - const unsigned int idx: index to the element of s1 that should be packed -**************************************************/ -void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *t0_elem, - const unsigned int idx) { - sk += 2 * SEEDBYTES + TRBYTES + L * POLYETA_PACKEDBYTES + K * POLYETA_PACKEDBYTES; - polyt0_pack(sk + idx * POLYT0_PACKEDBYTES, t0_elem); -} - -/************************************************* -* Name: pack_sk_rho -* -* Description: Bit-pack only rho in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const unsigned char rho[]: byte array containing rho -**************************************************/ -void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char rho[SEEDBYTES]) { - for (unsigned int i = 0; i < SEEDBYTES; ++i) { - sk[i] = rho[i]; - } -} - -/************************************************* -* Name: pack_sk_key -* -* Description: Bit-pack only key in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const unsigned char key[]: byte array containing key -**************************************************/ -void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char key[SEEDBYTES]) { - sk += SEEDBYTES; - for (unsigned int i = 0; i < SEEDBYTES; ++i) { - sk[i] = key[i]; - } -} - -/************************************************* -* Name: pack_sk_tr -* -* Description: Bit-pack only tr in secret key sk = (rho, key, tr, s1, s2, t0). -* -* Arguments: - unsigned char sk[]: output byte array -* - const unsigned char tr[]: byte array containing tr -**************************************************/ -void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char tr[TRBYTES]) { - sk += 2*SEEDBYTES; - for (unsigned int i = 0; i < TRBYTES; ++i) { - sk[i] = tr[i]; - } -} - -/************************************************* -* Name: challenge -* -* Description: Implementation of H. Samples polynomial with TAU nonzero -* coefficients in {-1,1} using the output stream of -* SHAKE256(seed). Stack optimized. -* -* Arguments: - poly *c: pointer to output polynomial -* - const uint8_t mu[]: byte array containing seed of length SEEDBYTES -**************************************************/ -#define CHALLENGE_STACK_BUF_SIZE 8 -void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]) { - unsigned int i, b, pos; - uint64_t signs; - uint8_t buf[CHALLENGE_STACK_BUF_SIZE]; - shake256incctx state; - - shake256_inc_init(&state); - shake256_inc_absorb(&state, seed, SEEDBYTES); - shake256_inc_finalize(&state); - shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); - signs = 0; - for(i = 0; i < 8; ++i) - { - signs |= (uint64_t)buf[i] << 8*i; - } - pos = 8; - - for(i = 0; i < N; ++i) - c->coeffs[i] = 0; - for(i = N-TAU; i < N; ++i) { - do { - if(pos >= CHALLENGE_STACK_BUF_SIZE) { - shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); - pos = 0; - } - - b = buf[pos++]; - } while(b > i); - - c->coeffs[i] = c->coeffs[b]; - c->coeffs[b] = 1 - 2*(signs & 1); - signs >>= 1; - } -} \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.c b/crypto_sign/dilithium3/m4fstack/stack.c new file mode 120000 index 00000000..d25ed6f7 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/stack.c @@ -0,0 +1 @@ +../../dilithium2/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.h b/crypto_sign/dilithium3/m4fstack/stack.h deleted file mode 100644 index 06c8c576..00000000 --- a/crypto_sign/dilithium3/m4fstack/stack.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef STACK_H -#define STACK_H - -#include "poly.h" -#include "smallpoly.h" -#include -#include -#include "fips202.h" - -void poly_challenge_compress(uint8_t c[68], const poly *cp); -void poly_challenge_decompress(poly *cp, const uint8_t c[68]); - - -void poly_schoolbook(poly *c, const uint8_t ccomp[68], const uint8_t *t0); -void poly_schoolbook_t1(poly *c, const uint8_t ccomp[68], const uint8_t *t1); -void polyw_pack(uint8_t buf[3*256], poly *w); -void polyw_unpack(poly *w, const uint8_t buf[3*256]); - -void polyw_add(uint8_t buf[3*256], poly *p); -void polyw_sub(poly* c, uint8_t buf[3*256], poly *a); - -void poly_highbits(poly *a1, const poly *a); -void poly_lowbits(poly *a0, const poly *a); - -void unpack_sk_s1(smallpoly *a, const uint8_t *sk, size_t idx); -void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx); - -void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state); -void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); -void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); -void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]); - -size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]); -int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]); -void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints); - -void unpack_sk_stack(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - -void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], - const unsigned char rho[SEEDBYTES]); - -void pack_pk_t1(unsigned char pk[CRYPTO_PUBLICKEYBYTES], - const poly *t1, - const unsigned int idx); - -void pack_sk_s1(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *s1_elem, - const unsigned int idx); - -void pack_sk_s2(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *s2_elem, - const unsigned int idx); - -void pack_sk_t0(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const poly *t0_elem, - const unsigned int idx); - -void pack_sk_rho(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char rho[SEEDBYTES]); - -void pack_sk_key(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char key[SEEDBYTES]); - -void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], - const unsigned char tr[TRBYTES]); -#endif \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.h b/crypto_sign/dilithium3/m4fstack/stack.h new file mode 120000 index 00000000..beab8ca2 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/stack.h @@ -0,0 +1 @@ +../../dilithium2/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c deleted file mode 100644 index 963f6498..00000000 --- a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "params.h" -#include "symmetric.h" -#include "fips202.h" - -void dilithium_shake128_stream_init(shake128incctx *state, const uint8_t seed[SEEDBYTES], uint16_t nonce) -{ - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake128_inc_init(state); - shake128_inc_absorb(state, seed, SEEDBYTES); - shake128_inc_absorb(state, t, 2); - shake128_inc_finalize(state); -} - -void dilithium_shake256_stream_init(shake256incctx *state, const uint8_t seed[CRHBYTES], uint16_t nonce) -{ - uint8_t t[2]; - t[0] = nonce; - t[1] = nonce >> 8; - - shake256_inc_init(state); - shake256_inc_absorb(state, seed, CRHBYTES); - shake256_inc_absorb(state, t, 2); - shake256_inc_finalize(state); -} diff --git a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c new file mode 120000 index 00000000..6ad80541 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c @@ -0,0 +1 @@ +../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/symmetric.h b/crypto_sign/dilithium3/m4fstack/symmetric.h deleted file mode 100644 index 47037377..00000000 --- a/crypto_sign/dilithium3/m4fstack/symmetric.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef SYMMETRIC_H -#define SYMMETRIC_H - -#include -#include "params.h" - -#ifdef DILITHIUM_USE_AES - -#include "aes256ctr.h" -#include "fips202.h" - -typedef aes256ctr_ctx stream128_state; -typedef aes256ctr_ctx stream256_state; - -#define dilithium_aes256ctr_init DILITHIUM_NAMESPACE(dilithium_aes256ctr_init) -void dilithium_aes256ctr_init(aes256ctr_ctx *state, - const uint8_t key[32], - uint16_t nonce); - -#define STREAM128_BLOCKBYTES AES256CTR_BLOCKBYTES -#define STREAM256_BLOCKBYTES AES256CTR_BLOCKBYTES - -#define stream128_init(STATE, SEED, NONCE) \ - dilithium_aes256ctr_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - dilithium_aes256ctr_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - aes256ctr_squeezeblocks(OUT, OUTBLOCKS, STATE) - -#else - -#include "fips202.h" -typedef shake128incctx stream128_state; -typedef shake256incctx stream256_state; - -#define shake256_inc_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_inc_squeeze(OUT, OUTBLOCKS*SHAKE256_RATE, STATE) - -#define dilithium_shake128_stream_init DILITHIUM_NAMESPACE(dilithium_shake128_stream_init) -void dilithium_shake128_stream_init(stream128_state *state, - const uint8_t seed[SEEDBYTES], - uint16_t nonce); - -#define dilithium_shake256_stream_init DILITHIUM_NAMESPACE(dilithium_shake256_stream_init) -void dilithium_shake256_stream_init(stream256_state *state, - const uint8_t seed[CRHBYTES], - uint16_t nonce); - -#define STREAM128_BLOCKBYTES SHAKE128_RATE -#define STREAM256_BLOCKBYTES SHAKE256_RATE - -#define stream128_init(STATE, SEED, NONCE) \ - dilithium_shake128_stream_init(STATE, SEED, NONCE) -#define stream128_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake128_inc_squeeze(OUT, OUTBLOCKS*SHAKE128_RATE, STATE) -#define stream256_init(STATE, SEED, NONCE) \ - dilithium_shake256_stream_init(STATE, SEED, NONCE) -#define stream256_squeezeblocks(OUT, OUTBLOCKS, STATE) \ - shake256_inc_squeeze(OUT, OUTBLOCKS*SHAKE256_RATE, STATE) - -#endif - -#endif diff --git a/crypto_sign/dilithium3/m4fstack/symmetric.h b/crypto_sign/dilithium3/m4fstack/symmetric.h new file mode 120000 index 00000000..90ad5c07 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/symmetric.h @@ -0,0 +1 @@ +../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/vector.h b/crypto_sign/dilithium3/m4fstack/vector.h deleted file mode 100644 index e5c5dda3..00000000 --- a/crypto_sign/dilithium3/m4fstack/vector.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef VECTOR_H -#define VECTOR_H - -#include -#include "params.h" - -#define asm_reduce32 DILITHIUM_NAMESPACE(asm_reduce32) -void asm_reduce32(int32_t a[N]); -#define small_asm_reduce32_central DILITHIUM_NAMESPACE(small_asm_reduce32_central) -void small_asm_reduce32_central(int32_t a[N]); -#define asm_caddq DILITHIUM_NAMESPACE(asm_caddq) -void asm_caddq(int32_t a[N]); -#define asm_freeze DILITHIUM_NAMESPACE(asm_freeze) -void asm_freeze(int32_t a[N]); -#define asm_rej_uniform DILITHIUM_NAMESPACE(asm_rej_uniform) -unsigned int asm_rej_uniform(int32_t *a, - unsigned int len, - const unsigned char *buf, - unsigned int buflen); -#endif diff --git a/crypto_sign/dilithium3/m4fstack/vector.h b/crypto_sign/dilithium3/m4fstack/vector.h new file mode 120000 index 00000000..6e2280f0 --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/vector.h @@ -0,0 +1 @@ +../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/vector.s b/crypto_sign/dilithium3/m4fstack/vector.s deleted file mode 100644 index 559f11b0..00000000 --- a/crypto_sign/dilithium3/m4fstack/vector.s +++ /dev/null @@ -1,210 +0,0 @@ -.syntax unified -.thumb -.macro redq a, tmp, q - add \tmp, \a, #4194304 - asrs \tmp, \tmp, #23 - mls \a, \tmp, \q, \a -.endm - -// void asm_reduce32(int32_t a[N]); -.global pqcrystals_dilithium_asm_reduce32 -.type pqcrystals_dilithium_asm_reduce32, %function -.align 2 -pqcrystals_dilithium_asm_reduce32: - push {r4-r10} - - movw r12,#:lower16:8380417 - movt r12,#:upper16:8380417 - movw r10, #32 - 1: - ldr.w r1, [r0] - ldr.w r2, [r0, #1*4] - ldr.w r3, [r0, #2*4] - ldr.w r4, [r0, #3*4] - ldr.w r5, [r0, #4*4] - ldr.w r6, [r0, #5*4] - ldr.w r7, [r0, #6*4] - ldr.w r8, [r0, #7*4] - - redq r1, r9, r12 - redq r2, r9, r12 - redq r3, r9, r12 - redq r4, r9, r12 - redq r5, r9, r12 - redq r6, r9, r12 - redq r7, r9, r12 - redq r8, r9, r12 - - str.w r2, [r0, #1*4] - str.w r3, [r0, #2*4] - str.w r4, [r0, #3*4] - str.w r5, [r0, #4*4] - str.w r6, [r0, #5*4] - str.w r7, [r0, #6*4] - str.w r8, [r0, #7*4] - str r1, [r0], #8*4 - subs r10, #1 - bne.w 1b - - pop {r4-r10} - bx lr -.size pqcrystals_dilithium_asm_reduce32, .-pqcrystals_dilithium_asm_reduce32 - -.macro barrett_32 a, Qbar, Q, tmp - smmulr.w \tmp, \a, \Qbar - mls.w \a, \tmp, \Q, \a -.endm - -// INPUT: target (signed), KYBER_Q (signed) -// OUTPUT: target adjusted to be between -KYBER_Q/2 and KYBER_Q/2 -.macro central_reduce target, Q - cmp \target, \Q, lsr #1 - it hi - subhi \target, \Q - cmn \target, \Q, lsr #1 - it lt - addlt \target, \Q -.endm - -// void asm_reduce32(int32_t a[N]); -.global pqcrystals_dilithium_small_asm_reduce32_central -.type pqcrystals_dilithium_small_asm_reduce32_central, %function -.align 2 -pqcrystals_dilithium_small_asm_reduce32_central: - push {r4-r12, lr} - - - movw r9, #:lower16:5585133 - movt r9, #:upper16:5585133 - mov.w r10,#769 - - movw r12, #32 - 1: - ldr.w r1, [r0] - ldr.w r2, [r0, #1*4] - ldr.w r3, [r0, #2*4] - ldr.w r4, [r0, #3*4] - ldr.w r5, [r0, #4*4] - ldr.w r6, [r0, #5*4] - ldr.w r7, [r0, #6*4] - ldr.w r8, [r0, #7*4] - - barrett_32 r1, r9, r10, r11 - barrett_32 r2, r9, r10, r11 - barrett_32 r3, r9, r10, r11 - barrett_32 r4, r9, r10, r11 - barrett_32 r5, r9, r10, r11 - barrett_32 r6, r9, r10, r11 - barrett_32 r7, r9, r10, r11 - barrett_32 r8, r9, r10, r11 - - - str.w r2, [r0, #1*4] - str.w r3, [r0, #2*4] - str.w r4, [r0, #3*4] - str.w r5, [r0, #4*4] - str.w r6, [r0, #5*4] - str.w r7, [r0, #6*4] - str.w r8, [r0, #7*4] - str r1, [r0], #8*4 - subs r12, #1 - bne.w 1b - - pop {r4-r12, pc} - -.size pqcrystals_dilithium_small_asm_reduce32_central, .-pqcrystals_dilithium_small_asm_reduce32_central - -.macro caddq a, tmp, q - and \tmp, \q, \a, asr #31 - add \a, \a, \tmp -.endm - -.macro freezeq a, tmp, q - redq \a, \tmp, \q - caddq \a, \tmp, \q -.endm - -// void asm_caddq(int32_t a[N]); -.global pqcrystals_dilithium_asm_caddq -.type pqcrystals_dilithium_asm_caddq, %function -.align 2 -pqcrystals_dilithium_asm_caddq: - push {r4-r10} - - movw r12,#:lower16:8380417 - movt r12,#:upper16:8380417 - - movw r10, #32 - 1: - ldr.w r1, [r0] - ldr.w r2, [r0, #1*4] - ldr.w r3, [r0, #2*4] - ldr.w r4, [r0, #3*4] - ldr.w r5, [r0, #4*4] - ldr.w r6, [r0, #5*4] - ldr.w r7, [r0, #6*4] - ldr.w r8, [r0, #7*4] - - caddq r1, r9, r12 - caddq r2, r9, r12 - caddq r3, r9, r12 - caddq r4, r9, r12 - caddq r5, r9, r12 - caddq r6, r9, r12 - caddq r7, r9, r12 - caddq r8, r9, r12 - - str.w r2, [r0, #1*4] - str.w r3, [r0, #2*4] - str.w r4, [r0, #3*4] - str.w r5, [r0, #4*4] - str.w r6, [r0, #5*4] - str.w r7, [r0, #6*4] - str.w r8, [r0, #7*4] - str r1, [r0], #8*4 - subs r10, #1 - bne.w 1b - - pop {r4-r10} - bx lr -.size pqcrystals_dilithium_asm_caddq, .-pqcrystals_dilithium_asm_caddq - - -// asm_rej_uniform(int32_t *a,unsigned int len,const unsigned char *buf, unsigned int buflen); -.global pqcrystals_dilithium_asm_rej_uniform -.type pqcrystals_dilithium_asm_rej_uniform, %function -.align 2 -pqcrystals_dilithium_asm_rej_uniform: - push.w {r4-r6} - push.w {r1} - // Store Q-1 in r12. - movw r12,#:lower16:8380416 - movt r12,#:upper16:8380416 - - add.w r6, r0, r1, lsl #2 - add.w r3, r2, r3 - sub.w r3, r3, #2 - -1: - // If there are less than 3 bytes available, return. - cmp.w r3, r2 - ble.w end - - ldr r5, [r2], #3 - ubfx r5, r5, #0, #23 - - cmp.n r5, r12 - it le - strle r5, [r0], #4 - - cmp.n r0, r6 - bne.n 1b - -end: - pop.w {r5} - - sub.w r0, r6, r0 - sub.w r0, r5, r0, lsr #2 - pop.w {r4-r6} - bx lr -.size pqcrystals_dilithium_asm_rej_uniform, .-pqcrystals_dilithium_asm_rej_uniform diff --git a/crypto_sign/dilithium3/m4fstack/vector.s b/crypto_sign/dilithium3/m4fstack/vector.s new file mode 120000 index 00000000..2d2b4dcf --- /dev/null +++ b/crypto_sign/dilithium3/m4fstack/vector.s @@ -0,0 +1 @@ +../../dilithium2/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/api.h b/crypto_sign/dilithium5/m4fstack/api.h index d29362d1..9d1668d8 120000 --- a/crypto_sign/dilithium5/m4fstack/api.h +++ b/crypto_sign/dilithium5/m4fstack/api.h @@ -1 +1 @@ -../m4f/api.h \ No newline at end of file +../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros.i b/crypto_sign/dilithium5/m4fstack/macros.i index d615b854..e3f2469a 120000 --- a/crypto_sign/dilithium5/m4fstack/macros.i +++ b/crypto_sign/dilithium5/m4fstack/macros.i @@ -1 +1 @@ -../m4f/macros.i \ No newline at end of file +../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros_smallntt.i b/crypto_sign/dilithium5/m4fstack/macros_smallntt.i index fc731f12..37838a21 120000 --- a/crypto_sign/dilithium5/m4fstack/macros_smallntt.i +++ b/crypto_sign/dilithium5/m4fstack/macros_smallntt.i @@ -1 +1 @@ -../../dilithium3/m4fstack/macros_smallntt.i \ No newline at end of file +../../dilithium2/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.S b/crypto_sign/dilithium5/m4fstack/ntt.S index 40cd5d40..6fbceff1 120000 --- a/crypto_sign/dilithium5/m4fstack/ntt.S +++ b/crypto_sign/dilithium5/m4fstack/ntt.S @@ -1 +1 @@ -../m4f/ntt.S \ No newline at end of file +../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.h b/crypto_sign/dilithium5/m4fstack/ntt.h index 8e99caeb..43729fef 120000 --- a/crypto_sign/dilithium5/m4fstack/ntt.h +++ b/crypto_sign/dilithium5/m4fstack/ntt.h @@ -1 +1 @@ -../m4f/ntt.h \ No newline at end of file +../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.c b/crypto_sign/dilithium5/m4fstack/packing.c index 1052fe26..b41782c2 120000 --- a/crypto_sign/dilithium5/m4fstack/packing.c +++ b/crypto_sign/dilithium5/m4fstack/packing.c @@ -1 +1 @@ -../m4f/packing.c \ No newline at end of file +../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.h b/crypto_sign/dilithium5/m4fstack/packing.h index 643cc32a..ba1a6b3b 120000 --- a/crypto_sign/dilithium5/m4fstack/packing.h +++ b/crypto_sign/dilithium5/m4fstack/packing.h @@ -1 +1 @@ -../m4f/packing.h \ No newline at end of file +../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/params.h b/crypto_sign/dilithium5/m4fstack/params.h index 1f91a364..a6a4d8b6 120000 --- a/crypto_sign/dilithium5/m4fstack/params.h +++ b/crypto_sign/dilithium5/m4fstack/params.h @@ -1 +1 @@ -../m4f/params.h \ No newline at end of file +../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.h b/crypto_sign/dilithium5/m4fstack/pointwise_mont.h index 32558852..0a6f8b9f 120000 --- a/crypto_sign/dilithium5/m4fstack/pointwise_mont.h +++ b/crypto_sign/dilithium5/m4fstack/pointwise_mont.h @@ -1 +1 @@ -../m4f/pointwise_mont.h \ No newline at end of file +../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.s b/crypto_sign/dilithium5/m4fstack/pointwise_mont.s index 3597ffdc..c4ddb96c 120000 --- a/crypto_sign/dilithium5/m4fstack/pointwise_mont.s +++ b/crypto_sign/dilithium5/m4fstack/pointwise_mont.s @@ -1 +1 @@ -../m4f/pointwise_mont.s \ No newline at end of file +../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.c b/crypto_sign/dilithium5/m4fstack/poly.c index b5bdaa81..2544e75b 120000 --- a/crypto_sign/dilithium5/m4fstack/poly.c +++ b/crypto_sign/dilithium5/m4fstack/poly.c @@ -1 +1 @@ -../m4f/poly.c \ No newline at end of file +../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.h b/crypto_sign/dilithium5/m4fstack/poly.h index bd94e469..7ef70e53 120000 --- a/crypto_sign/dilithium5/m4fstack/poly.h +++ b/crypto_sign/dilithium5/m4fstack/poly.h @@ -1 +1 @@ -../m4f/poly.h \ No newline at end of file +../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.c b/crypto_sign/dilithium5/m4fstack/polyvec.c index 569a9a1b..a8edd0d0 120000 --- a/crypto_sign/dilithium5/m4fstack/polyvec.c +++ b/crypto_sign/dilithium5/m4fstack/polyvec.c @@ -1 +1 @@ -../m4f/polyvec.c \ No newline at end of file +../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.h b/crypto_sign/dilithium5/m4fstack/polyvec.h index d02c99c3..cabd6a93 120000 --- a/crypto_sign/dilithium5/m4fstack/polyvec.h +++ b/crypto_sign/dilithium5/m4fstack/polyvec.h @@ -1 +1 @@ -../m4f/polyvec.h \ No newline at end of file +../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/reduce.h b/crypto_sign/dilithium5/m4fstack/reduce.h index 45fbf228..f1e2b389 120000 --- a/crypto_sign/dilithium5/m4fstack/reduce.h +++ b/crypto_sign/dilithium5/m4fstack/reduce.h @@ -1 +1 @@ -../../dilithium3/m4fstack/reduce.h \ No newline at end of file +../../dilithium2/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.c b/crypto_sign/dilithium5/m4fstack/rounding.c index ec780689..80b8dce2 120000 --- a/crypto_sign/dilithium5/m4fstack/rounding.c +++ b/crypto_sign/dilithium5/m4fstack/rounding.c @@ -1 +1 @@ -../m4f/rounding.c \ No newline at end of file +../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.h b/crypto_sign/dilithium5/m4fstack/rounding.h index e64114bc..74c40c5e 120000 --- a/crypto_sign/dilithium5/m4fstack/rounding.h +++ b/crypto_sign/dilithium5/m4fstack/rounding.h @@ -1 +1 @@ -../m4f/rounding.h \ No newline at end of file +../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.c b/crypto_sign/dilithium5/m4fstack/sign.c index ae3b84fa..39f6ec48 120000 --- a/crypto_sign/dilithium5/m4fstack/sign.c +++ b/crypto_sign/dilithium5/m4fstack/sign.c @@ -1 +1 @@ -../../dilithium3/m4fstack/sign.c \ No newline at end of file +../../dilithium2/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.h b/crypto_sign/dilithium5/m4fstack/sign.h index 551f979a..b7f1e89c 120000 --- a/crypto_sign/dilithium5/m4fstack/sign.h +++ b/crypto_sign/dilithium5/m4fstack/sign.h @@ -1 +1 @@ -../m4f/sign.h \ No newline at end of file +../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt.h b/crypto_sign/dilithium5/m4fstack/smallntt.h index cfd626b9..60f2d18a 120000 --- a/crypto_sign/dilithium5/m4fstack/smallntt.h +++ b/crypto_sign/dilithium5/m4fstack/smallntt.h @@ -1 +1 @@ -../../dilithium3/m4fstack/smallntt.h \ No newline at end of file +../../dilithium2/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt_769.S b/crypto_sign/dilithium5/m4fstack/smallntt_769.S index 6300683f..4ae2f9bb 120000 --- a/crypto_sign/dilithium5/m4fstack/smallntt_769.S +++ b/crypto_sign/dilithium5/m4fstack/smallntt_769.S @@ -1 +1 @@ -../../dilithium3/m4fstack/smallntt_769.S \ No newline at end of file +../../dilithium2/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.c b/crypto_sign/dilithium5/m4fstack/smallpoly.c index 7dbf4992..9c350567 120000 --- a/crypto_sign/dilithium5/m4fstack/smallpoly.c +++ b/crypto_sign/dilithium5/m4fstack/smallpoly.c @@ -1 +1 @@ -../../dilithium3/m4fstack/smallpoly.c \ No newline at end of file +../../dilithium2/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.h b/crypto_sign/dilithium5/m4fstack/smallpoly.h index 366391d9..45701a42 120000 --- a/crypto_sign/dilithium5/m4fstack/smallpoly.h +++ b/crypto_sign/dilithium5/m4fstack/smallpoly.h @@ -1 +1 @@ -../../dilithium3/m4fstack/smallpoly.h \ No newline at end of file +../../dilithium2/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.c b/crypto_sign/dilithium5/m4fstack/stack.c index c89dc5a0..d25ed6f7 120000 --- a/crypto_sign/dilithium5/m4fstack/stack.c +++ b/crypto_sign/dilithium5/m4fstack/stack.c @@ -1 +1 @@ -../../dilithium3/m4fstack/stack.c \ No newline at end of file +../../dilithium2/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.h b/crypto_sign/dilithium5/m4fstack/stack.h index c9aed5d7..beab8ca2 120000 --- a/crypto_sign/dilithium5/m4fstack/stack.h +++ b/crypto_sign/dilithium5/m4fstack/stack.h @@ -1 +1 @@ -../../dilithium3/m4fstack/stack.h \ No newline at end of file +../../dilithium2/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric-shake.c b/crypto_sign/dilithium5/m4fstack/symmetric-shake.c index b95855bb..6ad80541 120000 --- a/crypto_sign/dilithium5/m4fstack/symmetric-shake.c +++ b/crypto_sign/dilithium5/m4fstack/symmetric-shake.c @@ -1 +1 @@ -../m4f/symmetric-shake.c \ No newline at end of file +../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric.h b/crypto_sign/dilithium5/m4fstack/symmetric.h index e89ae955..90ad5c07 120000 --- a/crypto_sign/dilithium5/m4fstack/symmetric.h +++ b/crypto_sign/dilithium5/m4fstack/symmetric.h @@ -1 +1 @@ -../m4f/symmetric.h \ No newline at end of file +../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.h b/crypto_sign/dilithium5/m4fstack/vector.h index 0793594b..6e2280f0 120000 --- a/crypto_sign/dilithium5/m4fstack/vector.h +++ b/crypto_sign/dilithium5/m4fstack/vector.h @@ -1 +1 @@ -../m4f/vector.h \ No newline at end of file +../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.s b/crypto_sign/dilithium5/m4fstack/vector.s index 1a496055..2d2b4dcf 120000 --- a/crypto_sign/dilithium5/m4fstack/vector.s +++ b/crypto_sign/dilithium5/m4fstack/vector.s @@ -1 +1 @@ -../m4f/vector.s \ No newline at end of file +../../dilithium2/m4f/vector.s \ No newline at end of file From cda61fb978537889ef985a0f15f4131030df9394 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 3 Jul 2024 11:02:34 +0800 Subject: [PATCH 092/107] Kyber: Fixed secret-dependent branch in poly_fromsg (#345) * Fixed secret-dependent branch in poly_fromsg * update mupq * update Kyber benchmarks * add missing prototype * extend skiplist * add Falcon benchmarks --- benchmarks.csv | 138 +++++++++++---------- benchmarks.md | 138 +++++++++++---------- crypto_kem/kyber1024/m4fspeed/cmov_int16.S | 1 + crypto_kem/kyber1024/m4fstack/cmov_int16.S | 1 + crypto_kem/kyber512/m4fspeed/cmov_int16.S | 1 + crypto_kem/kyber512/m4fspeed/poly.c | 22 ++-- crypto_kem/kyber512/m4fstack/cmov_int16.S | 1 + crypto_kem/kyber512/m4fstack/poly.c | 22 ++-- crypto_kem/kyber768/m4fspeed/cmov_int16.S | 15 +++ crypto_kem/kyber768/m4fspeed/poly.c | 23 ++-- crypto_kem/kyber768/m4fstack/cmov_int16.S | 1 + crypto_kem/kyber768/m4fstack/poly.c | 22 ++-- mupq | 2 +- skiplist.py | 2 + 14 files changed, 228 insertions(+), 161 deletions(-) create mode 120000 crypto_kem/kyber1024/m4fspeed/cmov_int16.S create mode 120000 crypto_kem/kyber1024/m4fstack/cmov_int16.S create mode 120000 crypto_kem/kyber512/m4fspeed/cmov_int16.S create mode 120000 crypto_kem/kyber512/m4fstack/cmov_int16.S create mode 100644 crypto_kem/kyber768/m4fspeed/cmov_int16.S create mode 120000 crypto_kem/kyber768/m4fstack/cmov_int16.S diff --git a/benchmarks.csv b/benchmarks.csv index 6064966e..952b95f8 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -8,15 +8,15 @@ bikel3 (10 executions),opt,248083316,248083286,248083345,16405238,16405236,16405 hqc-128 (10 executions),clean,52705201,52705180,52705224,105650897,105650877,105650927,159569179,159569176,159569183 hqc-192 (10 executions),clean,161458617,161458590,161458638,323146261,323146250,323146292,486156251,486156214,486156266 hqc-256 (10 executions),clean,295934078,295934057,295934104,591853870,591853850,591853898,891163005,891162988,891163038 -kyber1024 (10 executions),clean,1540378,1537672,1549497,1707203,1704498,1716319,2019461,2016781,2028566 -kyber1024 (10 executions),m4fspeed,1007332,1004620,1027834,1025692,1023006,1046169,1088140,1085497,1108618 -kyber1024 (10 executions),m4fstack,1010439,1007447,1019916,1034164,1031168,1043640,1097375,1094378,1106850 -kyber512 (10 executions),clean,596231,595868,596646,696137,695809,696547,884186,883823,884599 -kyber512 (10 executions),m4fspeed,387168,386737,387669,386230,385800,386729,423509,423078,424010 -kyber512 (10 executions),m4fstack,386859,386551,387231,388111,387802,388486,425445,425136,425820 -kyber768 (10 executions),clean,990392,988002,998996,1134996,1132606,1143599,1384768,1382378,1393371 -kyber768 (10 executions),m4fspeed,631922,631406,632490,651769,651258,652364,700842,700331,701436 -kyber768 (10 executions),m4fstack,633057,632425,633410,656716,656088,657072,706247,705620,706604 +kyber1024 (10 executions),clean,1540394,1537580,1549267,1712150,1709337,1721019,2024408,2021583,2033304 +kyber1024 (10 executions),m4fspeed,1006341,1004590,1016692,1029398,1027642,1039752,1091847,1090091,1102201 +kyber1024 (10 executions),m4fstack,1009603,1007702,1019835,1038001,1036100,1048226,1101208,1099307,1111470 +kyber512 (10 executions),clean,597372,596106,607563,702227,700957,712416,890274,889008,900467 +kyber512 (10 executions),m4fspeed,387341,386762,387769,391098,390520,391527,428365,427786,428794 +kyber512 (10 executions),m4fstack,386853,386573,387221,392801,392521,393166,430140,429861,430504 +kyber768 (10 executions),clean,989247,987825,999577,1138807,1137381,1149131,1388568,1387146,1398896 +kyber768 (10 executions),m4fspeed,631912,631599,632459,656455,656155,656969,705524,705223,706037 +kyber768 (10 executions),m4fstack,634213,632786,644273,662556,661130,672615,712081,710655,722140 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) aimer-l1-param1 (10 executions),ref,392943,392938,392977,32386301,32386203,32386424,31111672,31111588,31111782 @@ -54,17 +54,21 @@ dilithium3 (1000 executions),m4fstack,3412759,3406659,3419247,23673016,6733971,1 dilithium5 (1000 executions),clean,5341477,5286872,5395822,15710371,7953367,75940093,5609679,5609217,5610183 dilithium5 (1000 executions),m4f,4275029,4210286,4329519,7977781,4882524,25936176,4185417,4184925,4185896 dilithium5 (1000 executions),m4fstack,5816287,5474236,6115061,33452872,11170780,185259803,9912851,9845789,9981834 -falcon-1024 (10 executions),m4-ct,354880005,284902033,635131652,87741288,87506676,87922628,991320,982548,997219 -falcon-1024 (10 executions),opt-ct,555202324,284912829,1157528581,87710190,87606677,87841235,993584,983066,997523 -falcon-1024 (10 executions),opt-leaktime,438412062,334858742,625013074,80139483,79891200,80551967,994127,984891,997390 -falcon-1024-tree (10 executions),opt-ct,500950316,327706067,969046860,39207109,39013867,39449442,992787,982032,998080 -falcon-1024-tree (10 executions),opt-leaktime,372505822,284807343,551245131,42213136,41842229,42582424,995859,984960,998421 -falcon-512 (10 executions),m4-ct,161245486,110088298,279215300,40225282,40072879,40389913,478930,472982,485577 -falcon-512 (10 executions),opt-ct,151650543,116181731,228216352,40147309,40003575,40360540,480990,472795,485260 -falcon-512 (10 executions),opt-leaktime,159608965,111149933,301580807,37267337,36991076,37518518,478421,471680,484872 -falcon-512-tree (10 executions),m4-ct,167653515,121618919,272326714,18250061,18135371,18325579,479823,471774,485540 -falcon-512-tree (10 executions),opt-ct,184949574,121623805,270290280,18248036,18069599,18462666,484565,484059,485335 -falcon-512-tree (10 executions),opt-leaktime,156710258,106732109,326634247,20050613,19891001,20227947,482101,472948,485643 +falcon-1024 (10 executions),clean,602066436,377135260,1488065363,136241759,136017549,136556585,1678109,1677732,1678566 +falcon-1024 (10 executions),m4-ct,408725773,314885208,712370124,87706019,87549942,87839508,990541,984448,997160 +falcon-1024 (10 executions),opt-ct,448194494,301446952,784390745,87699336,87550679,87857833,992822,983184,998271 +falcon-1024 (10 executions),opt-leaktime,371539477,261831977,576613448,80134413,79844667,80338608,992815,982774,998600 +falcon-1024-tree (10 executions),opt-ct,469168139,341160847,733947155,39197559,39095597,39392055,995190,984826,998305 +falcon-1024-tree (10 executions),opt-leaktime,418213501,284879287,699555143,42181577,41844047,42456098,991791,983935,997742 +falcon-512 (10 executions),clean,229742458,134930383,358460785,62255726,62124149,62424751,834970,834402,835533 +falcon-512 (10 executions),m4-ct,146357328,106015844,250638532,40191597,40123901,40381630,482280,472137,485160 +falcon-512 (10 executions),opt-ct,168942163,106015882,258726842,40136012,40046972,40195851,481102,472809,485947 +falcon-512 (10 executions),opt-leaktime,130638983,94352160,240934147,37196341,36969717,37564986,476152,471514,484487 +falcon-512-tree (10 executions),m4-ct,187840863,121618909,531189026,18199972,18111179,18297541,479819,472890,485685 +falcon-512-tree (10 executions),opt-ct,179501018,121618960,347996956,18222471,18064774,18329860,479635,472057,484767 +falcon-512-tree (10 executions),opt-leaktime,203618838,106760540,425495750,20110699,19752157,20375122,480119,472263,485743 +falcon-padded-1024 (10 executions),clean,464867653,351942875,908060882,136157961,135988344,136430038,1677719,1677506,1677932 +falcon-padded-512 (10 executions),clean,241548154,164862595,348699388,62231774,62096573,62365088,834766,834480,834957 haetae2 (100 executions),m4f,6743278,1555292,25393506,21993963,4721290,86765689,918459,918244,918668 haetae2 (100 executions),ref,9363639,1716264,41895014,31631089,6247382,216853925,1104080,1103874,1104329 haetae3 (100 executions),m4f,12925388,2752846,52240529,30891994,7467529,160522018,1760745,1760408,1761081 @@ -204,19 +208,21 @@ dilithium3,m4fstack,4408,6608,2704,,,,,, dilithium5,clean,97696,122724,92940,,,,,, dilithium5,m4f,97688,116076,92932,,,,,, dilithium5,m4fstack,4408,8136,2712,,,,,, -falcon-1024,clean,34988,84604,8784,,,,,, +falcon-1024,clean,35076,84604,8776,,,,,, falcon-1024,m4-ct,1156,2508,376,,,,,, -falcon-1024,opt-ct,1156,2508,376,,,,,, -falcon-1024,opt-leaktime,1212,2580,376,,,,,, -falcon-1024-tree,opt-ct,1252,2772,376,,,,,, -falcon-1024-tree,opt-leaktime,1212,2988,376,,,,,, -falcon-512,clean,18092,43548,4688,,,,,, -falcon-512,m4-ct,1156,2428,376,,,,,, -falcon-512,opt-ct,1156,2428,376,,,,,, -falcon-512,opt-leaktime,1156,2492,376,,,,,, -falcon-512-tree,m4-ct,1212,2636,376,,,,,, +falcon-1024,opt-ct,1204,2508,376,,,,,, +falcon-1024,opt-leaktime,1252,2580,444,,,,,, +falcon-1024-tree,opt-ct,1148,2884,376,,,,,, +falcon-1024-tree,opt-leaktime,1196,2988,376,,,,,, +falcon-512,clean,18180,43548,4680,,,,,, +falcon-512,m4-ct,1148,2428,376,,,,,, +falcon-512,opt-ct,1244,2428,376,,,,,, +falcon-512,opt-leaktime,1148,2492,376,,,,,, +falcon-512-tree,m4-ct,1172,2636,376,,,,,, falcon-512-tree,opt-ct,1156,2636,376,,,,,, -falcon-512-tree,opt-leaktime,1212,2828,376,,,,,, +falcon-512-tree,opt-leaktime,1196,2828,376,,,,,, +falcon-padded-1024,clean,34988,84596,8776,,,,,, +falcon-padded-512,clean,18092,43540,4680,,,,,, haetae2,m4f,19756,55568,23296,,,,,, haetae2,ref,26092,54444,29696,,,,,, haetae3,m4f,29596,83420,31784,,,,,, @@ -311,15 +317,15 @@ bikel3,opt,0.0,6.3,0.2,,,,,, hqc-128,clean,0.4,0.8,0.5,,,,,, hqc-192,clean,0.3,0.5,0.3,,,,,, hqc-256,clean,0.2,0.4,0.3,,,,,, -kyber1024,clean,50.0,45.8,38.7,,,,,, -kyber1024,m4fspeed,76.0,75.8,71.5,,,,,, -kyber1024,m4fstack,75.9,75.3,71.0,,,,,, -kyber512,clean,49.8,41.4,32.6,,,,,, -kyber512,m4fspeed,76.6,74.4,68.0,,,,,, -kyber512,m4fstack,76.6,74.0,67.6,,,,,, -kyber768,clean,48.4,43.3,35.5,,,,,, -kyber768,m4fspeed,75.4,74.9,69.6,,,,,, -kyber768,m4fstack,75.4,74.5,69.3,,,,,, +kyber1024,clean,49.9,45.6,38.6,,,,,, +kyber1024,m4fspeed,76.1,75.5,71.2,,,,,, +kyber1024,m4fstack,75.8,74.9,70.6,,,,,, +kyber512,clean,49.8,41.1,32.5,,,,,, +kyber512,m4fspeed,76.5,73.5,67.1,,,,,, +kyber512,m4fstack,76.5,73.1,66.8,,,,,, +kyber768,clean,48.5,43.2,35.4,,,,,, +kyber768,m4fspeed,75.4,74.4,69.2,,,,,, +kyber768,m4fstack,75.3,73.8,68.7,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, aimer-l1-param1,ref,72.0,47.2,46.7,,,,,, @@ -357,19 +363,21 @@ dilithium3,m4fstack,77.1,54.6,41.0,,,,,, dilithium5,clean,67.0,35.7,61.1,,,,,, dilithium5,m4f,83.5,65.0,81.7,,,,,, dilithium5,m4fstack,76.1,54.5,42.6,,,,,, -falcon-1024,clean,6.5,0.3,23.7,,,,,, -falcon-1024,m4-ct,7.4,0.4,32.4,,,,,, -falcon-1024,opt-ct,11.7,0.4,32.2,,,,,, -falcon-1024,opt-leaktime,12.3,0.5,32.4,,,,,, -falcon-1024-tree,opt-ct,5.2,0.9,32.3,,,,,, -falcon-1024-tree,opt-leaktime,11.9,0.9,32.4,,,,,, -falcon-512,clean,10.9,0.4,26.0,,,,,, -falcon-512,m4-ct,15.3,0.5,34.3,,,,,, -falcon-512,opt-ct,17.2,0.5,33.6,,,,,, -falcon-512,opt-leaktime,16.0,0.5,33.8,,,,,, -falcon-512-tree,m4-ct,18.4,1.1,33.9,,,,,, -falcon-512-tree,opt-ct,14.5,1.1,33.9,,,,,, -falcon-512-tree,opt-leaktime,18.7,1.0,33.9,,,,,, +falcon-1024,clean,8.9,0.3,23.7,,,,,, +falcon-1024,m4-ct,8.6,0.4,32.2,,,,,, +falcon-1024,opt-ct,9.8,0.4,32.2,,,,,, +falcon-1024,opt-leaktime,10.9,0.5,32.2,,,,,, +falcon-1024-tree,opt-ct,9.2,0.9,32.3,,,,,, +falcon-1024-tree,opt-leaktime,10.6,0.9,32.3,,,,,, +falcon-512,clean,7.9,0.4,26.0,,,,,, +falcon-512,m4-ct,13.7,0.5,33.9,,,,,, +falcon-512,opt-ct,14.0,0.5,33.2,,,,,, +falcon-512,opt-leaktime,17.3,0.5,33.6,,,,,, +falcon-512-tree,m4-ct,12.6,1.1,33.7,,,,,, +falcon-512-tree,opt-ct,14.6,1.1,34.2,,,,,, +falcon-512-tree,opt-leaktime,20.5,1.0,34.3,,,,,, +falcon-padded-1024,clean,7.3,0.3,23.7,,,,,, +falcon-padded-512,clean,16.0,0.4,26.0,,,,,, haetae2,m4f,12.4,56.7,54.1,,,,,, haetae2,ref,10.6,42.4,45.1,,,,,, haetae3,m4f,14.6,56.6,57.1,,,,,, @@ -463,15 +471,15 @@ bikel3,opt,43091,24,1,43116,,,,, hqc-128,clean,18628,0,0,18628,,,,, hqc-192,clean,21104,0,0,21104,,,,, hqc-256,clean,26260,0,0,26260,,,,, -kyber1024,clean,6296,0,0,6296,,,,, -kyber1024,m4fspeed,16912,0,0,16912,,,,, -kyber1024,m4fstack,14120,0,0,14120,,,,, -kyber512,clean,5164,0,0,5164,,,,, -kyber512,m4fspeed,15824,0,0,15824,,,,, -kyber512,m4fstack,13308,0,0,13308,,,,, -kyber768,clean,5168,0,0,5168,,,,, -kyber768,m4fspeed,15992,0,0,15992,,,,, -kyber768,m4fstack,13316,0,0,13316,,,,, +kyber1024,clean,6264,0,0,6264,,,,, +kyber1024,m4fspeed,16884,0,0,16884,,,,, +kyber1024,m4fstack,14092,0,0,14092,,,,, +kyber512,clean,5132,0,0,5132,,,,, +kyber512,m4fspeed,15796,0,0,15796,,,,, +kyber512,m4fstack,13280,0,0,13280,,,,, +kyber768,clean,5136,0,0,5136,,,,, +kyber768,m4fspeed,15964,0,0,15964,,,,, +kyber768,m4fstack,13288,0,0,13288,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, aimer-l1-param1,ref,19302,468,0,19770,,,,, @@ -509,19 +517,21 @@ dilithium3,m4fstack,23448,0,0,23448,,,,, dilithium5,clean,7808,0,0,7808,,,,, dilithium5,m4f,18468,0,0,18468,,,,, dilithium5,m4fstack,23820,0,0,23820,,,,, -falcon-1024,clean,82647,0,0,82647,,,,, +falcon-1024,clean,82703,0,0,82703,,,,, falcon-1024,m4-ct,81825,0,79872,161697,,,,, falcon-1024,opt-ct,81825,0,79872,161697,,,,, falcon-1024,opt-leaktime,75429,0,79872,155301,,,,, falcon-1024-tree,opt-ct,81569,0,55296,136865,,,,, falcon-1024-tree,opt-leaktime,75173,0,55296,130469,,,,, -falcon-512,clean,82611,0,0,82611,,,,, +falcon-512,clean,82663,0,0,82663,,,,, falcon-512,m4-ct,81825,0,39936,121761,,,,, falcon-512,opt-ct,81825,0,39936,121761,,,,, falcon-512,opt-leaktime,75429,0,39936,115365,,,,, falcon-512-tree,m4-ct,81569,0,27648,109217,,,,, falcon-512-tree,opt-ct,81569,0,27648,109217,,,,, falcon-512-tree,opt-leaktime,75173,0,27648,102821,,,,, +falcon-padded-1024,clean,82643,0,0,82643,,,,, +falcon-padded-512,clean,82599,0,0,82599,,,,, haetae2,m4f,35708,0,0,35708,,,,, haetae2,ref,25568,0,0,25568,,,,, haetae3,m4f,35936,0,0,35936,,,,, diff --git a/benchmarks.md b/benchmarks.md index ba34c3d9..afb0ab01 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -9,15 +9,15 @@ | hqc-128 (10 executions) | clean | AVG: 52,705,201
MIN: 52,705,180
MAX: 52,705,224 | AVG: 105,650,897
MIN: 105,650,877
MAX: 105,650,927 | AVG: 159,569,179
MIN: 159,569,176
MAX: 159,569,183 | | hqc-192 (10 executions) | clean | AVG: 161,458,617
MIN: 161,458,590
MAX: 161,458,638 | AVG: 323,146,261
MIN: 323,146,250
MAX: 323,146,292 | AVG: 486,156,251
MIN: 486,156,214
MAX: 486,156,266 | | hqc-256 (10 executions) | clean | AVG: 295,934,078
MIN: 295,934,057
MAX: 295,934,104 | AVG: 591,853,870
MIN: 591,853,850
MAX: 591,853,898 | AVG: 891,163,005
MIN: 891,162,988
MAX: 891,163,038 | -| kyber1024 (10 executions) | clean | AVG: 1,540,378
MIN: 1,537,672
MAX: 1,549,497 | AVG: 1,707,203
MIN: 1,704,498
MAX: 1,716,319 | AVG: 2,019,461
MIN: 2,016,781
MAX: 2,028,566 | -| kyber1024 (10 executions) | m4fspeed | AVG: 1,007,332
MIN: 1,004,620
MAX: 1,027,834 | AVG: 1,025,692
MIN: 1,023,006
MAX: 1,046,169 | AVG: 1,088,140
MIN: 1,085,497
MAX: 1,108,618 | -| kyber1024 (10 executions) | m4fstack | AVG: 1,010,439
MIN: 1,007,447
MAX: 1,019,916 | AVG: 1,034,164
MIN: 1,031,168
MAX: 1,043,640 | AVG: 1,097,375
MIN: 1,094,378
MAX: 1,106,850 | -| kyber512 (10 executions) | clean | AVG: 596,231
MIN: 595,868
MAX: 596,646 | AVG: 696,137
MIN: 695,809
MAX: 696,547 | AVG: 884,186
MIN: 883,823
MAX: 884,599 | -| kyber512 (10 executions) | m4fspeed | AVG: 387,168
MIN: 386,737
MAX: 387,669 | AVG: 386,230
MIN: 385,800
MAX: 386,729 | AVG: 423,509
MIN: 423,078
MAX: 424,010 | -| kyber512 (10 executions) | m4fstack | AVG: 386,859
MIN: 386,551
MAX: 387,231 | AVG: 388,111
MIN: 387,802
MAX: 388,486 | AVG: 425,445
MIN: 425,136
MAX: 425,820 | -| kyber768 (10 executions) | clean | AVG: 990,392
MIN: 988,002
MAX: 998,996 | AVG: 1,134,996
MIN: 1,132,606
MAX: 1,143,599 | AVG: 1,384,768
MIN: 1,382,378
MAX: 1,393,371 | -| kyber768 (10 executions) | m4fspeed | AVG: 631,922
MIN: 631,406
MAX: 632,490 | AVG: 651,769
MIN: 651,258
MAX: 652,364 | AVG: 700,842
MIN: 700,331
MAX: 701,436 | -| kyber768 (10 executions) | m4fstack | AVG: 633,057
MIN: 632,425
MAX: 633,410 | AVG: 656,716
MIN: 656,088
MAX: 657,072 | AVG: 706,247
MIN: 705,620
MAX: 706,604 | +| kyber1024 (10 executions) | clean | AVG: 1,540,394
MIN: 1,537,580
MAX: 1,549,267 | AVG: 1,712,150
MIN: 1,709,337
MAX: 1,721,019 | AVG: 2,024,408
MIN: 2,021,583
MAX: 2,033,304 | +| kyber1024 (10 executions) | m4fspeed | AVG: 1,006,341
MIN: 1,004,590
MAX: 1,016,692 | AVG: 1,029,398
MIN: 1,027,642
MAX: 1,039,752 | AVG: 1,091,847
MIN: 1,090,091
MAX: 1,102,201 | +| kyber1024 (10 executions) | m4fstack | AVG: 1,009,603
MIN: 1,007,702
MAX: 1,019,835 | AVG: 1,038,001
MIN: 1,036,100
MAX: 1,048,226 | AVG: 1,101,208
MIN: 1,099,307
MAX: 1,111,470 | +| kyber512 (10 executions) | clean | AVG: 597,372
MIN: 596,106
MAX: 607,563 | AVG: 702,227
MIN: 700,957
MAX: 712,416 | AVG: 890,274
MIN: 889,008
MAX: 900,467 | +| kyber512 (10 executions) | m4fspeed | AVG: 387,341
MIN: 386,762
MAX: 387,769 | AVG: 391,098
MIN: 390,520
MAX: 391,527 | AVG: 428,365
MIN: 427,786
MAX: 428,794 | +| kyber512 (10 executions) | m4fstack | AVG: 386,853
MIN: 386,573
MAX: 387,221 | AVG: 392,801
MIN: 392,521
MAX: 393,166 | AVG: 430,140
MIN: 429,861
MAX: 430,504 | +| kyber768 (10 executions) | clean | AVG: 989,247
MIN: 987,825
MAX: 999,577 | AVG: 1,138,807
MIN: 1,137,381
MAX: 1,149,131 | AVG: 1,388,568
MIN: 1,387,146
MAX: 1,398,896 | +| kyber768 (10 executions) | m4fspeed | AVG: 631,912
MIN: 631,599
MAX: 632,459 | AVG: 656,455
MIN: 656,155
MAX: 656,969 | AVG: 705,524
MIN: 705,223
MAX: 706,037 | +| kyber768 (10 executions) | m4fstack | AVG: 634,213
MIN: 632,786
MAX: 644,273 | AVG: 662,556
MIN: 661,130
MAX: 672,615 | AVG: 712,081
MIN: 710,655
MAX: 722,140 | ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | @@ -56,17 +56,21 @@ | dilithium5 (1000 executions) | clean | AVG: 5,341,477
MIN: 5,286,872
MAX: 5,395,822 | AVG: 15,710,371
MIN: 7,953,367
MAX: 75,940,093 | AVG: 5,609,679
MIN: 5,609,217
MAX: 5,610,183 | | dilithium5 (1000 executions) | m4f | AVG: 4,275,029
MIN: 4,210,286
MAX: 4,329,519 | AVG: 7,977,781
MIN: 4,882,524
MAX: 25,936,176 | AVG: 4,185,417
MIN: 4,184,925
MAX: 4,185,896 | | dilithium5 (1000 executions) | m4fstack | AVG: 5,816,287
MIN: 5,474,236
MAX: 6,115,061 | AVG: 33,452,872
MIN: 11,170,780
MAX: 185,259,803 | AVG: 9,912,851
MIN: 9,845,789
MAX: 9,981,834 | -| falcon-1024 (10 executions) | m4-ct | AVG: 354,880,005
MIN: 284,902,033
MAX: 635,131,652 | AVG: 87,741,288
MIN: 87,506,676
MAX: 87,922,628 | AVG: 991,320
MIN: 982,548
MAX: 997,219 | -| falcon-1024 (10 executions) | opt-ct | AVG: 555,202,324
MIN: 284,912,829
MAX: 1,157,528,581 | AVG: 87,710,190
MIN: 87,606,677
MAX: 87,841,235 | AVG: 993,584
MIN: 983,066
MAX: 997,523 | -| falcon-1024 (10 executions) | opt-leaktime | AVG: 438,412,062
MIN: 334,858,742
MAX: 625,013,074 | AVG: 80,139,483
MIN: 79,891,200
MAX: 80,551,967 | AVG: 994,127
MIN: 984,891
MAX: 997,390 | -| falcon-1024-tree (10 executions) | opt-ct | AVG: 500,950,316
MIN: 327,706,067
MAX: 969,046,860 | AVG: 39,207,109
MIN: 39,013,867
MAX: 39,449,442 | AVG: 992,787
MIN: 982,032
MAX: 998,080 | -| falcon-1024-tree (10 executions) | opt-leaktime | AVG: 372,505,822
MIN: 284,807,343
MAX: 551,245,131 | AVG: 42,213,136
MIN: 41,842,229
MAX: 42,582,424 | AVG: 995,859
MIN: 984,960
MAX: 998,421 | -| falcon-512 (10 executions) | m4-ct | AVG: 161,245,486
MIN: 110,088,298
MAX: 279,215,300 | AVG: 40,225,282
MIN: 40,072,879
MAX: 40,389,913 | AVG: 478,930
MIN: 472,982
MAX: 485,577 | -| falcon-512 (10 executions) | opt-ct | AVG: 151,650,543
MIN: 116,181,731
MAX: 228,216,352 | AVG: 40,147,309
MIN: 40,003,575
MAX: 40,360,540 | AVG: 480,990
MIN: 472,795
MAX: 485,260 | -| falcon-512 (10 executions) | opt-leaktime | AVG: 159,608,965
MIN: 111,149,933
MAX: 301,580,807 | AVG: 37,267,337
MIN: 36,991,076
MAX: 37,518,518 | AVG: 478,421
MIN: 471,680
MAX: 484,872 | -| falcon-512-tree (10 executions) | m4-ct | AVG: 167,653,515
MIN: 121,618,919
MAX: 272,326,714 | AVG: 18,250,061
MIN: 18,135,371
MAX: 18,325,579 | AVG: 479,823
MIN: 471,774
MAX: 485,540 | -| falcon-512-tree (10 executions) | opt-ct | AVG: 184,949,574
MIN: 121,623,805
MAX: 270,290,280 | AVG: 18,248,036
MIN: 18,069,599
MAX: 18,462,666 | AVG: 484,565
MIN: 484,059
MAX: 485,335 | -| falcon-512-tree (10 executions) | opt-leaktime | AVG: 156,710,258
MIN: 106,732,109
MAX: 326,634,247 | AVG: 20,050,613
MIN: 19,891,001
MAX: 20,227,947 | AVG: 482,101
MIN: 472,948
MAX: 485,643 | +| falcon-1024 (10 executions) | clean | AVG: 602,066,436
MIN: 377,135,260
MAX: 1,488,065,363 | AVG: 136,241,759
MIN: 136,017,549
MAX: 136,556,585 | AVG: 1,678,109
MIN: 1,677,732
MAX: 1,678,566 | +| falcon-1024 (10 executions) | m4-ct | AVG: 408,725,773
MIN: 314,885,208
MAX: 712,370,124 | AVG: 87,706,019
MIN: 87,549,942
MAX: 87,839,508 | AVG: 990,541
MIN: 984,448
MAX: 997,160 | +| falcon-1024 (10 executions) | opt-ct | AVG: 448,194,494
MIN: 301,446,952
MAX: 784,390,745 | AVG: 87,699,336
MIN: 87,550,679
MAX: 87,857,833 | AVG: 992,822
MIN: 983,184
MAX: 998,271 | +| falcon-1024 (10 executions) | opt-leaktime | AVG: 371,539,477
MIN: 261,831,977
MAX: 576,613,448 | AVG: 80,134,413
MIN: 79,844,667
MAX: 80,338,608 | AVG: 992,815
MIN: 982,774
MAX: 998,600 | +| falcon-1024-tree (10 executions) | opt-ct | AVG: 469,168,139
MIN: 341,160,847
MAX: 733,947,155 | AVG: 39,197,559
MIN: 39,095,597
MAX: 39,392,055 | AVG: 995,190
MIN: 984,826
MAX: 998,305 | +| falcon-1024-tree (10 executions) | opt-leaktime | AVG: 418,213,501
MIN: 284,879,287
MAX: 699,555,143 | AVG: 42,181,577
MIN: 41,844,047
MAX: 42,456,098 | AVG: 991,791
MIN: 983,935
MAX: 997,742 | +| falcon-512 (10 executions) | clean | AVG: 229,742,458
MIN: 134,930,383
MAX: 358,460,785 | AVG: 62,255,726
MIN: 62,124,149
MAX: 62,424,751 | AVG: 834,970
MIN: 834,402
MAX: 835,533 | +| falcon-512 (10 executions) | m4-ct | AVG: 146,357,328
MIN: 106,015,844
MAX: 250,638,532 | AVG: 40,191,597
MIN: 40,123,901
MAX: 40,381,630 | AVG: 482,280
MIN: 472,137
MAX: 485,160 | +| falcon-512 (10 executions) | opt-ct | AVG: 168,942,163
MIN: 106,015,882
MAX: 258,726,842 | AVG: 40,136,012
MIN: 40,046,972
MAX: 40,195,851 | AVG: 481,102
MIN: 472,809
MAX: 485,947 | +| falcon-512 (10 executions) | opt-leaktime | AVG: 130,638,983
MIN: 94,352,160
MAX: 240,934,147 | AVG: 37,196,341
MIN: 36,969,717
MAX: 37,564,986 | AVG: 476,152
MIN: 471,514
MAX: 484,487 | +| falcon-512-tree (10 executions) | m4-ct | AVG: 187,840,863
MIN: 121,618,909
MAX: 531,189,026 | AVG: 18,199,972
MIN: 18,111,179
MAX: 18,297,541 | AVG: 479,819
MIN: 472,890
MAX: 485,685 | +| falcon-512-tree (10 executions) | opt-ct | AVG: 179,501,018
MIN: 121,618,960
MAX: 347,996,956 | AVG: 18,222,471
MIN: 18,064,774
MAX: 18,329,860 | AVG: 479,635
MIN: 472,057
MAX: 484,767 | +| falcon-512-tree (10 executions) | opt-leaktime | AVG: 203,618,838
MIN: 106,760,540
MAX: 425,495,750 | AVG: 20,110,699
MIN: 19,752,157
MAX: 20,375,122 | AVG: 480,119
MIN: 472,263
MAX: 485,743 | +| falcon-padded-1024 (10 executions) | clean | AVG: 464,867,653
MIN: 351,942,875
MAX: 908,060,882 | AVG: 136,157,961
MIN: 135,988,344
MAX: 136,430,038 | AVG: 1,677,719
MIN: 1,677,506
MAX: 1,677,932 | +| falcon-padded-512 (10 executions) | clean | AVG: 241,548,154
MIN: 164,862,595
MAX: 348,699,388 | AVG: 62,231,774
MIN: 62,096,573
MAX: 62,365,088 | AVG: 834,766
MIN: 834,480
MAX: 834,957 | | haetae2 (100 executions) | m4f | AVG: 6,743,278
MIN: 1,555,292
MAX: 25,393,506 | AVG: 21,993,963
MIN: 4,721,290
MAX: 86,765,689 | AVG: 918,459
MIN: 918,244
MAX: 918,668 | | haetae2 (100 executions) | ref | AVG: 9,363,639
MIN: 1,716,264
MAX: 41,895,014 | AVG: 31,631,089
MIN: 6,247,382
MAX: 216,853,925 | AVG: 1,104,080
MIN: 1,103,874
MAX: 1,104,329 | | haetae3 (100 executions) | m4f | AVG: 12,925,388
MIN: 2,752,846
MAX: 52,240,529 | AVG: 30,891,994
MIN: 7,467,529
MAX: 160,522,018 | AVG: 1,760,745
MIN: 1,760,408
MAX: 1,761,081 | @@ -208,19 +212,21 @@ | dilithium5 | clean | 97,696 | 122,724 | 92,940 | | dilithium5 | m4f | 97,688 | 116,076 | 92,932 | | dilithium5 | m4fstack | 4,408 | 8,136 | 2,712 | -| falcon-1024 | clean | 34,988 | 84,604 | 8,784 | +| falcon-1024 | clean | 35,076 | 84,604 | 8,776 | | falcon-1024 | m4-ct | 1,156 | 2,508 | 376 | -| falcon-1024 | opt-ct | 1,156 | 2,508 | 376 | -| falcon-1024 | opt-leaktime | 1,212 | 2,580 | 376 | -| falcon-1024-tree | opt-ct | 1,252 | 2,772 | 376 | -| falcon-1024-tree | opt-leaktime | 1,212 | 2,988 | 376 | -| falcon-512 | clean | 18,092 | 43,548 | 4,688 | -| falcon-512 | m4-ct | 1,156 | 2,428 | 376 | -| falcon-512 | opt-ct | 1,156 | 2,428 | 376 | -| falcon-512 | opt-leaktime | 1,156 | 2,492 | 376 | -| falcon-512-tree | m4-ct | 1,212 | 2,636 | 376 | +| falcon-1024 | opt-ct | 1,204 | 2,508 | 376 | +| falcon-1024 | opt-leaktime | 1,252 | 2,580 | 444 | +| falcon-1024-tree | opt-ct | 1,148 | 2,884 | 376 | +| falcon-1024-tree | opt-leaktime | 1,196 | 2,988 | 376 | +| falcon-512 | clean | 18,180 | 43,548 | 4,680 | +| falcon-512 | m4-ct | 1,148 | 2,428 | 376 | +| falcon-512 | opt-ct | 1,244 | 2,428 | 376 | +| falcon-512 | opt-leaktime | 1,148 | 2,492 | 376 | +| falcon-512-tree | m4-ct | 1,172 | 2,636 | 376 | | falcon-512-tree | opt-ct | 1,156 | 2,636 | 376 | -| falcon-512-tree | opt-leaktime | 1,212 | 2,828 | 376 | +| falcon-512-tree | opt-leaktime | 1,196 | 2,828 | 376 | +| falcon-padded-1024 | clean | 34,988 | 84,596 | 8,776 | +| falcon-padded-512 | clean | 18,092 | 43,540 | 4,680 | | haetae2 | m4f | 19,756 | 55,568 | 23,296 | | haetae2 | ref | 26,092 | 54,444 | 29,696 | | haetae3 | m4f | 29,596 | 83,420 | 31,784 | @@ -316,15 +322,15 @@ | hqc-128 | clean | 0.4% | 0.8% | 0.5% | | hqc-192 | clean | 0.3% | 0.5% | 0.3% | | hqc-256 | clean | 0.2% | 0.4% | 0.3% | -| kyber1024 | clean | 50.0% | 45.8% | 38.7% | -| kyber1024 | m4fspeed | 76.0% | 75.8% | 71.5% | -| kyber1024 | m4fstack | 75.9% | 75.3% | 71.0% | -| kyber512 | clean | 49.8% | 41.4% | 32.6% | -| kyber512 | m4fspeed | 76.6% | 74.4% | 68.0% | -| kyber512 | m4fstack | 76.6% | 74.0% | 67.6% | -| kyber768 | clean | 48.4% | 43.3% | 35.5% | -| kyber768 | m4fspeed | 75.4% | 74.9% | 69.6% | -| kyber768 | m4fstack | 75.4% | 74.5% | 69.3% | +| kyber1024 | clean | 49.9% | 45.6% | 38.6% | +| kyber1024 | m4fspeed | 76.1% | 75.5% | 71.2% | +| kyber1024 | m4fstack | 75.8% | 74.9% | 70.6% | +| kyber512 | clean | 49.8% | 41.1% | 32.5% | +| kyber512 | m4fspeed | 76.5% | 73.5% | 67.1% | +| kyber512 | m4fstack | 76.5% | 73.1% | 66.8% | +| kyber768 | clean | 48.5% | 43.2% | 35.4% | +| kyber768 | m4fspeed | 75.4% | 74.4% | 69.2% | +| kyber768 | m4fstack | 75.3% | 73.8% | 68.7% | ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | @@ -363,19 +369,21 @@ | dilithium5 | clean | 67.0% | 35.7% | 61.1% | | dilithium5 | m4f | 83.5% | 65.0% | 81.7% | | dilithium5 | m4fstack | 76.1% | 54.5% | 42.6% | -| falcon-1024 | clean | 6.5% | 0.3% | 23.7% | -| falcon-1024 | m4-ct | 7.4% | 0.4% | 32.4% | -| falcon-1024 | opt-ct | 11.7% | 0.4% | 32.2% | -| falcon-1024 | opt-leaktime | 12.3% | 0.5% | 32.4% | -| falcon-1024-tree | opt-ct | 5.2% | 0.9% | 32.3% | -| falcon-1024-tree | opt-leaktime | 11.9% | 0.9% | 32.4% | -| falcon-512 | clean | 10.9% | 0.4% | 26.0% | -| falcon-512 | m4-ct | 15.3% | 0.5% | 34.3% | -| falcon-512 | opt-ct | 17.2% | 0.5% | 33.6% | -| falcon-512 | opt-leaktime | 16.0% | 0.5% | 33.8% | -| falcon-512-tree | m4-ct | 18.4% | 1.1% | 33.9% | -| falcon-512-tree | opt-ct | 14.5% | 1.1% | 33.9% | -| falcon-512-tree | opt-leaktime | 18.7% | 1.0% | 33.9% | +| falcon-1024 | clean | 8.9% | 0.3% | 23.7% | +| falcon-1024 | m4-ct | 8.6% | 0.4% | 32.2% | +| falcon-1024 | opt-ct | 9.8% | 0.4% | 32.2% | +| falcon-1024 | opt-leaktime | 10.9% | 0.5% | 32.2% | +| falcon-1024-tree | opt-ct | 9.2% | 0.9% | 32.3% | +| falcon-1024-tree | opt-leaktime | 10.6% | 0.9% | 32.3% | +| falcon-512 | clean | 7.9% | 0.4% | 26.0% | +| falcon-512 | m4-ct | 13.7% | 0.5% | 33.9% | +| falcon-512 | opt-ct | 14.0% | 0.5% | 33.2% | +| falcon-512 | opt-leaktime | 17.3% | 0.5% | 33.6% | +| falcon-512-tree | m4-ct | 12.6% | 1.1% | 33.7% | +| falcon-512-tree | opt-ct | 14.6% | 1.1% | 34.2% | +| falcon-512-tree | opt-leaktime | 20.5% | 1.0% | 34.3% | +| falcon-padded-1024 | clean | 7.3% | 0.3% | 23.7% | +| falcon-padded-512 | clean | 16.0% | 0.4% | 26.0% | | haetae2 | m4f | 12.4% | 56.7% | 54.1% | | haetae2 | ref | 10.6% | 42.4% | 45.1% | | haetae3 | m4f | 14.6% | 56.6% | 57.1% | @@ -470,15 +478,15 @@ | hqc-128 | clean | 18,628 | 0 | 0 | 18,628 | | hqc-192 | clean | 21,104 | 0 | 0 | 21,104 | | hqc-256 | clean | 26,260 | 0 | 0 | 26,260 | -| kyber1024 | clean | 6,296 | 0 | 0 | 6,296 | -| kyber1024 | m4fspeed | 16,912 | 0 | 0 | 16,912 | -| kyber1024 | m4fstack | 14,120 | 0 | 0 | 14,120 | -| kyber512 | clean | 5,164 | 0 | 0 | 5,164 | -| kyber512 | m4fspeed | 15,824 | 0 | 0 | 15,824 | -| kyber512 | m4fstack | 13,308 | 0 | 0 | 13,308 | -| kyber768 | clean | 5,168 | 0 | 0 | 5,168 | -| kyber768 | m4fspeed | 15,992 | 0 | 0 | 15,992 | -| kyber768 | m4fstack | 13,316 | 0 | 0 | 13,316 | +| kyber1024 | clean | 6,264 | 0 | 0 | 6,264 | +| kyber1024 | m4fspeed | 16,884 | 0 | 0 | 16,884 | +| kyber1024 | m4fstack | 14,092 | 0 | 0 | 14,092 | +| kyber512 | clean | 5,132 | 0 | 0 | 5,132 | +| kyber512 | m4fspeed | 15,796 | 0 | 0 | 15,796 | +| kyber512 | m4fstack | 13,280 | 0 | 0 | 13,280 | +| kyber768 | clean | 5,136 | 0 | 0 | 5,136 | +| kyber768 | m4fspeed | 15,964 | 0 | 0 | 15,964 | +| kyber768 | m4fstack | 13,288 | 0 | 0 | 13,288 | ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | @@ -517,19 +525,21 @@ | dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | | dilithium5 | m4f | 18,468 | 0 | 0 | 18,468 | | dilithium5 | m4fstack | 23,820 | 0 | 0 | 23,820 | -| falcon-1024 | clean | 82,647 | 0 | 0 | 82,647 | +| falcon-1024 | clean | 82,703 | 0 | 0 | 82,703 | | falcon-1024 | m4-ct | 81,825 | 0 | 79,872 | 161,697 | | falcon-1024 | opt-ct | 81,825 | 0 | 79,872 | 161,697 | | falcon-1024 | opt-leaktime | 75,429 | 0 | 79,872 | 155,301 | | falcon-1024-tree | opt-ct | 81,569 | 0 | 55,296 | 136,865 | | falcon-1024-tree | opt-leaktime | 75,173 | 0 | 55,296 | 130,469 | -| falcon-512 | clean | 82,611 | 0 | 0 | 82,611 | +| falcon-512 | clean | 82,663 | 0 | 0 | 82,663 | | falcon-512 | m4-ct | 81,825 | 0 | 39,936 | 121,761 | | falcon-512 | opt-ct | 81,825 | 0 | 39,936 | 121,761 | | falcon-512 | opt-leaktime | 75,429 | 0 | 39,936 | 115,365 | | falcon-512-tree | m4-ct | 81,569 | 0 | 27,648 | 109,217 | | falcon-512-tree | opt-ct | 81,569 | 0 | 27,648 | 109,217 | | falcon-512-tree | opt-leaktime | 75,173 | 0 | 27,648 | 102,821 | +| falcon-padded-1024 | clean | 82,643 | 0 | 0 | 82,643 | +| falcon-padded-512 | clean | 82,599 | 0 | 0 | 82,599 | | haetae2 | m4f | 35,708 | 0 | 0 | 35,708 | | haetae2 | ref | 25,568 | 0 | 0 | 25,568 | | haetae3 | m4f | 35,936 | 0 | 0 | 35,936 | diff --git a/crypto_kem/kyber1024/m4fspeed/cmov_int16.S b/crypto_kem/kyber1024/m4fspeed/cmov_int16.S new file mode 120000 index 00000000..e57b8b26 --- /dev/null +++ b/crypto_kem/kyber1024/m4fspeed/cmov_int16.S @@ -0,0 +1 @@ +../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/cmov_int16.S b/crypto_kem/kyber1024/m4fstack/cmov_int16.S new file mode 120000 index 00000000..e57b8b26 --- /dev/null +++ b/crypto_kem/kyber1024/m4fstack/cmov_int16.S @@ -0,0 +1 @@ +../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/cmov_int16.S b/crypto_kem/kyber512/m4fspeed/cmov_int16.S new file mode 120000 index 00000000..e57b8b26 --- /dev/null +++ b/crypto_kem/kyber512/m4fspeed/cmov_int16.S @@ -0,0 +1 @@ +../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/poly.c b/crypto_kem/kyber512/m4fspeed/poly.c index 29861e69..401b26b7 100644 --- a/crypto_kem/kyber512/m4fspeed/poly.c +++ b/crypto_kem/kyber512/m4fspeed/poly.c @@ -606,6 +606,8 @@ void poly_sub(poly *r, const poly *a, const poly *b) { pointwise_sub(r->coeffs,a->coeffs,b->coeffs); } +void cmov_int16(int16_t *r, int16_t v, uint16_t b); + /************************************************* * Name: poly_frommsg * @@ -614,16 +616,20 @@ void poly_sub(poly *r, const poly *a, const poly *b) { * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *msg: pointer to input message **************************************************/ -void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { - int i, j; - uint16_t mask; +void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) +{ + unsigned int i,j; - for (i = 0; i < KYBER_SYMBYTES; i++) { - for (j = 0; j < 8; j++) { - mask = -((msg[i] >> j) & 1); - r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); - } +#if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) +#error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" +#endif + + for(i=0;icoeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } + } } /************************************************* diff --git a/crypto_kem/kyber512/m4fstack/cmov_int16.S b/crypto_kem/kyber512/m4fstack/cmov_int16.S new file mode 120000 index 00000000..e57b8b26 --- /dev/null +++ b/crypto_kem/kyber512/m4fstack/cmov_int16.S @@ -0,0 +1 @@ +../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/poly.c b/crypto_kem/kyber512/m4fstack/poly.c index cc849592..443fdbae 100644 --- a/crypto_kem/kyber512/m4fstack/poly.c +++ b/crypto_kem/kyber512/m4fstack/poly.c @@ -571,6 +571,8 @@ void poly_sub(poly *r, const poly *a, const poly *b) { pointwise_sub(r->coeffs,a->coeffs,b->coeffs); } +void cmov_int16(int16_t *r, int16_t v, uint16_t b); + /************************************************* * Name: poly_frommsg * @@ -579,16 +581,20 @@ void poly_sub(poly *r, const poly *a, const poly *b) { * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *msg: pointer to input message **************************************************/ -void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { - int i, j; - uint16_t mask; +void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) +{ + unsigned int i,j; - for (i = 0; i < KYBER_SYMBYTES; i++) { - for (j = 0; j < 8; j++) { - mask = -((msg[i] >> j) & 1); - r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); - } +#if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) +#error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" +#endif + + for(i=0;icoeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } + } } /************************************************* diff --git a/crypto_kem/kyber768/m4fspeed/cmov_int16.S b/crypto_kem/kyber768/m4fspeed/cmov_int16.S new file mode 100644 index 00000000..4f7dcc6c --- /dev/null +++ b/crypto_kem/kyber768/m4fspeed/cmov_int16.S @@ -0,0 +1,15 @@ +.syntax unified +.cpu cortex-m4 +.thumb + +// void cmov_int16(int16_t *r, int16_t v, uint16_t b) +.global cmov_int16 +.type cmov_int16, %function +.align 2 +cmov_int16: + cmp.w r2, #0 + ldrsh.w r3, [r0] + it ne + movne.w r3, r1 + strh.w r3, [r0] + bx lr \ No newline at end of file diff --git a/crypto_kem/kyber768/m4fspeed/poly.c b/crypto_kem/kyber768/m4fspeed/poly.c index f73f1acd..b52060f9 100644 --- a/crypto_kem/kyber768/m4fspeed/poly.c +++ b/crypto_kem/kyber768/m4fspeed/poly.c @@ -587,6 +587,9 @@ void poly_sub(poly *r, const poly *a, const poly *b) { pointwise_sub(r->coeffs,a->coeffs,b->coeffs); } + +void cmov_int16(int16_t *r, int16_t v, uint16_t b); + /************************************************* * Name: poly_frommsg * @@ -595,16 +598,20 @@ void poly_sub(poly *r, const poly *a, const poly *b) { * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *msg: pointer to input message **************************************************/ -void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { - int i, j; - uint16_t mask; +void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) +{ + unsigned int i,j; - for (i = 0; i < KYBER_SYMBYTES; i++) { - for (j = 0; j < 8; j++) { - mask = -((msg[i] >> j) & 1); - r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); - } +#if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) +#error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" +#endif + + for(i=0;icoeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } + } } /************************************************* diff --git a/crypto_kem/kyber768/m4fstack/cmov_int16.S b/crypto_kem/kyber768/m4fstack/cmov_int16.S new file mode 120000 index 00000000..9055f6ab --- /dev/null +++ b/crypto_kem/kyber768/m4fstack/cmov_int16.S @@ -0,0 +1 @@ +../m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber768/m4fstack/poly.c b/crypto_kem/kyber768/m4fstack/poly.c index 29b959f7..35475adb 100644 --- a/crypto_kem/kyber768/m4fstack/poly.c +++ b/crypto_kem/kyber768/m4fstack/poly.c @@ -552,6 +552,8 @@ void poly_sub(poly *r, const poly *a, const poly *b) { pointwise_sub(r->coeffs,a->coeffs,b->coeffs); } +void cmov_int16(int16_t *r, int16_t v, uint16_t b); + /************************************************* * Name: poly_frommsg * @@ -560,16 +562,20 @@ void poly_sub(poly *r, const poly *a, const poly *b) { * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *msg: pointer to input message **************************************************/ -void poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) { - int i, j; - uint16_t mask; +void poly_frommsg(poly *r, const uint8_t msg[KYBER_INDCPA_MSGBYTES]) +{ + unsigned int i,j; - for (i = 0; i < KYBER_SYMBYTES; i++) { - for (j = 0; j < 8; j++) { - mask = -((msg[i] >> j) & 1); - r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2); - } +#if (KYBER_INDCPA_MSGBYTES != KYBER_N/8) +#error "KYBER_INDCPA_MSGBYTES must be equal to KYBER_N/8 bytes!" +#endif + + for(i=0;icoeffs[8*i+j] = 0; + cmov_int16(r->coeffs+8*i+j, ((KYBER_Q+1)/2), (msg[i] >> j)&1); } + } } /************************************************* diff --git a/mupq b/mupq index 12d739e1..d5d4ed32 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 12d739e1112c383d9e1e0276465b2ea2cdb82604 +Subproject commit d5d4ed32d3016346c2c882f0ca3c951936364205 diff --git a/skiplist.py b/skiplist.py index b97c1b84..4f6a868b 100644 --- a/skiplist.py +++ b/skiplist.py @@ -240,4 +240,6 @@ {'scheme': 'dilithium2', 'implementation': 'm4fstack', 'estmemory': 12288}, {'scheme': 'dilithium5', 'implementation': 'm4fstack', 'estmemory': 21504}, {'scheme': 'dilithium3', 'implementation': 'm4fstack', 'estmemory': 17408}, + {'scheme': 'falcon-padded-1024', 'implementation': 'clean', 'estmemory': 91136}, + {'scheme': 'falcon-padded-512', 'implementation': 'clean', 'estmemory': 48128}, ] From f2b698a24055515bc0cb353dcf9afe6e545ebe84 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 6 Aug 2024 15:21:58 +0800 Subject: [PATCH 093/107] Improve Dilithium (speed) verification stack usage (#346) * Improve Dilithium (speed) verification stack usage Once upon a time, we wrote a paper on memory-efficient Dilithium [1] which included a speed-optimized version of verification that still included some memory optimizations that don't come at a performance penalty. Unfortunately with the update of the reference code to round 3 that version did not get migrated leading to some complaints about verification memory consumption. I finally found some time to port these. Verficication speed is essentially unchanged, but stack consumption is much better. [1] https://eprint.iacr.org/2020/1278.pdf * update benchmarks --- benchmarks.csv | 24 +++--- benchmarks.md | 24 +++--- crypto_sign/dilithium2/m4f/packing.c | 106 +++++++++++++++++++++++- crypto_sign/dilithium2/m4f/packing.h | 13 +++ crypto_sign/dilithium2/m4f/poly.c | 12 +++ crypto_sign/dilithium2/m4f/poly.h | 2 + crypto_sign/dilithium2/m4f/sign.c | 117 ++++++++++++++++++--------- crypto_sign/dilithium2/m4f/vector.h | 2 + crypto_sign/dilithium2/m4f/vector.s | 53 ++++++++++++ 9 files changed, 289 insertions(+), 64 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index 952b95f8..c614c534 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -46,13 +46,13 @@ cross-sha3-r-sdpg-1-small (10 executions),ref,290135,287741,297757,102853622,102 cross-sha3-r-sdpg-3-fast (10 executions),ref,627948,625525,637639,43573841,43565461,43582933,27513830,27493024,27525746 cross-sha3-r-sdpg-5-fast (10 executions),ref,1146280,1142409,1153794,93557878,93547167,93566329,59948216,59857434,60043852 dilithium2 (1000 executions),clean,1874167,1827645,1914566,7493877,3321630,40762756,2062795,2062255,2063222 -dilithium2 (1000 executions),m4f,1426036,1379636,1466394,3807970,1813656,18528070,1417745,1417203,1418192 +dilithium2 (1000 executions),m4f,1425723,1379410,1466445,3835095,1813682,16068642,1421307,1420219,1422056 dilithium2 (1000 executions),m4fstack,1801523,1684895,1902114,12170976,3900911,86281518,3241353,3194028,3281144 dilithium3 (1000 executions),clean,3205551,3204090,3207411,12696585,5097364,74392293,3376992,3376581,3377393 -dilithium3 (1000 executions),m4f,2515969,2514498,2517634,5884832,2917322,25268693,2411257,2410858,2411717 +dilithium3 (1000 executions),m4f,2515915,2514307,2517413,6054094,2917316,27829552,2415526,2414696,2416440 dilithium3 (1000 executions),m4fstack,3412759,3406659,3419247,23673016,6733971,145803146,5733307,5688893,5778120 dilithium5 (1000 executions),clean,5341477,5286872,5395822,15710371,7953367,75940093,5609679,5609217,5610183 -dilithium5 (1000 executions),m4f,4275029,4210286,4329519,7977781,4882524,25936176,4185417,4184925,4185896 +dilithium5 (1000 executions),m4f,4275033,4220989,4350945,8349360,4882552,29688762,4192692,4191427,4193764 dilithium5 (1000 executions),m4fstack,5816287,5474236,6115061,33452872,11170780,185259803,9912851,9845789,9981834 falcon-1024 (10 executions),clean,602066436,377135260,1488065363,136241759,136017549,136556585,1678109,1677732,1678566 falcon-1024 (10 executions),m4-ct,408725773,314885208,712370124,87706019,87549942,87839508,990541,984448,997160 @@ -200,13 +200,13 @@ cross-sha3-r-sdpg-1-small,ref,2328,466400,245512,,,,,, cross-sha3-r-sdpg-3-fast,ref,4032,205080,108236,,,,,, cross-sha3-r-sdpg-5-fast,ref,6824,398600,213436,,,,,, dilithium2,clean,38304,51968,36192,,,,,, -dilithium2,m4f,38296,49416,36220,,,,,, +dilithium2,m4f,38296,49416,9012,,,,,, dilithium2,m4fstack,4408,5072,2704,,,,,, dilithium3,clean,60832,79616,57728,,,,,, -dilithium3,m4f,60824,68864,57720,,,,,, +dilithium3,m4f,60824,68864,9880,,,,,, dilithium3,m4fstack,4408,6608,2704,,,,,, dilithium5,clean,97696,122724,92940,,,,,, -dilithium5,m4f,97688,116076,92932,,,,,, +dilithium5,m4f,97688,116076,11944,,,,,, dilithium5,m4fstack,4408,8136,2712,,,,,, falcon-1024,clean,35076,84604,8776,,,,,, falcon-1024,m4-ct,1156,2508,376,,,,,, @@ -355,13 +355,13 @@ cross-sha3-r-sdpg-1-small,ref,71.8,74.7,78.4,,,,,, cross-sha3-r-sdpg-3-fast,ref,71.7,68.2,68.7,,,,,, cross-sha3-r-sdpg-5-fast,ref,71.1,66.1,66.8,,,,,, dilithium2,clean,61.0,30.9,52.9,,,,,, -dilithium2,m4f,79.9,60.6,76.8,,,,,, +dilithium2,m4f,79.9,60.7,76.6,,,,,, dilithium2,m4fstack,74.8,55.2,40.8,,,,,, dilithium3,clean,64.7,31.3,56.8,,,,,, -dilithium3,m4f,82.3,60.3,79.4,,,,,, +dilithium3,m4f,82.3,60.7,79.2,,,,,, dilithium3,m4fstack,77.1,54.6,41.0,,,,,, dilithium5,clean,67.0,35.7,61.1,,,,,, -dilithium5,m4f,83.5,65.0,81.7,,,,,, +dilithium5,m4f,83.5,65.3,81.6,,,,,, dilithium5,m4fstack,76.1,54.5,42.6,,,,,, falcon-1024,clean,8.9,0.3,23.7,,,,,, falcon-1024,m4-ct,8.6,0.4,32.2,,,,,, @@ -509,13 +509,13 @@ cross-sha3-r-sdpg-1-small,ref,18846,0,208,19054,,,,, cross-sha3-r-sdpg-3-fast,ref,19689,0,208,19897,,,,, cross-sha3-r-sdpg-5-fast,ref,18593,0,208,18801,,,,, dilithium2,clean,8064,0,0,8064,,,,, -dilithium2,m4f,18596,0,0,18596,,,,, +dilithium2,m4f,19180,0,0,19180,,,,, dilithium2,m4fstack,24184,0,0,24184,,,,, dilithium3,clean,7580,0,0,7580,,,,, -dilithium3,m4f,18588,0,0,18588,,,,, +dilithium3,m4f,19188,0,0,19188,,,,, dilithium3,m4fstack,23448,0,0,23448,,,,, dilithium5,clean,7808,0,0,7808,,,,, -dilithium5,m4f,18468,0,0,18468,,,,, +dilithium5,m4f,19096,0,0,19096,,,,, dilithium5,m4fstack,23820,0,0,23820,,,,, falcon-1024,clean,82703,0,0,82703,,,,, falcon-1024,m4-ct,81825,0,79872,161697,,,,, diff --git a/benchmarks.md b/benchmarks.md index afb0ab01..87df4aa4 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -48,13 +48,13 @@ | cross-sha3-r-sdpg-3-fast (10 executions) | ref | AVG: 627,948
MIN: 625,525
MAX: 637,639 | AVG: 43,573,841
MIN: 43,565,461
MAX: 43,582,933 | AVG: 27,513,830
MIN: 27,493,024
MAX: 27,525,746 | | cross-sha3-r-sdpg-5-fast (10 executions) | ref | AVG: 1,146,280
MIN: 1,142,409
MAX: 1,153,794 | AVG: 93,557,878
MIN: 93,547,167
MAX: 93,566,329 | AVG: 59,948,216
MIN: 59,857,434
MAX: 60,043,852 | | dilithium2 (1000 executions) | clean | AVG: 1,874,167
MIN: 1,827,645
MAX: 1,914,566 | AVG: 7,493,877
MIN: 3,321,630
MAX: 40,762,756 | AVG: 2,062,795
MIN: 2,062,255
MAX: 2,063,222 | -| dilithium2 (1000 executions) | m4f | AVG: 1,426,036
MIN: 1,379,636
MAX: 1,466,394 | AVG: 3,807,970
MIN: 1,813,656
MAX: 18,528,070 | AVG: 1,417,745
MIN: 1,417,203
MAX: 1,418,192 | +| dilithium2 (1000 executions) | m4f | AVG: 1,425,723
MIN: 1,379,410
MAX: 1,466,445 | AVG: 3,835,095
MIN: 1,813,682
MAX: 16,068,642 | AVG: 1,421,307
MIN: 1,420,219
MAX: 1,422,056 | | dilithium2 (1000 executions) | m4fstack | AVG: 1,801,523
MIN: 1,684,895
MAX: 1,902,114 | AVG: 12,170,976
MIN: 3,900,911
MAX: 86,281,518 | AVG: 3,241,353
MIN: 3,194,028
MAX: 3,281,144 | | dilithium3 (1000 executions) | clean | AVG: 3,205,551
MIN: 3,204,090
MAX: 3,207,411 | AVG: 12,696,585
MIN: 5,097,364
MAX: 74,392,293 | AVG: 3,376,992
MIN: 3,376,581
MAX: 3,377,393 | -| dilithium3 (1000 executions) | m4f | AVG: 2,515,969
MIN: 2,514,498
MAX: 2,517,634 | AVG: 5,884,832
MIN: 2,917,322
MAX: 25,268,693 | AVG: 2,411,257
MIN: 2,410,858
MAX: 2,411,717 | +| dilithium3 (1000 executions) | m4f | AVG: 2,515,915
MIN: 2,514,307
MAX: 2,517,413 | AVG: 6,054,094
MIN: 2,917,316
MAX: 27,829,552 | AVG: 2,415,526
MIN: 2,414,696
MAX: 2,416,440 | | dilithium3 (1000 executions) | m4fstack | AVG: 3,412,759
MIN: 3,406,659
MAX: 3,419,247 | AVG: 23,673,016
MIN: 6,733,971
MAX: 145,803,146 | AVG: 5,733,307
MIN: 5,688,893
MAX: 5,778,120 | | dilithium5 (1000 executions) | clean | AVG: 5,341,477
MIN: 5,286,872
MAX: 5,395,822 | AVG: 15,710,371
MIN: 7,953,367
MAX: 75,940,093 | AVG: 5,609,679
MIN: 5,609,217
MAX: 5,610,183 | -| dilithium5 (1000 executions) | m4f | AVG: 4,275,029
MIN: 4,210,286
MAX: 4,329,519 | AVG: 7,977,781
MIN: 4,882,524
MAX: 25,936,176 | AVG: 4,185,417
MIN: 4,184,925
MAX: 4,185,896 | +| dilithium5 (1000 executions) | m4f | AVG: 4,275,033
MIN: 4,220,989
MAX: 4,350,945 | AVG: 8,349,360
MIN: 4,882,552
MAX: 29,688,762 | AVG: 4,192,692
MIN: 4,191,427
MAX: 4,193,764 | | dilithium5 (1000 executions) | m4fstack | AVG: 5,816,287
MIN: 5,474,236
MAX: 6,115,061 | AVG: 33,452,872
MIN: 11,170,780
MAX: 185,259,803 | AVG: 9,912,851
MIN: 9,845,789
MAX: 9,981,834 | | falcon-1024 (10 executions) | clean | AVG: 602,066,436
MIN: 377,135,260
MAX: 1,488,065,363 | AVG: 136,241,759
MIN: 136,017,549
MAX: 136,556,585 | AVG: 1,678,109
MIN: 1,677,732
MAX: 1,678,566 | | falcon-1024 (10 executions) | m4-ct | AVG: 408,725,773
MIN: 314,885,208
MAX: 712,370,124 | AVG: 87,706,019
MIN: 87,549,942
MAX: 87,839,508 | AVG: 990,541
MIN: 984,448
MAX: 997,160 | @@ -204,13 +204,13 @@ | cross-sha3-r-sdpg-3-fast | ref | 4,032 | 205,080 | 108,236 | | cross-sha3-r-sdpg-5-fast | ref | 6,824 | 398,600 | 213,436 | | dilithium2 | clean | 38,304 | 51,968 | 36,192 | -| dilithium2 | m4f | 38,296 | 49,416 | 36,220 | +| dilithium2 | m4f | 38,296 | 49,416 | 9,012 | | dilithium2 | m4fstack | 4,408 | 5,072 | 2,704 | | dilithium3 | clean | 60,832 | 79,616 | 57,728 | -| dilithium3 | m4f | 60,824 | 68,864 | 57,720 | +| dilithium3 | m4f | 60,824 | 68,864 | 9,880 | | dilithium3 | m4fstack | 4,408 | 6,608 | 2,704 | | dilithium5 | clean | 97,696 | 122,724 | 92,940 | -| dilithium5 | m4f | 97,688 | 116,076 | 92,932 | +| dilithium5 | m4f | 97,688 | 116,076 | 11,944 | | dilithium5 | m4fstack | 4,408 | 8,136 | 2,712 | | falcon-1024 | clean | 35,076 | 84,604 | 8,776 | | falcon-1024 | m4-ct | 1,156 | 2,508 | 376 | @@ -361,13 +361,13 @@ | cross-sha3-r-sdpg-3-fast | ref | 71.7% | 68.2% | 68.7% | | cross-sha3-r-sdpg-5-fast | ref | 71.1% | 66.1% | 66.8% | | dilithium2 | clean | 61.0% | 30.9% | 52.9% | -| dilithium2 | m4f | 79.9% | 60.6% | 76.8% | +| dilithium2 | m4f | 79.9% | 60.7% | 76.6% | | dilithium2 | m4fstack | 74.8% | 55.2% | 40.8% | | dilithium3 | clean | 64.7% | 31.3% | 56.8% | -| dilithium3 | m4f | 82.3% | 61.4% | 79.4% | +| dilithium3 | m4f | 82.3% | 60.7% | 79.2% | | dilithium3 | m4fstack | 77.1% | 54.6% | 41.0% | | dilithium5 | clean | 67.0% | 35.7% | 61.1% | -| dilithium5 | m4f | 83.5% | 65.0% | 81.7% | +| dilithium5 | m4f | 83.5% | 65.3% | 81.6% | | dilithium5 | m4fstack | 76.1% | 54.5% | 42.6% | | falcon-1024 | clean | 8.9% | 0.3% | 23.7% | | falcon-1024 | m4-ct | 8.6% | 0.4% | 32.2% | @@ -517,13 +517,13 @@ | cross-sha3-r-sdpg-3-fast | ref | 19,689 | 0 | 208 | 19,897 | | cross-sha3-r-sdpg-5-fast | ref | 18,593 | 0 | 208 | 18,801 | | dilithium2 | clean | 8,064 | 0 | 0 | 8,064 | -| dilithium2 | m4f | 18,596 | 0 | 0 | 18,596 | +| dilithium2 | m4f | 19,180 | 0 | 0 | 19,180 | | dilithium2 | m4fstack | 24,184 | 0 | 0 | 24,184 | | dilithium3 | clean | 7,580 | 0 | 0 | 7,580 | -| dilithium3 | m4f | 18,588 | 0 | 0 | 18,588 | +| dilithium3 | m4f | 19,188 | 0 | 0 | 19,188 | | dilithium3 | m4fstack | 23,448 | 0 | 0 | 23,448 | | dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | -| dilithium5 | m4f | 18,468 | 0 | 0 | 18,468 | +| dilithium5 | m4f | 19,096 | 0 | 0 | 19,096 | | dilithium5 | m4fstack | 23,820 | 0 | 0 | 23,820 | | falcon-1024 | clean | 82,703 | 0 | 0 | 82,703 | | falcon-1024 | m4-ct | 81,825 | 0 | 79,872 | 161,697 | diff --git a/crypto_sign/dilithium2/m4f/packing.c b/crypto_sign/dilithium2/m4f/packing.c index 8aaff2a3..eb9d9a3e 100644 --- a/crypto_sign/dilithium2/m4f/packing.c +++ b/crypto_sign/dilithium2/m4f/packing.c @@ -2,6 +2,7 @@ #include "packing.h" #include "polyvec.h" #include "poly.h" +#include /************************************************* * Name: pack_pk @@ -49,6 +50,21 @@ void unpack_pk(uint8_t rho[SEEDBYTES], polyt1_unpack(&t1->vec[i], pk + i*POLYT1_PACKEDBYTES); } +/************************************************* +* Name: unpack_pk_t1 +* +* Description: Unpack public key pk = (rho, t1). +* +* Arguments: - const polyvec *t1: pointer to output vector t1 +* - const size_t idx: unpack n'th element from t1 +* - unsigned char pk[]: byte array containing bit-packed pk +**************************************************/ +void unpack_pk_t1(poly *t1, size_t idx, const unsigned char pk[CRYPTO_PUBLICKEYBYTES]) { + pk += SEEDBYTES; + polyt1_unpack(t1, pk + idx * POLYT1_PACKEDBYTES); +} + + /************************************************* * Name: pack_sk * @@ -283,4 +299,92 @@ int unpack_sig(uint8_t c[CTILDEBYTES], return 1; return 0; -} \ No newline at end of file +} + +/************************************************* +* Name: unpack_sig_c +* +* Description: Unpack only c from signature sig = (z, h, c). +* +* Arguments: - poly *c: pointer to output challenge polynomial +* - const unsigned char sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig_c(uint8_t c[CTILDEBYTES], const unsigned char sig[CRYPTO_BYTES]) { + for(size_t i = 0; i < CTILDEBYTES; ++i) + c[i] = sig[i]; + sig += CTILDEBYTES; + return 0; +} + +/************************************************* +* Name: unpack_sig_z +* +* Description: Unpack only z from signature sig = (z, h, c). +* +* Arguments: - polyvecl *z: pointer to output vector z +* - const unsigned char sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig_z(polyvecl *z, const unsigned char sig[CRYPTO_BYTES]) { + sig += CTILDEBYTES; + for (size_t i = 0; i < L; ++i) { + polyz_unpack(&z->vec[i], sig + i * POLYZ_PACKEDBYTES); + } + return 0; +} + +/************************************************* +* Name: unpack_sig_h +* +* Description: Unpack only h from signature sig = (z, h, c). +* +* Arguments: - polyveck *h: pointer to output hint vector h +* - const unsigned char sig[]: byte array containing +* bit-packed signature +* +* Returns 1 in case of malformed signature; otherwise 0. +**************************************************/ +int unpack_sig_h(poly *h, size_t idx, const unsigned char sig[CRYPTO_BYTES]) { + sig += CTILDEBYTES; + sig += L * POLYZ_PACKEDBYTES; + + /* Decode h */ + size_t k = 0; + for (size_t i = 0; i < K; ++i) { + for (size_t j = 0; j < N; ++j) { + if (i == idx) { + h->coeffs[j] = 0; + } + } + + if (sig[OMEGA + i] < k || sig[OMEGA + i] > OMEGA) { + return 1; + } + + for (size_t j = k; j < sig[OMEGA + i]; ++j) { + /* Coefficients are ordered for strong unforgeability */ + if (j > k && sig[j] <= sig[j - 1]) { + return 1; + } + if (i == idx) { + h->coeffs[sig[j]] = 1; + } + } + + k = sig[OMEGA + i]; + } + + /* Extra indices are zero for strong unforgeability */ + for (size_t j = k; j < OMEGA; ++j) { + if (sig[j]) { + return 1; + } + } + return 0; +} + diff --git a/crypto_sign/dilithium2/m4f/packing.h b/crypto_sign/dilithium2/m4f/packing.h index 35553545..78ef2c2c 100644 --- a/crypto_sign/dilithium2/m4f/packing.h +++ b/crypto_sign/dilithium2/m4f/packing.h @@ -2,6 +2,7 @@ #define PACKING_H #include +#include #include "params.h" #include "polyvec.h" #include "smallpoly.h" @@ -24,6 +25,9 @@ void pack_sig(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES], const pol #define unpack_pk DILITHIUM_NAMESPACE(unpack_pk) void unpack_pk(uint8_t rho[SEEDBYTES], polyveck *t1, const uint8_t pk[CRYPTO_PUBLICKEYBYTES]); +#define unpack_pk_t1 DILITHIUM_NAMESPACE(unpack_pk_t1) +void unpack_pk_t1(poly *t1, size_t idx, const unsigned char pk[CRYPTO_PUBLICKEYBYTES]); + #define unpack_sk DILITHIUM_NAMESPACE(unpack_sk) void unpack_sk(uint8_t rho[SEEDBYTES], uint8_t tr[TRBYTES], @@ -36,6 +40,15 @@ void unpack_sk(uint8_t rho[SEEDBYTES], #define unpack_sig DILITHIUM_NAMESPACE(unpack_sig) int unpack_sig(uint8_t c[CTILDEBYTES], polyvecl *z, polyveck *h, const uint8_t sig[CRYPTO_BYTES]); + +#define unpack_sig_z DILITHIUM_NAMESPACE(unpack_sig_z) +int unpack_sig_z(polyvecl *z, const unsigned char sig[CRYPTO_BYTES]); +#define unpack_sig_h DILITHIUM_NAMESPACE(unpack_sig_h) +int unpack_sig_h(poly *h, size_t idx, const unsigned char sig[CRYPTO_BYTES]); +#define unpack_sig_c DILITHIUM_NAMESPACE(unpack_sig_c) +int unpack_sig_c(uint8_t c[CTILDEBYTES], const unsigned char sig[CRYPTO_BYTES]); + + #define pack_sig_c DILITHIUM_NAMESPACE(pack_sig_c) void pack_sig_c(uint8_t sig[CRYPTO_BYTES], const uint8_t c[CTILDEBYTES]); diff --git a/crypto_sign/dilithium2/m4f/poly.c b/crypto_sign/dilithium2/m4f/poly.c index 0d40fda3..654f4f23 100644 --- a/crypto_sign/dilithium2/m4f/poly.c +++ b/crypto_sign/dilithium2/m4f/poly.c @@ -45,6 +45,18 @@ void poly_caddq(poly *a) { asm_caddq(a->coeffs); } +/************************************************* +* Name: poly_csubq +* +* Description: For all coefficients of input polynomial subtract Q if +* coefficient is bigger than Q; add Q if coefficient is negative. +* +* Arguments: - poly *a: pointer to input/output polynomial +**************************************************/ +void poly_csubq(poly *a) { + asm_caddq(a->coeffs); +} + #if 0 /************************************************* * Name: poly_freeze diff --git a/crypto_sign/dilithium2/m4f/poly.h b/crypto_sign/dilithium2/m4f/poly.h index 8f8819b0..af9e7a50 100644 --- a/crypto_sign/dilithium2/m4f/poly.h +++ b/crypto_sign/dilithium2/m4f/poly.h @@ -12,6 +12,8 @@ typedef struct { void poly_reduce(poly *a); #define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) void poly_caddq(poly *a); +#define poly_csubq DILITHIUM_NAMESPACE(poly_csubq) +void poly_csubq(poly *a); #define poly_freeze DILITHIUM_NAMESPACE(poly_freeze) void poly_freeze(poly *a); diff --git a/crypto_sign/dilithium2/m4f/sign.c b/crypto_sign/dilithium2/m4f/sign.c index 04bec45c..d1c5222b 100644 --- a/crypto_sign/dilithium2/m4f/sign.c +++ b/crypto_sign/dilithium2/m4f/sign.c @@ -225,20 +225,36 @@ int crypto_sign(uint8_t *sm, *smlen += mlen; return 0; } +/************************************************* + * Name: expand_mat_elem + * + * Description: Implementation of ExpandA. Generates matrix A with uniformly + * random coefficients a_{i,j} by performing rejection + * sampling on the output stream of SHAKE128(rho|i|j). + * + * Arguments: - poly mat_elem: output matrix element + * - const unsigned char rho[]: byte array containing seed rho + * - k_idx: matrix row index + * - l_idx: matrix col index + **************************************************/ +static void expand_mat_elem(poly *mat_elem, const unsigned char rho[SEEDBYTES], size_t k_idx, size_t l_idx) +{ + poly_uniform(mat_elem, rho, (uint16_t)((k_idx << 8) + l_idx)); +} /************************************************* -* Name: crypto_sign_verify -* -* Description: Verifies signature. -* -* Arguments: - uint8_t *m: pointer to input signature -* - size_t siglen: length of signature -* - const uint8_t *m: pointer to message -* - size_t mlen: length of message -* - const uint8_t *pk: pointer to bit-packed public key -* -* Returns 0 if signature could be verified correctly and -1 otherwise -**************************************************/ + * Name: crypto_sign_verify + * + * Description: Verifies signature. + * + * Arguments: - uint8_t *m: pointer to input signature + * - size_t siglen: length of signature + * - const uint8_t *m: pointer to message + * - size_t mlen: length of message + * - const uint8_t *pk: pointer to bit-packed public key + * + * Returns 0 if signature could be verified correctly and -1 otherwise + **************************************************/ int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, @@ -246,23 +262,23 @@ int crypto_sign_verify(const uint8_t *sig, const uint8_t *pk) { unsigned int i; - uint8_t buf[K*POLYW1_PACKEDBYTES]; - uint8_t rho[SEEDBYTES]; + const uint8_t *rho = pk; uint8_t mu[CRHBYTES]; uint8_t c[CTILDEBYTES]; uint8_t c2[CTILDEBYTES]; poly cp; - polyvecl mat[K], z; - polyveck t1, w1, h; + polyvecl z; shake256incctx state; - if(siglen != CRYPTO_BYTES) + poly tmp_elem, w1_elem; + + if (siglen != CRYPTO_BYTES) return -1; - unpack_pk(rho, &t1, pk); - if(unpack_sig(c, &z, &h, sig)) + if (unpack_sig_z(&z, sig) != 0) { return -1; - if(polyvecl_chknorm(&z, GAMMA1 - BETA)) + } + if (polyvecl_chknorm(&z, GAMMA1 - BETA)) return -1; /* Compute CRH(h(rho, t1), msg) */ @@ -273,35 +289,58 @@ int crypto_sign_verify(const uint8_t *sig, shake256_inc_finalize(&state); shake256_inc_squeeze(mu, CRHBYTES, &state); + // Hash [mu || w1'] to get c. + shake256_inc_init(&state); + shake256_inc_absorb(&state, mu, CRHBYTES); + /* Matrix-vector multiplication; compute Az - c2^dt1 */ + if (unpack_sig_c(c, sig) != 0) { + return -1; + } poly_challenge(&cp, c); - polyvec_matrix_expand(mat, rho); - + poly_ntt(&cp); polyvecl_ntt(&z); - polyvec_matrix_pointwise_montgomery(&w1, mat, &z); - poly_ntt(&cp); - polyveck_shiftl(&t1); - polyveck_ntt(&t1); - polyveck_pointwise_poly_montgomery(&t1, &cp, &t1); - polyveck_sub(&w1, &w1, &t1); - polyveck_reduce(&w1); - polyveck_invntt_tomont(&w1); + for (size_t k_idx = 0; k_idx < K; k_idx++) + { + // Sample the current element from A. + expand_mat_elem(&tmp_elem, rho, k_idx, 0); + poly_pointwise_montgomery(&w1_elem, &tmp_elem, &z.vec[0]); + + for (size_t l_idx = 1; l_idx < L; l_idx++) + { + // Sample the element from A. + expand_mat_elem(&tmp_elem, rho, k_idx, l_idx); + poly_pointwise_acc_montgomery(&w1_elem, &tmp_elem, &z.vec[l_idx]); + } + + // Subtract c*(t1_{k_idx} * 2^d) + unpack_pk_t1(&tmp_elem, k_idx, pk); + poly_shiftl(&tmp_elem); + poly_ntt(&tmp_elem); + poly_pointwise_montgomery(&tmp_elem, &cp, &tmp_elem); + poly_sub(&w1_elem, &w1_elem, &tmp_elem); + poly_reduce(&w1_elem); + poly_invntt_tomont(&w1_elem); + + // Reconstruct w1 + poly_csubq(&w1_elem); + if (unpack_sig_h(&tmp_elem, k_idx, sig) != 0) { + return -1; + } + poly_use_hint(&w1_elem, &w1_elem, &tmp_elem); + uint8_t w1_packed[POLYW1_PACKEDBYTES]; + polyw1_pack(w1_packed, &w1_elem); + shake256_inc_absorb(&state, w1_packed, POLYW1_PACKEDBYTES); + } - /* Reconstruct w1 */ - polyveck_caddq(&w1); - polyveck_use_hint(&w1, &w1, &h); - polyveck_pack_w1(buf, &w1); /* Call random oracle and verify challenge */ - shake256_inc_init(&state); - shake256_inc_absorb(&state, mu, CRHBYTES); - shake256_inc_absorb(&state, buf, K*POLYW1_PACKEDBYTES); shake256_inc_finalize(&state); shake256_inc_squeeze(c2, CTILDEBYTES, &state); - for(i = 0; i < CTILDEBYTES; ++i) - if(c[i] != c2[i]) + for (i = 0; i < CTILDEBYTES; ++i) + if (c[i] != c2[i]) return -1; return 0; diff --git a/crypto_sign/dilithium2/m4f/vector.h b/crypto_sign/dilithium2/m4f/vector.h index e5c5dda3..183ddc83 100644 --- a/crypto_sign/dilithium2/m4f/vector.h +++ b/crypto_sign/dilithium2/m4f/vector.h @@ -10,6 +10,8 @@ void asm_reduce32(int32_t a[N]); void small_asm_reduce32_central(int32_t a[N]); #define asm_caddq DILITHIUM_NAMESPACE(asm_caddq) void asm_caddq(int32_t a[N]); +#define asm_csubq DILITHIUM_NAMESPACE(asm_csubq) +void asm_csubq(int32_t a[N]); #define asm_freeze DILITHIUM_NAMESPACE(asm_freeze) void asm_freeze(int32_t a[N]); #define asm_rej_uniform DILITHIUM_NAMESPACE(asm_rej_uniform) diff --git a/crypto_sign/dilithium2/m4f/vector.s b/crypto_sign/dilithium2/m4f/vector.s index 559f11b0..a393c914 100644 --- a/crypto_sign/dilithium2/m4f/vector.s +++ b/crypto_sign/dilithium2/m4f/vector.s @@ -169,6 +169,59 @@ pqcrystals_dilithium_asm_caddq: bx lr .size pqcrystals_dilithium_asm_caddq, .-pqcrystals_dilithium_asm_caddq +.macro csubq a, tmp, q + cmp.n \a, \q + it ge + subge.w \a, \a, \q + cmp \a, #0 + it mi + addmi.w \a, \a, \q +.endm + +// void asm_csubq(int32_t a[N]); +.global pqcrystals_dilithium_asm_csubq +.type pqcrystals_dilithium_asm_csubq, %function +.align 2 +pqcrystals_dilithium_asm_csubq: + push {r4-r10} + + movw r12,#:lower16:8380417 + movt r12,#:upper16:8380417 + + movw r10, #32 + 1: + ldr.w r1, [r0] + ldr.w r2, [r0, #1*4] + ldr.w r3, [r0, #2*4] + ldr.w r4, [r0, #3*4] + ldr.w r5, [r0, #4*4] + ldr.w r6, [r0, #5*4] + ldr.w r7, [r0, #6*4] + ldr.w r8, [r0, #7*4] + + csubq r1, r9, r12 + csubq r2, r9, r12 + csubq r3, r9, r12 + csubq r4, r9, r12 + csubq r5, r9, r12 + csubq r6, r9, r12 + csubq r7, r9, r12 + csubq r8, r9, r12 + + str.w r2, [r0, #1*4] + str.w r3, [r0, #2*4] + str.w r4, [r0, #3*4] + str.w r5, [r0, #4*4] + str.w r6, [r0, #5*4] + str.w r7, [r0, #6*4] + str.w r8, [r0, #7*4] + str r1, [r0], #8*4 + subs r10, #1 + bne.w 1b + + pop {r4-r10} + bx lr +.size pqcrystals_dilithium_asm_csubq, .-pqcrystals_dilithium_asm_csubq // asm_rej_uniform(int32_t *a,unsigned int len,const unsigned char *buf, unsigned int buflen); .global pqcrystals_dilithium_asm_rej_uniform From 7cead3c69e9f9c5faa8e6c942e6e0749f6503796 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 6 Aug 2024 15:27:24 +0800 Subject: [PATCH 094/107] Add dependabot --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..4c35da08 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "gitsubmodule" + directory: '/' + schedule: + interval: "monthly" From 6554684c0e7a51a102d0d8c91d2a11abb362598d Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 12 Aug 2024 21:38:20 +0800 Subject: [PATCH 095/107] Update AIMer implementations (#350) * add skiplist entries for new aimer implementations * remove old aimer benchmarks * add AIMer benchmarks * add missing aimer-128f benchmarks * track correct version of mupq --- benchmarks.csv | 48 ++++++++++++++++++++++++++++++++++++------------ benchmarks.md | 48 ++++++++++++++++++++++++++++++++++++------------ mupq | 2 +- skiplist.py | 19 ++++++++++++------- 4 files changed, 85 insertions(+), 32 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index c614c534..28be1159 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -19,9 +19,15 @@ kyber768 (10 executions),m4fspeed,631912,631599,632459,656455,656155,656969,7055 kyber768 (10 executions),m4fstack,634213,632786,644273,662556,661130,672615,712081,710655,722140 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) -aimer-l1-param1 (10 executions),ref,392943,392938,392977,32386301,32386203,32386424,31111672,31111588,31111782 -aimer-l1-param2 (10 executions),ref,392938,392938,392941,79450721,79450349,79451595,78429263,78398061,78434987 -aimer-l3-param1 (10 executions),ref,981288,981288,981290,90953716,90953603,90953763,88350755,88350600,88350906 +aimer128f (10 executions),mem_opt,564325,564324,564326,46875341,46874593,46876276,26989249,26988505,26989828 +aimer128f (10 executions),ref,564323,564323,564324,28991142,28991115,28991171,26994617,26994234,26994927 +aimer128s (10 executions),mem_opt,564323,564323,564325,374834586,374834473,374834973,227230761,227230441,227230833 +aimer192f (10 executions),mem_opt,1397043,1397043,1397043,117993511,117991579,117995094,76372135,76370763,76373839 +aimer192f (10 executions),ref,1397040,1397040,1397041,81884026,81883991,81884035,76458825,76456517,76460984 +aimer192s (10 executions),mem_opt,1397047,1397039,1397079,916637185,916637133,916637425,629249382,629249345,629249415 +aimer256f (10 executions),mem_opt,3344254,3344250,3344255,233973308,233969892,233976707,170620601,170617448,170623743 +aimer256f (10 executions),ref,3344258,3344255,3344292,164484408,164483962,164484481,170648722,170647189,170651027 +aimer256s (10 executions),mem_opt,3344262,3344252,3344293,1752719642,1752719422,1752720844,1361337862,1361336718,1361338013 ascon-sign-128f-robust (10 executions),ref,122506162,122506099,122506254,2855797836,2855797243,2855798602,174707763,169973472,179525137 ascon-sign-128f-simple (10 executions),ref,69376878,69376875,69376883,1629111557,1629111334,1629112028,97798317,95509050,98714007 ascon-sign-128s-robust (10 executions),ref,7842366557,7842366432,7842366620,59267552580,59267543517,59267565672,60232378,57865239,62848708 @@ -173,9 +179,15 @@ kyber768,m4fspeed,5396,6468,6452,,,,,, kyber768,m4fstack,2820,2860,2844,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, -aimer-l1-param1,ref,10952,187724,196728,,,,,, -aimer-l1-param2,ref,10952,442668,451672,,,,,, -aimer-l3-param1,ref,23864,413940,435640,,,,,, +aimer128f,mem_opt,8728,13864,15440,,,,,, +aimer128f,ref,8728,123376,15448,,,,,, +aimer128s,mem_opt,8728,27324,34624,,,,,, +aimer192f,mem_opt,19192,29976,31608,,,,,, +aimer192f,ref,19192,273104,31608,,,,,, +aimer192s,mem_opt,19192,43220,60384,,,,,, +aimer256f,mem_opt,50040,77164,78568,,,,,, +aimer256f,ref,50040,573284,78716,,,,,, +aimer256s,mem_opt,50040,76140,117044,,,,,, ascon-sign-128f-robust,ref,3260,2772,2992,,,,,, ascon-sign-128f-simple,ref,2632,2144,2448,,,,,, ascon-sign-128s-robust,ref,3452,2916,2240,,,,,, @@ -328,9 +340,15 @@ kyber768,m4fspeed,75.4,74.4,69.2,,,,,, kyber768,m4fstack,75.3,73.8,68.7,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, -aimer-l1-param1,ref,72.0,47.2,46.7,,,,,, -aimer-l1-param2,ref,72.0,48.7,48.7,,,,,, -aimer-l3-param1,ref,77.4,41.7,41.6,,,,,, +aimer128f,mem_opt,50.6,66.1,49.6,,,,,, +aimer128f,ref,50.6,48.8,49.6,,,,,, +aimer128s,mem_opt,50.6,67.9,50.2,,,,,, +aimer192f,mem_opt,53.5,56.4,40.5,,,,,, +aimer192f,ref,53.5,39.8,40.5,,,,,, +aimer192s,mem_opt,53.5,58.1,40.9,,,,,, +aimer256f,mem_opt,58.9,40.6,27.0,,,,,, +aimer256f,ref,58.9,28.0,27.0,,,,,, +aimer256s,mem_opt,58.9,42.4,27.2,,,,,, ascon-sign-128f-robust,ref,0.0,0.0,0.0,,,,,, ascon-sign-128f-simple,ref,0.0,0.0,0.0,,,,,, ascon-sign-128s-robust,ref,0.0,0.0,0.0,,,,,, @@ -482,9 +500,15 @@ kyber768,m4fspeed,15964,0,0,15964,,,,, kyber768,m4fstack,13288,0,0,13288,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, -aimer-l1-param1,ref,19302,468,0,19770,,,,, -aimer-l1-param2,ref,19894,468,0,20362,,,,, -aimer-l3-param1,ref,23398,468,0,23866,,,,, +aimer128f,mem_opt,17476,0,0,17476,,,,, +aimer128f,ref,17076,0,0,17076,,,,, +aimer128s,mem_opt,17452,0,0,17452,,,,, +aimer192f,mem_opt,25384,0,0,25384,,,,, +aimer192f,ref,24956,0,0,24956,,,,, +aimer192s,mem_opt,25288,0,0,25288,,,,, +aimer256f,mem_opt,27804,0,0,27804,,,,, +aimer256f,ref,27304,0,0,27304,,,,, +aimer256s,mem_opt,27636,0,0,27636,,,,, ascon-sign-128f-robust,ref,17664,0,0,17664,,,,, ascon-sign-128f-simple,ref,17596,0,0,17596,,,,, ascon-sign-128s-robust,ref,17972,0,0,17972,,,,, diff --git a/benchmarks.md b/benchmarks.md index 87df4aa4..dfc2106f 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -21,9 +21,15 @@ ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | -| aimer-l1-param1 (10 executions) | ref | AVG: 392,943
MIN: 392,938
MAX: 392,977 | AVG: 32,386,301
MIN: 32,386,203
MAX: 32,386,424 | AVG: 31,111,672
MIN: 31,111,588
MAX: 31,111,782 | -| aimer-l1-param2 (10 executions) | ref | AVG: 392,938
MIN: 392,938
MAX: 392,941 | AVG: 79,450,721
MIN: 79,450,349
MAX: 79,451,595 | AVG: 78,429,263
MIN: 78,398,061
MAX: 78,434,987 | -| aimer-l3-param1 (10 executions) | ref | AVG: 981,288
MIN: 981,288
MAX: 981,290 | AVG: 90,953,716
MIN: 90,953,603
MAX: 90,953,763 | AVG: 88,350,755
MIN: 88,350,600
MAX: 88,350,906 | +| aimer128f (10 executions) | mem_opt | AVG: 564,325
MIN: 564,324
MAX: 564,326 | AVG: 46,875,341
MIN: 46,874,593
MAX: 46,876,276 | AVG: 26,989,249
MIN: 26,988,505
MAX: 26,989,828 | +| aimer128f (10 executions) | ref | AVG: 564,323
MIN: 564,323
MAX: 564,324 | AVG: 28,991,142
MIN: 28,991,115
MAX: 28,991,171 | AVG: 26,994,617
MIN: 26,994,234
MAX: 26,994,927 | +| aimer128s (10 executions) | mem_opt | AVG: 564,323
MIN: 564,323
MAX: 564,325 | AVG: 374,834,586
MIN: 374,834,473
MAX: 374,834,973 | AVG: 227,230,761
MIN: 227,230,441
MAX: 227,230,833 | +| aimer192f (10 executions) | mem_opt | AVG: 1,397,043
MIN: 1,397,043
MAX: 1,397,043 | AVG: 117,993,511
MIN: 117,991,579
MAX: 117,995,094 | AVG: 76,372,135
MIN: 76,370,763
MAX: 76,373,839 | +| aimer192f (10 executions) | ref | AVG: 1,397,040
MIN: 1,397,040
MAX: 1,397,041 | AVG: 81,884,026
MIN: 81,883,991
MAX: 81,884,035 | AVG: 76,458,825
MIN: 76,456,517
MAX: 76,460,984 | +| aimer192s (10 executions) | mem_opt | AVG: 1,397,047
MIN: 1,397,039
MAX: 1,397,079 | AVG: 916,637,185
MIN: 916,637,133
MAX: 916,637,425 | AVG: 629,249,382
MIN: 629,249,345
MAX: 629,249,415 | +| aimer256f (10 executions) | mem_opt | AVG: 3,344,254
MIN: 3,344,250
MAX: 3,344,255 | AVG: 233,973,308
MIN: 233,969,892
MAX: 233,976,707 | AVG: 170,620,601
MIN: 170,617,448
MAX: 170,623,743 | +| aimer256f (10 executions) | ref | AVG: 3,344,258
MIN: 3,344,255
MAX: 3,344,292 | AVG: 164,484,408
MIN: 164,483,962
MAX: 164,484,481 | AVG: 170,648,722
MIN: 170,647,189
MAX: 170,651,027 | +| aimer256s (10 executions) | mem_opt | AVG: 3,344,262
MIN: 3,344,252
MAX: 3,344,293 | AVG: 1,752,719,642
MIN: 1,752,719,422
MAX: 1,752,720,844 | AVG: 1,361,337,862
MIN: 1,361,336,718
MAX: 1,361,338,013 | | ascon-sign-128f-robust (10 executions) | ref | AVG: 122,506,162
MIN: 122,506,099
MAX: 122,506,254 | AVG: 2,855,797,836
MIN: 2,855,797,243
MAX: 2,855,798,602 | AVG: 174,707,763
MIN: 169,973,472
MAX: 179,525,137 | | ascon-sign-128f-simple (10 executions) | ref | AVG: 69,376,878
MIN: 69,376,875
MAX: 69,376,883 | AVG: 1,629,111,557
MIN: 1,629,111,334
MAX: 1,629,112,028 | AVG: 97,798,317
MIN: 95,509,050
MAX: 98,714,007 | | ascon-sign-128s-robust (10 executions) | ref | AVG: 7,842,366,557
MIN: 7,842,366,432
MAX: 7,842,366,620 | AVG: 59,267,552,580
MIN: 59,267,543,517
MAX: 59,267,565,672 | AVG: 60,232,378
MIN: 57,865,239
MAX: 62,848,708 | @@ -177,9 +183,15 @@ ## Signature Schemes | Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | | ------ | -------------- | ---------------------- | ------------ | -------------- | -| aimer-l1-param1 | ref | 10,952 | 187,724 | 196,728 | -| aimer-l1-param2 | ref | 10,952 | 442,668 | 451,672 | -| aimer-l3-param1 | ref | 23,864 | 413,940 | 435,640 | +| aimer128f | mem_opt | 8,728 | 13,864 | 15,440 | +| aimer128f | ref | 8,728 | 123,376 | 15,448 | +| aimer128s | mem_opt | 8,728 | 27,324 | 34,624 | +| aimer192f | mem_opt | 19,192 | 29,976 | 31,608 | +| aimer192f | ref | 19,192 | 273,104 | 31,608 | +| aimer192s | mem_opt | 19,192 | 43,220 | 60,384 | +| aimer256f | mem_opt | 50,040 | 77,164 | 78,568 | +| aimer256f | ref | 50,040 | 573,284 | 78,716 | +| aimer256s | mem_opt | 50,040 | 76,140 | 117,044 | | ascon-sign-128f-robust | ref | 3,260 | 2,772 | 2,992 | | ascon-sign-128f-simple | ref | 2,632 | 2,144 | 2,448 | | ascon-sign-128s-robust | ref | 3,452 | 2,916 | 2,240 | @@ -334,9 +346,15 @@ ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | -| aimer-l1-param1 | ref | 72.0% | 47.2% | 46.7% | -| aimer-l1-param2 | ref | 72.0% | 48.7% | 48.7% | -| aimer-l3-param1 | ref | 77.4% | 41.7% | 41.6% | +| aimer128f | mem_opt | 50.6% | 66.1% | 49.6% | +| aimer128f | ref | 50.6% | 48.8% | 49.6% | +| aimer128s | mem_opt | 50.6% | 67.9% | 50.2% | +| aimer192f | mem_opt | 53.5% | 56.4% | 40.5% | +| aimer192f | ref | 53.5% | 39.8% | 40.5% | +| aimer192s | mem_opt | 53.5% | 58.1% | 40.9% | +| aimer256f | mem_opt | 58.9% | 40.6% | 27.0% | +| aimer256f | ref | 58.9% | 28.0% | 27.0% | +| aimer256s | mem_opt | 58.9% | 42.4% | 27.2% | | ascon-sign-128f-robust | ref | 0.0% | 0.0% | 0.0% | | ascon-sign-128f-simple | ref | 0.0% | 0.0% | 0.0% | | ascon-sign-128s-robust | ref | 0.0% | 0.0% | 0.0% | @@ -490,9 +508,15 @@ ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | -| aimer-l1-param1 | ref | 19,302 | 468 | 0 | 19,770 | -| aimer-l1-param2 | ref | 19,894 | 468 | 0 | 20,362 | -| aimer-l3-param1 | ref | 23,398 | 468 | 0 | 23,866 | +| aimer128f | mem_opt | 17,476 | 0 | 0 | 17,476 | +| aimer128f | ref | 17,076 | 0 | 0 | 17,076 | +| aimer128s | mem_opt | 17,452 | 0 | 0 | 17,452 | +| aimer192f | mem_opt | 25,384 | 0 | 0 | 25,384 | +| aimer192f | ref | 24,956 | 0 | 0 | 24,956 | +| aimer192s | mem_opt | 25,288 | 0 | 0 | 25,288 | +| aimer256f | mem_opt | 27,804 | 0 | 0 | 27,804 | +| aimer256f | ref | 27,304 | 0 | 0 | 27,304 | +| aimer256s | mem_opt | 27,636 | 0 | 0 | 27,636 | | ascon-sign-128f-robust | ref | 17,664 | 0 | 0 | 17,664 | | ascon-sign-128f-simple | ref | 17,596 | 0 | 0 | 17,596 | | ascon-sign-128s-robust | ref | 17,972 | 0 | 0 | 17,972 | diff --git a/mupq b/mupq index d5d4ed32..817a9de4 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit d5d4ed32d3016346c2c882f0ca3c951936364205 +Subproject commit 817a9de4bbcc87bf5fb57ca85eecf0d566e0c414 diff --git a/skiplist.py b/skiplist.py index 4f6a868b..f483bfb7 100644 --- a/skiplist.py +++ b/skiplist.py @@ -1,11 +1,16 @@ skip_list = [ - {'scheme': 'aimer-l1-param1', 'implementation': 'ref', 'estmemory': 206848}, - {'scheme': 'aimer-l1-param2', 'implementation': 'ref', 'estmemory': 461824}, - {'scheme': 'aimer-l1-param3', 'implementation': 'ref', 'estmemory': 1442816}, - {'scheme': 'aimer-l3-param1', 'implementation': 'ref', 'estmemory': 452608}, - {'scheme': 'aimer-l3-param2', 'implementation': 'ref', 'estmemory': 1091584}, - {'scheme': 'aimer-l5-param1', 'implementation': 'ref', 'estmemory': 926720}, - {'scheme': 'aimer-l5-param2', 'implementation': 'ref', 'estmemory': 2169856}, + {'scheme': 'aimer192s', 'implementation': 'opt_mem', 'estmemory': 70656}, + {'scheme': 'aimer192s', 'implementation': 'ref', 'estmemory': 2036736}, + {'scheme': 'aimer192f', 'implementation': 'opt_mem', 'estmemory': 46080}, + {'scheme': 'aimer192f', 'implementation': 'ref', 'estmemory': 287744}, + {'scheme': 'aimer128s', 'implementation': 'opt_mem', 'estmemory': 39936}, + {'scheme': 'aimer128s', 'implementation': 'ref', 'estmemory': 924672}, + {'scheme': 'aimer256f', 'implementation': 'opt_mem', 'estmemory': 105472}, + {'scheme': 'aimer256f', 'implementation': 'ref', 'estmemory': 600064}, + {'scheme': 'aimer256s', 'implementation': 'opt_mem', 'estmemory': 135168}, + {'scheme': 'aimer256s', 'implementation': 'ref', 'estmemory': 4148224}, + {'scheme': 'aimer128f', 'implementation': 'opt_mem', 'estmemory': 22528}, + {'scheme': 'aimer128f', 'implementation': 'ref', 'estmemory': 131072}, {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, From 8d44b724396ddbc0db55d5de93bec252cedb9c04 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 13 Aug 2024 08:06:44 +0800 Subject: [PATCH 096/107] init msg buffer in {speed,hashing}.c (#351) --- mupq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mupq b/mupq index 817a9de4..c15e900c 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 817a9de4bbcc87bf5fb57ca85eecf0d566e0c414 +Subproject commit c15e900c693afd6ca7165405bc5650efdbcce02d From 79a0ddf3399067eb2de3b14d92331411b195bf10 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 14 Oct 2024 18:16:32 +0800 Subject: [PATCH 097/107] Update Kyber to final FIPS203 and rename to ML-KEM (#362) --- README.md | 20 +- benchmarks.csv | 72 ++-- benchmarks.md | 72 ++-- crypto_kem/kyber1024/m4fspeed/cbd.c | 1 - crypto_kem/kyber1024/m4fspeed/cbd.h | 1 - crypto_kem/kyber1024/m4fspeed/cmov_int16.S | 1 - crypto_kem/kyber1024/m4fspeed/fastaddsub.S | 1 - crypto_kem/kyber1024/m4fspeed/fastbasemul.S | 1 - crypto_kem/kyber1024/m4fspeed/fastinvntt.S | 1 - crypto_kem/kyber1024/m4fspeed/fastntt.S | 1 - crypto_kem/kyber1024/m4fspeed/indcpa.c | 1 - crypto_kem/kyber1024/m4fspeed/indcpa.h | 1 - crypto_kem/kyber1024/m4fspeed/kem.c | 1 - crypto_kem/kyber1024/m4fspeed/macros.i | 1 - crypto_kem/kyber1024/m4fspeed/matacc.c | 1 - crypto_kem/kyber1024/m4fspeed/matacc.h | 1 - crypto_kem/kyber1024/m4fspeed/matacc.i | 1 - crypto_kem/kyber1024/m4fspeed/matacc_asm.S | 1 - crypto_kem/kyber1024/m4fspeed/ntt.c | 1 - crypto_kem/kyber1024/m4fspeed/ntt.h | 1 - crypto_kem/kyber1024/m4fspeed/poly.c | 1 - crypto_kem/kyber1024/m4fspeed/poly.h | 1 - crypto_kem/kyber1024/m4fspeed/poly_asm.S | 1 - crypto_kem/kyber1024/m4fspeed/polyvec.c | 1 - crypto_kem/kyber1024/m4fspeed/polyvec.h | 1 - crypto_kem/kyber1024/m4fspeed/reduce.S | 1 - .../kyber1024/m4fspeed/symmetric-fips202.c | 1 - crypto_kem/kyber1024/m4fspeed/symmetric.h | 1 - crypto_kem/kyber1024/m4fspeed/verify.c | 1 - crypto_kem/kyber1024/m4fspeed/verify.h | 1 - crypto_kem/kyber1024/m4fstack/cmov_int16.S | 1 - crypto_kem/kyber1024/m4fstack/fastbasemul.S | 1 - crypto_kem/kyber1024/m4fstack/fastinvntt.S | 1 - crypto_kem/kyber1024/m4fstack/fastntt.S | 1 - crypto_kem/kyber1024/m4fstack/indcpa.c | 1 - crypto_kem/kyber1024/m4fstack/indcpa.h | 1 - crypto_kem/kyber1024/m4fstack/matacc.c | 1 - crypto_kem/kyber1024/m4fstack/matacc.h | 1 - crypto_kem/kyber1024/m4fstack/matacc.i | 1 - crypto_kem/kyber1024/m4fstack/matacc_asm.S | 1 - crypto_kem/kyber1024/m4fstack/poly.c | 1 - crypto_kem/kyber1024/m4fstack/poly.h | 1 - crypto_kem/kyber1024/m4fstack/poly_asm.S | 1 - crypto_kem/kyber512/m4fspeed/cmov_int16.S | 1 - crypto_kem/kyber512/m4fspeed/fastaddsub.S | 1 - crypto_kem/kyber512/m4fspeed/fastbasemul.S | 1 - crypto_kem/kyber512/m4fspeed/fastinvntt.S | 1 - crypto_kem/kyber512/m4fspeed/fastntt.S | 1 - crypto_kem/kyber512/m4fspeed/indcpa.h | 1 - crypto_kem/kyber512/m4fspeed/kem.c | 1 - crypto_kem/kyber512/m4fspeed/macros.i | 1 - crypto_kem/kyber512/m4fspeed/matacc.c | 1 - crypto_kem/kyber512/m4fspeed/matacc.h | 1 - crypto_kem/kyber512/m4fspeed/matacc.i | 1 - crypto_kem/kyber512/m4fspeed/matacc_asm.S | 1 - crypto_kem/kyber512/m4fspeed/ntt.c | 1 - crypto_kem/kyber512/m4fspeed/ntt.h | 1 - crypto_kem/kyber512/m4fspeed/poly_asm.S | 1 - crypto_kem/kyber512/m4fspeed/polyvec.c | 1 - crypto_kem/kyber512/m4fspeed/polyvec.h | 1 - crypto_kem/kyber512/m4fspeed/reduce.S | 1 - .../kyber512/m4fspeed/symmetric-fips202.c | 1 - crypto_kem/kyber512/m4fspeed/symmetric.h | 1 - crypto_kem/kyber512/m4fspeed/verify.c | 1 - crypto_kem/kyber512/m4fspeed/verify.h | 1 - crypto_kem/kyber512/m4fstack/cmov_int16.S | 1 - crypto_kem/kyber512/m4fstack/fastbasemul.S | 1 - crypto_kem/kyber512/m4fstack/fastinvntt.S | 356 ------------------ crypto_kem/kyber512/m4fstack/matacc.c | 1 - crypto_kem/kyber512/m4fstack/matacc.h | 1 - crypto_kem/kyber512/m4fstack/matacc.i | 1 - crypto_kem/kyber512/m4fstack/matacc_asm.S | 1 - crypto_kem/kyber512/m4fstack/poly_asm.S | 1 - .../kyber768/m4fstack/symmetric-fips202.c | 1 - .../{kyber1024 => ml-kem-1024}/m4fspeed/api.h | 0 crypto_kem/ml-kem-1024/m4fspeed/cbd.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/cbd.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/cmov_int16.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/fastaddsub.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/fastbasemul.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/fastinvntt.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/fastntt.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/indcpa.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/indcpa.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/kem.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/macros.i | 1 + crypto_kem/ml-kem-1024/m4fspeed/matacc.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/matacc.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/matacc.i | 1 + crypto_kem/ml-kem-1024/m4fspeed/matacc_asm.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/ntt.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/ntt.h | 1 + .../m4fspeed/params.h | 0 crypto_kem/ml-kem-1024/m4fspeed/poly.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/poly.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/poly_asm.S | 1 + crypto_kem/ml-kem-1024/m4fspeed/polyvec.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/polyvec.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/reduce.S | 1 + .../ml-kem-1024/m4fspeed/symmetric-fips202.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/symmetric.h | 1 + crypto_kem/ml-kem-1024/m4fspeed/verify.c | 1 + crypto_kem/ml-kem-1024/m4fspeed/verify.h | 1 + .../{kyber1024 => ml-kem-1024}/m4fstack/api.h | 0 .../{kyber1024 => ml-kem-1024}/m4fstack/cbd.c | 0 .../{kyber1024 => ml-kem-1024}/m4fstack/cbd.h | 0 crypto_kem/ml-kem-1024/m4fstack/cmov_int16.S | 1 + .../m4fstack/fastaddsub.S | 0 crypto_kem/ml-kem-1024/m4fstack/fastbasemul.S | 1 + crypto_kem/ml-kem-1024/m4fstack/fastinvntt.S | 1 + crypto_kem/ml-kem-1024/m4fstack/fastntt.S | 1 + crypto_kem/ml-kem-1024/m4fstack/indcpa.c | 1 + crypto_kem/ml-kem-1024/m4fstack/indcpa.h | 1 + .../{kyber1024 => ml-kem-1024}/m4fstack/kem.c | 0 .../m4fstack/macros.i | 0 crypto_kem/ml-kem-1024/m4fstack/matacc.c | 1 + crypto_kem/ml-kem-1024/m4fstack/matacc.h | 1 + crypto_kem/ml-kem-1024/m4fstack/matacc.i | 1 + crypto_kem/ml-kem-1024/m4fstack/matacc_asm.S | 1 + .../{kyber1024 => ml-kem-1024}/m4fstack/ntt.c | 0 .../{kyber1024 => ml-kem-1024}/m4fstack/ntt.h | 0 .../m4fstack/params.h | 0 crypto_kem/ml-kem-1024/m4fstack/poly.c | 1 + crypto_kem/ml-kem-1024/m4fstack/poly.h | 1 + crypto_kem/ml-kem-1024/m4fstack/poly_asm.S | 1 + .../m4fstack/polyvec.c | 0 .../m4fstack/polyvec.h | 0 .../m4fstack/reduce.S | 0 .../ml-kem-1024/m4fstack/symmetric-fips202.c | 1 + .../m4fstack/symmetric.h | 0 .../m4fstack/verify.c | 0 .../m4fstack/verify.h | 0 .../{kyber512 => ml-kem-512}/m4fspeed/api.h | 0 .../{kyber512 => ml-kem-512}/m4fspeed/cbd.c | 0 .../{kyber512 => ml-kem-512}/m4fspeed/cbd.h | 0 crypto_kem/ml-kem-512/m4fspeed/cmov_int16.S | 1 + crypto_kem/ml-kem-512/m4fspeed/fastaddsub.S | 1 + crypto_kem/ml-kem-512/m4fspeed/fastbasemul.S | 1 + crypto_kem/ml-kem-512/m4fspeed/fastinvntt.S | 1 + crypto_kem/ml-kem-512/m4fspeed/fastntt.S | 1 + .../m4fspeed/indcpa.c | 4 +- crypto_kem/ml-kem-512/m4fspeed/indcpa.h | 1 + crypto_kem/ml-kem-512/m4fspeed/kem.c | 1 + crypto_kem/ml-kem-512/m4fspeed/macros.i | 1 + crypto_kem/ml-kem-512/m4fspeed/matacc.c | 1 + crypto_kem/ml-kem-512/m4fspeed/matacc.h | 1 + crypto_kem/ml-kem-512/m4fspeed/matacc.i | 1 + crypto_kem/ml-kem-512/m4fspeed/matacc_asm.S | 1 + crypto_kem/ml-kem-512/m4fspeed/ntt.c | 1 + crypto_kem/ml-kem-512/m4fspeed/ntt.h | 1 + .../m4fspeed/params.h | 0 .../{kyber512 => ml-kem-512}/m4fspeed/poly.c | 0 .../{kyber512 => ml-kem-512}/m4fspeed/poly.h | 0 crypto_kem/ml-kem-512/m4fspeed/poly_asm.S | 1 + crypto_kem/ml-kem-512/m4fspeed/polyvec.c | 1 + crypto_kem/ml-kem-512/m4fspeed/polyvec.h | 1 + crypto_kem/ml-kem-512/m4fspeed/reduce.S | 1 + .../ml-kem-512/m4fspeed/symmetric-fips202. | 1 + .../ml-kem-512/m4fspeed/symmetric-fips202.c | 1 + crypto_kem/ml-kem-512/m4fspeed/symmetric.h | 1 + crypto_kem/ml-kem-512/m4fspeed/verify.c | 1 + crypto_kem/ml-kem-512/m4fspeed/verify.h | 1 + .../{kyber512 => ml-kem-512}/m4fstack/api.h | 0 .../{kyber512 => ml-kem-512}/m4fstack/cbd.c | 0 .../{kyber512 => ml-kem-512}/m4fstack/cbd.h | 0 crypto_kem/ml-kem-512/m4fstack/cmov_int16.S | 1 + .../m4fstack/fastaddsub.S | 0 crypto_kem/ml-kem-512/m4fstack/fastbasemul.S | 1 + crypto_kem/ml-kem-512/m4fstack/fastinvntt.S | 1 + .../m4fstack/fastntt.S | 0 .../m4fstack/indcpa.c | 4 +- .../m4fstack/indcpa.h | 0 .../{kyber512 => ml-kem-512}/m4fstack/kem.c | 0 .../m4fstack/macros.i | 0 crypto_kem/ml-kem-512/m4fstack/matacc.c | 1 + crypto_kem/ml-kem-512/m4fstack/matacc.h | 1 + crypto_kem/ml-kem-512/m4fstack/matacc.i | 1 + crypto_kem/ml-kem-512/m4fstack/matacc_asm.S | 1 + .../{kyber512 => ml-kem-512}/m4fstack/ntt.c | 0 .../{kyber512 => ml-kem-512}/m4fstack/ntt.h | 0 .../m4fstack/params.h | 0 .../{kyber512 => ml-kem-512}/m4fstack/poly.c | 0 .../{kyber512 => ml-kem-512}/m4fstack/poly.h | 0 crypto_kem/ml-kem-512/m4fstack/poly_asm.S | 1 + .../m4fstack/polyvec.c | 0 .../m4fstack/polyvec.h | 0 .../m4fstack/reduce.S | 0 .../m4fstack/symmetric-fips202.c | 0 .../m4fstack/symmetric.h | 0 .../m4fstack/verify.c | 0 .../m4fstack/verify.h | 0 .../{kyber768 => ml-kem-768}/m4fspeed/api.h | 0 .../{kyber768 => ml-kem-768}/m4fspeed/cbd.c | 0 .../{kyber768 => ml-kem-768}/m4fspeed/cbd.h | 0 .../m4fspeed/cmov_int16.S | 0 .../m4fspeed/fastaddsub.S | 0 .../m4fspeed/fastbasemul.S | 0 .../m4fspeed/fastinvntt.S | 0 .../m4fspeed/fastntt.S | 0 .../m4fspeed/indcpa.c | 4 +- .../m4fspeed/indcpa.h | 0 .../{kyber768 => ml-kem-768}/m4fspeed/kem.c | 0 .../m4fspeed/macros.i | 0 .../m4fspeed/matacc.c | 0 .../m4fspeed/matacc.h | 0 .../m4fspeed/matacc.i | 0 .../m4fspeed/matacc_asm.S | 0 .../{kyber768 => ml-kem-768}/m4fspeed/ntt.c | 0 .../{kyber768 => ml-kem-768}/m4fspeed/ntt.h | 0 .../m4fspeed/params.h | 0 .../{kyber768 => ml-kem-768}/m4fspeed/poly.c | 0 .../{kyber768 => ml-kem-768}/m4fspeed/poly.h | 0 .../m4fspeed/poly_asm.S | 0 .../m4fspeed/polyvec.c | 0 .../m4fspeed/polyvec.h | 0 .../m4fspeed/reduce.S | 0 .../m4fspeed/symmetric-fips202.c | 0 .../m4fspeed/symmetric.h | 0 .../m4fspeed/verify.c | 0 .../m4fspeed/verify.h | 0 .../{kyber768 => ml-kem-768}/m4fstack/api.h | 0 .../{kyber768 => ml-kem-768}/m4fstack/cbd.c | 0 .../{kyber768 => ml-kem-768}/m4fstack/cbd.h | 0 .../m4fstack/cmov_int16.S | 0 .../m4fstack/fastaddsub.S | 0 .../m4fstack/fastbasemul.S | 0 .../m4fstack/fastinvntt.S | 0 .../m4fstack/fastntt.S | 0 .../m4fstack/indcpa.c | 4 +- .../m4fstack/indcpa.h | 0 .../{kyber768 => ml-kem-768}/m4fstack/kem.c | 0 .../m4fstack/macros.i | 0 .../m4fstack/matacc.c | 0 .../m4fstack/matacc.h | 0 .../m4fstack/matacc.i | 0 .../m4fstack/matacc_asm.S | 0 .../{kyber768 => ml-kem-768}/m4fstack/ntt.c | 0 .../{kyber768 => ml-kem-768}/m4fstack/ntt.h | 0 .../m4fstack/params.h | 0 .../{kyber768 => ml-kem-768}/m4fstack/poly.c | 0 .../{kyber768 => ml-kem-768}/m4fstack/poly.h | 0 .../m4fstack/poly_asm.S | 0 .../m4fstack/polyvec.c | 0 .../m4fstack/polyvec.h | 0 .../m4fstack/reduce.S | 0 .../m4fstack/symmetric-fips202.c | 0 .../m4fstack/symmetric.h | 0 .../m4fstack/verify.c | 0 .../m4fstack/verify.h | 0 mupq | 2 +- skiplist.py | 18 +- 251 files changed, 176 insertions(+), 522 deletions(-) delete mode 120000 crypto_kem/kyber1024/m4fspeed/cbd.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/cbd.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/cmov_int16.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/fastaddsub.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/fastbasemul.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/fastinvntt.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/fastntt.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/indcpa.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/indcpa.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/kem.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/macros.i delete mode 120000 crypto_kem/kyber1024/m4fspeed/matacc.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/matacc.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/matacc.i delete mode 120000 crypto_kem/kyber1024/m4fspeed/matacc_asm.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/ntt.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/ntt.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/poly.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/poly.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/poly_asm.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/polyvec.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/polyvec.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/reduce.S delete mode 120000 crypto_kem/kyber1024/m4fspeed/symmetric-fips202.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/symmetric.h delete mode 120000 crypto_kem/kyber1024/m4fspeed/verify.c delete mode 120000 crypto_kem/kyber1024/m4fspeed/verify.h delete mode 120000 crypto_kem/kyber1024/m4fstack/cmov_int16.S delete mode 120000 crypto_kem/kyber1024/m4fstack/fastbasemul.S delete mode 120000 crypto_kem/kyber1024/m4fstack/fastinvntt.S delete mode 120000 crypto_kem/kyber1024/m4fstack/fastntt.S delete mode 120000 crypto_kem/kyber1024/m4fstack/indcpa.c delete mode 120000 crypto_kem/kyber1024/m4fstack/indcpa.h delete mode 120000 crypto_kem/kyber1024/m4fstack/matacc.c delete mode 120000 crypto_kem/kyber1024/m4fstack/matacc.h delete mode 120000 crypto_kem/kyber1024/m4fstack/matacc.i delete mode 120000 crypto_kem/kyber1024/m4fstack/matacc_asm.S delete mode 120000 crypto_kem/kyber1024/m4fstack/poly.c delete mode 120000 crypto_kem/kyber1024/m4fstack/poly.h delete mode 120000 crypto_kem/kyber1024/m4fstack/poly_asm.S delete mode 120000 crypto_kem/kyber512/m4fspeed/cmov_int16.S delete mode 120000 crypto_kem/kyber512/m4fspeed/fastaddsub.S delete mode 120000 crypto_kem/kyber512/m4fspeed/fastbasemul.S delete mode 120000 crypto_kem/kyber512/m4fspeed/fastinvntt.S delete mode 120000 crypto_kem/kyber512/m4fspeed/fastntt.S delete mode 120000 crypto_kem/kyber512/m4fspeed/indcpa.h delete mode 120000 crypto_kem/kyber512/m4fspeed/kem.c delete mode 120000 crypto_kem/kyber512/m4fspeed/macros.i delete mode 120000 crypto_kem/kyber512/m4fspeed/matacc.c delete mode 120000 crypto_kem/kyber512/m4fspeed/matacc.h delete mode 120000 crypto_kem/kyber512/m4fspeed/matacc.i delete mode 120000 crypto_kem/kyber512/m4fspeed/matacc_asm.S delete mode 120000 crypto_kem/kyber512/m4fspeed/ntt.c delete mode 120000 crypto_kem/kyber512/m4fspeed/ntt.h delete mode 120000 crypto_kem/kyber512/m4fspeed/poly_asm.S delete mode 120000 crypto_kem/kyber512/m4fspeed/polyvec.c delete mode 120000 crypto_kem/kyber512/m4fspeed/polyvec.h delete mode 120000 crypto_kem/kyber512/m4fspeed/reduce.S delete mode 120000 crypto_kem/kyber512/m4fspeed/symmetric-fips202.c delete mode 120000 crypto_kem/kyber512/m4fspeed/symmetric.h delete mode 120000 crypto_kem/kyber512/m4fspeed/verify.c delete mode 120000 crypto_kem/kyber512/m4fspeed/verify.h delete mode 120000 crypto_kem/kyber512/m4fstack/cmov_int16.S delete mode 120000 crypto_kem/kyber512/m4fstack/fastbasemul.S delete mode 100644 crypto_kem/kyber512/m4fstack/fastinvntt.S delete mode 120000 crypto_kem/kyber512/m4fstack/matacc.c delete mode 120000 crypto_kem/kyber512/m4fstack/matacc.h delete mode 120000 crypto_kem/kyber512/m4fstack/matacc.i delete mode 120000 crypto_kem/kyber512/m4fstack/matacc_asm.S delete mode 120000 crypto_kem/kyber512/m4fstack/poly_asm.S delete mode 120000 crypto_kem/kyber768/m4fstack/symmetric-fips202.c rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fspeed/api.h (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/cbd.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/cbd.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/cmov_int16.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/fastaddsub.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/fastbasemul.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/fastinvntt.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/fastntt.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/indcpa.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/indcpa.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/kem.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/macros.i create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/matacc.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/matacc.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/matacc.i create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/matacc_asm.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/ntt.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/ntt.h rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fspeed/params.h (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/poly.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/poly.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/poly_asm.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/polyvec.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/polyvec.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/reduce.S create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/symmetric-fips202.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/symmetric.h create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/verify.c create mode 120000 crypto_kem/ml-kem-1024/m4fspeed/verify.h rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/api.h (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/cbd.c (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/cbd.h (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fstack/cmov_int16.S rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/fastaddsub.S (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fstack/fastbasemul.S create mode 120000 crypto_kem/ml-kem-1024/m4fstack/fastinvntt.S create mode 120000 crypto_kem/ml-kem-1024/m4fstack/fastntt.S create mode 120000 crypto_kem/ml-kem-1024/m4fstack/indcpa.c create mode 120000 crypto_kem/ml-kem-1024/m4fstack/indcpa.h rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/kem.c (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/macros.i (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fstack/matacc.c create mode 120000 crypto_kem/ml-kem-1024/m4fstack/matacc.h create mode 120000 crypto_kem/ml-kem-1024/m4fstack/matacc.i create mode 120000 crypto_kem/ml-kem-1024/m4fstack/matacc_asm.S rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/ntt.c (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/ntt.h (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/params.h (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fstack/poly.c create mode 120000 crypto_kem/ml-kem-1024/m4fstack/poly.h create mode 120000 crypto_kem/ml-kem-1024/m4fstack/poly_asm.S rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/polyvec.c (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/polyvec.h (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/reduce.S (100%) create mode 120000 crypto_kem/ml-kem-1024/m4fstack/symmetric-fips202.c rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/symmetric.h (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/verify.c (100%) rename crypto_kem/{kyber1024 => ml-kem-1024}/m4fstack/verify.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/api.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/cbd.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/cbd.h (100%) create mode 120000 crypto_kem/ml-kem-512/m4fspeed/cmov_int16.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/fastaddsub.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/fastbasemul.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/fastinvntt.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/fastntt.S rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/indcpa.c (98%) create mode 120000 crypto_kem/ml-kem-512/m4fspeed/indcpa.h create mode 120000 crypto_kem/ml-kem-512/m4fspeed/kem.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/macros.i create mode 120000 crypto_kem/ml-kem-512/m4fspeed/matacc.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/matacc.h create mode 120000 crypto_kem/ml-kem-512/m4fspeed/matacc.i create mode 120000 crypto_kem/ml-kem-512/m4fspeed/matacc_asm.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/ntt.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/ntt.h rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/params.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/poly.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fspeed/poly.h (100%) create mode 120000 crypto_kem/ml-kem-512/m4fspeed/poly_asm.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/polyvec.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/polyvec.h create mode 120000 crypto_kem/ml-kem-512/m4fspeed/reduce.S create mode 120000 crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. create mode 120000 crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/symmetric.h create mode 120000 crypto_kem/ml-kem-512/m4fspeed/verify.c create mode 120000 crypto_kem/ml-kem-512/m4fspeed/verify.h rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/api.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/cbd.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/cbd.h (100%) create mode 120000 crypto_kem/ml-kem-512/m4fstack/cmov_int16.S rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/fastaddsub.S (100%) create mode 120000 crypto_kem/ml-kem-512/m4fstack/fastbasemul.S create mode 120000 crypto_kem/ml-kem-512/m4fstack/fastinvntt.S rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/fastntt.S (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/indcpa.c (98%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/indcpa.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/kem.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/macros.i (100%) create mode 120000 crypto_kem/ml-kem-512/m4fstack/matacc.c create mode 120000 crypto_kem/ml-kem-512/m4fstack/matacc.h create mode 120000 crypto_kem/ml-kem-512/m4fstack/matacc.i create mode 120000 crypto_kem/ml-kem-512/m4fstack/matacc_asm.S rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/ntt.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/ntt.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/params.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/poly.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/poly.h (100%) create mode 120000 crypto_kem/ml-kem-512/m4fstack/poly_asm.S rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/polyvec.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/polyvec.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/reduce.S (100%) rename crypto_kem/{kyber1024 => ml-kem-512}/m4fstack/symmetric-fips202.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/symmetric.h (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/verify.c (100%) rename crypto_kem/{kyber512 => ml-kem-512}/m4fstack/verify.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/api.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/cbd.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/cbd.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/cmov_int16.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/fastaddsub.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/fastbasemul.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/fastinvntt.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/fastntt.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/indcpa.c (98%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/indcpa.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/kem.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/macros.i (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/matacc.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/matacc.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/matacc.i (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/matacc_asm.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/ntt.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/ntt.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/params.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/poly.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/poly.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/poly_asm.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/polyvec.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/polyvec.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/reduce.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/symmetric-fips202.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/symmetric.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/verify.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fspeed/verify.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/api.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/cbd.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/cbd.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/cmov_int16.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/fastaddsub.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/fastbasemul.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/fastinvntt.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/fastntt.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/indcpa.c (98%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/indcpa.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/kem.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/macros.i (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/matacc.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/matacc.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/matacc.i (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/matacc_asm.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/ntt.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/ntt.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/params.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/poly.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/poly.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/poly_asm.S (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/polyvec.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/polyvec.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/reduce.S (100%) rename crypto_kem/{kyber512 => ml-kem-768}/m4fstack/symmetric-fips202.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/symmetric.h (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/verify.c (100%) rename crypto_kem/{kyber768 => ml-kem-768}/m4fstack/verify.h (100%) diff --git a/README.md b/README.md index 3fff71bf..2c0ec888 100644 --- a/README.md +++ b/README.md @@ -163,22 +163,22 @@ int crypto_sign_open(unsigned char *m, size_t *mlen, ## Running tests and benchmarks -The build system compiles six binaries for each implemenation which can be used to test and benchmark the schemes. For example, for the reference implementation of [Kyber768](https://pq-crystals.org/kyber/) the following binaries are assembled: - - `bin/crypto_kem_kyber768_m4_test.bin` tests if the scheme works as expected. For KEMs this tests if Alice and Bob derive the same shared key and for signature schemes it tests if a generated signature can be verified correctly. Several failure cases are also checked, see [mupq/crypto_kem/test.c](https://github.com/mupq/mupq/blob/master/crypto_kem/test.c) and [mupq/crypto_sign/test.c](https://github.com/mupq/mupq/blob/master/crypto_sign/test.c) for details. - - `bin/crypto_kem_kyber768_m4_speed.bin` measures the runtime of `crypto_kem_keypair`, `crypto_kem_enc`, and `crypto_kem_dec` for KEMs and `crypto_sign_keypair`, `crypto_sign`, and `crypto_sign_open` for signatures. See [mupq/crypto_kem/speed.c](https://github.com/mupq/mupq/blob/master/crypto_kem/speed.c) and [mupq/crypto_sign/speed.c](https://github.com/mupq/mupq/blob/master/crypto_sign/speed.c). - - `bin/crypto_kem_kyber768_m4_hashing.bin` measures the cycles spent in SHA-2, SHA-3, and AES of `crypto_kem_keypair`, `crypto_kem_enc`, and `crypto_kem_dec` for KEMs and `crypto_sign_keypair`, `crypto_sign`, and `crypto_sign_open` for signatures. See [mupq/crypto_kem/hashing.c](https://github.com/mupq/mupq/blob/master/crypto_kem/speed.c) and [mupq/crypto_sign/speed.c](https://github.com/mupq/mupq/blob/master/crypto_sign/speed.c). - - `bin/crypto_kem_kyber768_m4_stack.bin` measures the stack consumption of each of the procedures involved. The memory allocated outside of the procedures (e.g., public keys, private keys, ciphertexts, signatures) is not included. See [mupq/crypto_kem/stack.c](https://github.com/mupq/mupq/blob/master/crypto_kem/stack.c) and [mupq/crypto_sign/stack.c](https://github.com/mupq/mupq/blob/master/crypto_sign/stack.c). - - `bin/crypto_kem_kyber768_m4_testvectors.bin` uses a deterministic random number generator to generate testvectors for the implementation. These can be used to cross-check different implemenatations of the same scheme. See [mupq/crypto_kem/testvectors.c](https://github.com/mupq/mupq/blob/master/crypto_kem/testvectors.c) and [mupq/crypto_sign/testvectors.c](https://github.com/mupq/mupq/blob/master/crypto_sign/testvectors.c). -- `bin-host/crypto_kem_kyber768_m4_testvectors` uses the same deterministic random number generator to create the testvectors on your host. See [mupq/crypto_kem/testvectors-host.c](https://github.com/mupq/mupq/blob/master/crypto_kem/testvectors-host.c) and [mupq/crypto_sign/testvectors-host.c](https://github.com/mupq/mupq/blob/master/crypto_sign/testvectors-host.c). +The build system compiles six binaries for each implemenation which can be used to test and benchmark the schemes. For example, for the reference implementation of [ML-KEM-768](https://pq-crystals.org/kyber/) the following binaries are assembled: + - `bin/crypto_kem_ml-kem-768_m4_test.bin` tests if the scheme works as expected. For KEMs this tests if Alice and Bob derive the same shared key and for signature schemes it tests if a generated signature can be verified correctly. Several failure cases are also checked, see [mupq/crypto_kem/test.c](https://github.com/mupq/mupq/blob/master/crypto_kem/test.c) and [mupq/crypto_sign/test.c](https://github.com/mupq/mupq/blob/master/crypto_sign/test.c) for details. + - `bin/crypto_kem_ml-kem-768_m4_speed.bin` measures the runtime of `crypto_kem_keypair`, `crypto_kem_enc`, and `crypto_kem_dec` for KEMs and `crypto_sign_keypair`, `crypto_sign`, and `crypto_sign_open` for signatures. See [mupq/crypto_kem/speed.c](https://github.com/mupq/mupq/blob/master/crypto_kem/speed.c) and [mupq/crypto_sign/speed.c](https://github.com/mupq/mupq/blob/master/crypto_sign/speed.c). + - `bin/crypto_kem_ml-kem-768_m4_hashing.bin` measures the cycles spent in SHA-2, SHA-3, and AES of `crypto_kem_keypair`, `crypto_kem_enc`, and `crypto_kem_dec` for KEMs and `crypto_sign_keypair`, `crypto_sign`, and `crypto_sign_open` for signatures. See [mupq/crypto_kem/hashing.c](https://github.com/mupq/mupq/blob/master/crypto_kem/speed.c) and [mupq/crypto_sign/speed.c](https://github.com/mupq/mupq/blob/master/crypto_sign/speed.c). + - `bin/crypto_kem_ml-kem-768_m4_stack.bin` measures the stack consumption of each of the procedures involved. The memory allocated outside of the procedures (e.g., public keys, private keys, ciphertexts, signatures) is not included. See [mupq/crypto_kem/stack.c](https://github.com/mupq/mupq/blob/master/crypto_kem/stack.c) and [mupq/crypto_sign/stack.c](https://github.com/mupq/mupq/blob/master/crypto_sign/stack.c). + - `bin/crypto_kem_ml-kem-768_m4_testvectors.bin` uses a deterministic random number generator to generate testvectors for the implementation. These can be used to cross-check different implemenatations of the same scheme. See [mupq/crypto_kem/testvectors.c](https://github.com/mupq/mupq/blob/master/crypto_kem/testvectors.c) and [mupq/crypto_sign/testvectors.c](https://github.com/mupq/mupq/blob/master/crypto_sign/testvectors.c). +- `bin-host/crypto_kem_ml-kem-768_m4_testvectors` uses the same deterministic random number generator to create the testvectors on your host. See [mupq/crypto_kem/testvectors-host.c](https://github.com/mupq/mupq/blob/master/crypto_kem/testvectors-host.c) and [mupq/crypto_sign/testvectors-host.c](https://github.com/mupq/mupq/blob/master/crypto_sign/testvectors-host.c). - An `elf` file for each binary is generated in the `elf/` folder if desired. The `elf` files or binaries can be flashed to your board using an appropriate -tool. For example, the `stm32f4discovery` platform uses `st-flash`, e.g., `st-flash write bin/crypto_kem_kyber768_m4_test.bin 0x8000000`. To receive the output, run `python3 hostside/host_unidirectional.py`. +tool. For example, the `stm32f4discovery` platform uses `st-flash`, e.g., `st-flash write bin/crypto_kem_ml-kem-768_m4_test.bin 0x8000000`. To receive the output, run `python3 hostside/host_unidirectional.py`. If you target the `mps2-an386` platform, you can also run the `elf` file using the QEMU ARM emulator: ``` -qemu-system-arm -M mps2-an386 -nographic -semihosting -kernel elf/crypto_kem_kyber512_m4_test.elf +qemu-system-arm -M mps2-an386 -nographic -semihosting -kernel elf/crypto_kem_ml-kem-512_m4_test.elf ``` The emulator should exit automatically when the test / benchmark completes. If you run into an error, you can exit QEMU pressing CTRL+A and then X. @@ -197,7 +197,7 @@ The scripts take a number of command line arguments, which you'll need to adapt: If you change any of these values, you'll need to run `make clean` (the build system will remind you). -In case you don't want to include all schemes, pass a list of schemes you want to include to any of the scripts, e.g., `python3 test.py kyber768 sphincs-shake256-128f-simple`. +In case you don't want to include all schemes, pass a list of schemes you want to include to any of the scripts, e.g., `python3 test.py ml-kem-768 sphincs-shake256-128f-simple`. In case you want to exclude certain schemes pass `--exclude`, e.g., `python3 test.py --exclude saber`. The benchmark results (in `benchmarks/`) created by diff --git a/benchmarks.csv b/benchmarks.csv index 28be1159..0fda9e5b 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -8,15 +8,15 @@ bikel3 (10 executions),opt,248083316,248083286,248083345,16405238,16405236,16405 hqc-128 (10 executions),clean,52705201,52705180,52705224,105650897,105650877,105650927,159569179,159569176,159569183 hqc-192 (10 executions),clean,161458617,161458590,161458638,323146261,323146250,323146292,486156251,486156214,486156266 hqc-256 (10 executions),clean,295934078,295934057,295934104,591853870,591853850,591853898,891163005,891162988,891163038 -kyber1024 (10 executions),clean,1540394,1537580,1549267,1712150,1709337,1721019,2024408,2021583,2033304 -kyber1024 (10 executions),m4fspeed,1006341,1004590,1016692,1029398,1027642,1039752,1091847,1090091,1102201 -kyber1024 (10 executions),m4fstack,1009603,1007702,1019835,1038001,1036100,1048226,1101208,1099307,1111470 -kyber512 (10 executions),clean,597372,596106,607563,702227,700957,712416,890274,889008,900467 -kyber512 (10 executions),m4fspeed,387341,386762,387769,391098,390520,391527,428365,427786,428794 -kyber512 (10 executions),m4fstack,386853,386573,387221,392801,392521,393166,430140,429861,430504 -kyber768 (10 executions),clean,989247,987825,999577,1138807,1137381,1149131,1388568,1387146,1398896 -kyber768 (10 executions),m4fspeed,631912,631599,632459,656455,656155,656969,705524,705223,706037 -kyber768 (10 executions),m4fstack,634213,632786,644273,662556,661130,672615,712081,710655,722140 +ml-kem-1024 (10 executions),clean,1540607,1535678,1547404,1712361,1707431,1719164,2024616,2019674,2031410 +ml-kem-1024 (10 executions),m4fspeed,1007759,1004549,1017159,1030702,1027443,1040101,1093153,1089895,1102552 +ml-kem-1024 (10 executions),m4fstack,1010100,1007459,1018999,1038190,1035550,1047090,1101234,1098594,1110134 +ml-kem-512 (10 executions),clean,595882,595636,596329,700689,700440,701134,888740,888494,889189 +ml-kem-512 (10 executions),m4fspeed,388544,387190,398814,392178,390825,402445,429456,428102,439722 +ml-kem-512 (10 executions),m4fstack,386999,386677,387465,392813,392492,393280,430152,429831,430619 +ml-kem-768 (10 executions),clean,990901,986123,997663,1140412,1135630,1147169,1390176,1385399,1396936 +ml-kem-768 (10 executions),m4fspeed,631949,631658,632164,656369,656082,656596,705436,705148,705663 +ml-kem-768 (10 executions),m4fstack,634227,632761,644635,662468,661003,672877,711996,710530,722405 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) aimer128f (10 executions),mem_opt,564325,564324,564326,46875341,46874593,46876276,26989249,26988505,26989828 @@ -168,15 +168,15 @@ bikel3,opt,69444,50556,155388,,,,,, hqc-128,clean,33644,51428,55892,,,,,, hqc-192,clean,65668,101636,110660,,,,,, hqc-256,clean,103756,161508,175972,,,,,, -kyber1024,clean,15136,18784,20360,,,,,, -kyber1024,m4fspeed,6436,7500,7484,,,,,, -kyber1024,m4fstack,3332,3372,3356,,,,,, -kyber512,clean,6168,8800,9576,,,,,, -kyber512,m4fspeed,4364,5436,5412,,,,,, -kyber512,m4fstack,2292,2348,2332,,,,,, -kyber768,clean,10272,13408,14504,,,,,, -kyber768,m4fspeed,5396,6468,6452,,,,,, -kyber768,m4fstack,2820,2860,2844,,,,,, +ml-kem-1024,clean,15128,18776,20352,,,,,, +ml-kem-1024,m4fspeed,6436,7500,7484,,,,,, +ml-kem-1024,m4fstack,3332,3372,3356,,,,,, +ml-kem-512,clean,6152,8784,9560,,,,,, +ml-kem-512,m4fspeed,4372,5436,5412,,,,,, +ml-kem-512,m4fstack,2300,2348,2332,,,,,, +ml-kem-768,clean,10248,13384,14480,,,,,, +ml-kem-768,m4fspeed,5396,6468,6452,,,,,, +ml-kem-768,m4fstack,2820,2860,2844,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, aimer128f,mem_opt,8728,13864,15440,,,,,, @@ -329,15 +329,15 @@ bikel3,opt,0.0,6.3,0.2,,,,,, hqc-128,clean,0.4,0.8,0.5,,,,,, hqc-192,clean,0.3,0.5,0.3,,,,,, hqc-256,clean,0.2,0.4,0.3,,,,,, -kyber1024,clean,49.9,45.6,38.6,,,,,, -kyber1024,m4fspeed,76.1,75.5,71.2,,,,,, -kyber1024,m4fstack,75.8,74.9,70.6,,,,,, -kyber512,clean,49.8,41.1,32.5,,,,,, -kyber512,m4fspeed,76.5,73.5,67.1,,,,,, -kyber512,m4fstack,76.5,73.1,66.8,,,,,, -kyber768,clean,48.5,43.2,35.4,,,,,, -kyber768,m4fspeed,75.4,74.4,69.2,,,,,, -kyber768,m4fstack,75.3,73.8,68.7,,,,,, +ml-kem-1024,clean,50.0,45.6,38.6,,,,,, +ml-kem-1024,m4fspeed,76.1,75.5,71.2,,,,,, +ml-kem-1024,m4fstack,75.9,74.9,70.7,,,,,, +ml-kem-512,clean,49.9,41.1,32.5,,,,,, +ml-kem-512,m4fspeed,76.5,73.5,67.2,,,,,, +ml-kem-512,m4fstack,76.6,73.2,66.9,,,,,, +ml-kem-768,clean,48.6,43.2,35.4,,,,,, +ml-kem-768,m4fspeed,75.5,74.4,69.3,,,,,, +ml-kem-768,m4fstack,75.3,73.9,68.7,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, aimer128f,mem_opt,50.6,66.1,49.6,,,,,, @@ -489,15 +489,15 @@ bikel3,opt,43091,24,1,43116,,,,, hqc-128,clean,18628,0,0,18628,,,,, hqc-192,clean,21104,0,0,21104,,,,, hqc-256,clean,26260,0,0,26260,,,,, -kyber1024,clean,6264,0,0,6264,,,,, -kyber1024,m4fspeed,16884,0,0,16884,,,,, -kyber1024,m4fstack,14092,0,0,14092,,,,, -kyber512,clean,5132,0,0,5132,,,,, -kyber512,m4fspeed,15796,0,0,15796,,,,, -kyber512,m4fstack,13280,0,0,13280,,,,, -kyber768,clean,5136,0,0,5136,,,,, -kyber768,m4fspeed,15964,0,0,15964,,,,, -kyber768,m4fstack,13288,0,0,13288,,,,, +ml-kem-1024,clean,6160,0,0,6160,,,,, +ml-kem-1024,m4fspeed,16912,0,0,16912,,,,, +ml-kem-1024,m4fstack,14012,0,0,14012,,,,, +ml-kem-512,clean,5116,0,0,5116,,,,, +ml-kem-512,m4fspeed,15844,0,0,15844,,,,, +ml-kem-512,m4fstack,13324,0,0,13324,,,,, +ml-kem-768,clean,5120,0,0,5120,,,,, +ml-kem-768,m4fspeed,16012,0,0,16012,,,,, +ml-kem-768,m4fstack,13316,0,0,13316,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, aimer128f,mem_opt,17476,0,0,17476,,,,, diff --git a/benchmarks.md b/benchmarks.md index dfc2106f..a7788590 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -9,15 +9,15 @@ | hqc-128 (10 executions) | clean | AVG: 52,705,201
MIN: 52,705,180
MAX: 52,705,224 | AVG: 105,650,897
MIN: 105,650,877
MAX: 105,650,927 | AVG: 159,569,179
MIN: 159,569,176
MAX: 159,569,183 | | hqc-192 (10 executions) | clean | AVG: 161,458,617
MIN: 161,458,590
MAX: 161,458,638 | AVG: 323,146,261
MIN: 323,146,250
MAX: 323,146,292 | AVG: 486,156,251
MIN: 486,156,214
MAX: 486,156,266 | | hqc-256 (10 executions) | clean | AVG: 295,934,078
MIN: 295,934,057
MAX: 295,934,104 | AVG: 591,853,870
MIN: 591,853,850
MAX: 591,853,898 | AVG: 891,163,005
MIN: 891,162,988
MAX: 891,163,038 | -| kyber1024 (10 executions) | clean | AVG: 1,540,394
MIN: 1,537,580
MAX: 1,549,267 | AVG: 1,712,150
MIN: 1,709,337
MAX: 1,721,019 | AVG: 2,024,408
MIN: 2,021,583
MAX: 2,033,304 | -| kyber1024 (10 executions) | m4fspeed | AVG: 1,006,341
MIN: 1,004,590
MAX: 1,016,692 | AVG: 1,029,398
MIN: 1,027,642
MAX: 1,039,752 | AVG: 1,091,847
MIN: 1,090,091
MAX: 1,102,201 | -| kyber1024 (10 executions) | m4fstack | AVG: 1,009,603
MIN: 1,007,702
MAX: 1,019,835 | AVG: 1,038,001
MIN: 1,036,100
MAX: 1,048,226 | AVG: 1,101,208
MIN: 1,099,307
MAX: 1,111,470 | -| kyber512 (10 executions) | clean | AVG: 597,372
MIN: 596,106
MAX: 607,563 | AVG: 702,227
MIN: 700,957
MAX: 712,416 | AVG: 890,274
MIN: 889,008
MAX: 900,467 | -| kyber512 (10 executions) | m4fspeed | AVG: 387,341
MIN: 386,762
MAX: 387,769 | AVG: 391,098
MIN: 390,520
MAX: 391,527 | AVG: 428,365
MIN: 427,786
MAX: 428,794 | -| kyber512 (10 executions) | m4fstack | AVG: 386,853
MIN: 386,573
MAX: 387,221 | AVG: 392,801
MIN: 392,521
MAX: 393,166 | AVG: 430,140
MIN: 429,861
MAX: 430,504 | -| kyber768 (10 executions) | clean | AVG: 989,247
MIN: 987,825
MAX: 999,577 | AVG: 1,138,807
MIN: 1,137,381
MAX: 1,149,131 | AVG: 1,388,568
MIN: 1,387,146
MAX: 1,398,896 | -| kyber768 (10 executions) | m4fspeed | AVG: 631,912
MIN: 631,599
MAX: 632,459 | AVG: 656,455
MIN: 656,155
MAX: 656,969 | AVG: 705,524
MIN: 705,223
MAX: 706,037 | -| kyber768 (10 executions) | m4fstack | AVG: 634,213
MIN: 632,786
MAX: 644,273 | AVG: 662,556
MIN: 661,130
MAX: 672,615 | AVG: 712,081
MIN: 710,655
MAX: 722,140 | +| ml-kem-1024 (10 executions) | clean | AVG: 1,540,607
MIN: 1,535,678
MAX: 1,547,404 | AVG: 1,712,361
MIN: 1,707,431
MAX: 1,719,164 | AVG: 2,024,616
MIN: 2,019,674
MAX: 2,031,410 | +| ml-kem-1024 (10 executions) | m4fspeed | AVG: 1,007,759
MIN: 1,004,549
MAX: 1,017,159 | AVG: 1,030,702
MIN: 1,027,443
MAX: 1,040,101 | AVG: 1,093,153
MIN: 1,089,895
MAX: 1,102,552 | +| ml-kem-1024 (10 executions) | m4fstack | AVG: 1,010,100
MIN: 1,007,459
MAX: 1,018,999 | AVG: 1,038,190
MIN: 1,035,550
MAX: 1,047,090 | AVG: 1,101,234
MIN: 1,098,594
MAX: 1,110,134 | +| ml-kem-512 (10 executions) | clean | AVG: 595,882
MIN: 595,636
MAX: 596,329 | AVG: 700,689
MIN: 700,440
MAX: 701,134 | AVG: 888,740
MIN: 888,494
MAX: 889,189 | +| ml-kem-512 (10 executions) | m4fspeed | AVG: 388,544
MIN: 387,190
MAX: 398,814 | AVG: 392,178
MIN: 390,825
MAX: 402,445 | AVG: 429,456
MIN: 428,102
MAX: 439,722 | +| ml-kem-512 (10 executions) | m4fstack | AVG: 386,999
MIN: 386,677
MAX: 387,465 | AVG: 392,813
MIN: 392,492
MAX: 393,280 | AVG: 430,152
MIN: 429,831
MAX: 430,619 | +| ml-kem-768 (10 executions) | clean | AVG: 990,901
MIN: 986,123
MAX: 997,663 | AVG: 1,140,412
MIN: 1,135,630
MAX: 1,147,169 | AVG: 1,390,176
MIN: 1,385,399
MAX: 1,396,936 | +| ml-kem-768 (10 executions) | m4fspeed | AVG: 631,949
MIN: 631,658
MAX: 632,164 | AVG: 656,369
MIN: 656,082
MAX: 656,596 | AVG: 705,436
MIN: 705,148
MAX: 705,663 | +| ml-kem-768 (10 executions) | m4fstack | AVG: 634,227
MIN: 632,761
MAX: 644,635 | AVG: 662,468
MIN: 661,003
MAX: 672,877 | AVG: 711,996
MIN: 710,530
MAX: 722,405 | ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | @@ -171,15 +171,15 @@ | hqc-128 | clean | 33,644 | 51,428 | 55,892 | | hqc-192 | clean | 65,668 | 101,636 | 110,660 | | hqc-256 | clean | 103,756 | 161,508 | 175,972 | -| kyber1024 | clean | 15,136 | 18,784 | 20,360 | -| kyber1024 | m4fspeed | 6,436 | 7,500 | 7,484 | -| kyber1024 | m4fstack | 3,332 | 3,372 | 3,356 | -| kyber512 | clean | 6,168 | 8,800 | 9,576 | -| kyber512 | m4fspeed | 4,364 | 5,436 | 5,412 | -| kyber512 | m4fstack | 2,292 | 2,348 | 2,332 | -| kyber768 | clean | 10,272 | 13,408 | 14,504 | -| kyber768 | m4fspeed | 5,396 | 6,468 | 6,452 | -| kyber768 | m4fstack | 2,820 | 2,860 | 2,844 | +| ml-kem-1024 | clean | 15,128 | 18,776 | 20,352 | +| ml-kem-1024 | m4fspeed | 6,436 | 7,500 | 7,484 | +| ml-kem-1024 | m4fstack | 3,332 | 3,372 | 3,356 | +| ml-kem-512 | clean | 6,152 | 8,784 | 9,560 | +| ml-kem-512 | m4fspeed | 4,372 | 5,436 | 5,412 | +| ml-kem-512 | m4fstack | 2,300 | 2,348 | 2,332 | +| ml-kem-768 | clean | 10,248 | 13,384 | 14,480 | +| ml-kem-768 | m4fspeed | 5,396 | 6,468 | 6,452 | +| ml-kem-768 | m4fstack | 2,820 | 2,860 | 2,844 | ## Signature Schemes | Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | | ------ | -------------- | ---------------------- | ------------ | -------------- | @@ -334,15 +334,15 @@ | hqc-128 | clean | 0.4% | 0.8% | 0.5% | | hqc-192 | clean | 0.3% | 0.5% | 0.3% | | hqc-256 | clean | 0.2% | 0.4% | 0.3% | -| kyber1024 | clean | 49.9% | 45.6% | 38.6% | -| kyber1024 | m4fspeed | 76.1% | 75.5% | 71.2% | -| kyber1024 | m4fstack | 75.8% | 74.9% | 70.6% | -| kyber512 | clean | 49.8% | 41.1% | 32.5% | -| kyber512 | m4fspeed | 76.5% | 73.5% | 67.1% | -| kyber512 | m4fstack | 76.5% | 73.1% | 66.8% | -| kyber768 | clean | 48.5% | 43.2% | 35.4% | -| kyber768 | m4fspeed | 75.4% | 74.4% | 69.2% | -| kyber768 | m4fstack | 75.3% | 73.8% | 68.7% | +| ml-kem-1024 | clean | 50.0% | 45.6% | 38.6% | +| ml-kem-1024 | m4fspeed | 76.1% | 75.5% | 71.2% | +| ml-kem-1024 | m4fstack | 75.9% | 74.9% | 70.7% | +| ml-kem-512 | clean | 49.9% | 41.1% | 32.5% | +| ml-kem-512 | m4fspeed | 76.5% | 73.5% | 67.2% | +| ml-kem-512 | m4fstack | 76.6% | 73.2% | 66.9% | +| ml-kem-768 | clean | 48.6% | 43.2% | 35.4% | +| ml-kem-768 | m4fspeed | 75.5% | 74.4% | 69.3% | +| ml-kem-768 | m4fstack | 75.3% | 73.9% | 68.7% | ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | @@ -496,15 +496,15 @@ | hqc-128 | clean | 18,628 | 0 | 0 | 18,628 | | hqc-192 | clean | 21,104 | 0 | 0 | 21,104 | | hqc-256 | clean | 26,260 | 0 | 0 | 26,260 | -| kyber1024 | clean | 6,264 | 0 | 0 | 6,264 | -| kyber1024 | m4fspeed | 16,884 | 0 | 0 | 16,884 | -| kyber1024 | m4fstack | 14,092 | 0 | 0 | 14,092 | -| kyber512 | clean | 5,132 | 0 | 0 | 5,132 | -| kyber512 | m4fspeed | 15,796 | 0 | 0 | 15,796 | -| kyber512 | m4fstack | 13,280 | 0 | 0 | 13,280 | -| kyber768 | clean | 5,136 | 0 | 0 | 5,136 | -| kyber768 | m4fspeed | 15,964 | 0 | 0 | 15,964 | -| kyber768 | m4fstack | 13,288 | 0 | 0 | 13,288 | +| ml-kem-1024 | clean | 6,160 | 0 | 0 | 6,160 | +| ml-kem-1024 | m4fspeed | 16,912 | 0 | 0 | 16,912 | +| ml-kem-1024 | m4fstack | 14,012 | 0 | 0 | 14,012 | +| ml-kem-512 | clean | 5,116 | 0 | 0 | 5,116 | +| ml-kem-512 | m4fspeed | 15,844 | 0 | 0 | 15,844 | +| ml-kem-512 | m4fstack | 13,324 | 0 | 0 | 13,324 | +| ml-kem-768 | clean | 5,120 | 0 | 0 | 5,120 | +| ml-kem-768 | m4fspeed | 16,012 | 0 | 0 | 16,012 | +| ml-kem-768 | m4fstack | 13,316 | 0 | 0 | 13,316 | ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | diff --git a/crypto_kem/kyber1024/m4fspeed/cbd.c b/crypto_kem/kyber1024/m4fspeed/cbd.c deleted file mode 120000 index 37d243ad..00000000 --- a/crypto_kem/kyber1024/m4fspeed/cbd.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/cbd.h b/crypto_kem/kyber1024/m4fspeed/cbd.h deleted file mode 120000 index c00c0559..00000000 --- a/crypto_kem/kyber1024/m4fspeed/cbd.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/cmov_int16.S b/crypto_kem/kyber1024/m4fspeed/cmov_int16.S deleted file mode 120000 index e57b8b26..00000000 --- a/crypto_kem/kyber1024/m4fspeed/cmov_int16.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/fastaddsub.S b/crypto_kem/kyber1024/m4fspeed/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber1024/m4fspeed/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/fastbasemul.S b/crypto_kem/kyber1024/m4fspeed/fastbasemul.S deleted file mode 120000 index 7156a2a8..00000000 --- a/crypto_kem/kyber1024/m4fspeed/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/fastinvntt.S b/crypto_kem/kyber1024/m4fspeed/fastinvntt.S deleted file mode 120000 index 38ea2e36..00000000 --- a/crypto_kem/kyber1024/m4fspeed/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/fastntt.S b/crypto_kem/kyber1024/m4fspeed/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber1024/m4fspeed/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/indcpa.c b/crypto_kem/kyber1024/m4fspeed/indcpa.c deleted file mode 120000 index 04181f8d..00000000 --- a/crypto_kem/kyber1024/m4fspeed/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/indcpa.h b/crypto_kem/kyber1024/m4fspeed/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber1024/m4fspeed/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/kem.c b/crypto_kem/kyber1024/m4fspeed/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber1024/m4fspeed/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/macros.i b/crypto_kem/kyber1024/m4fspeed/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber1024/m4fspeed/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/matacc.c b/crypto_kem/kyber1024/m4fspeed/matacc.c deleted file mode 120000 index bf2438db..00000000 --- a/crypto_kem/kyber1024/m4fspeed/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/matacc.h b/crypto_kem/kyber1024/m4fspeed/matacc.h deleted file mode 120000 index 3288c40f..00000000 --- a/crypto_kem/kyber1024/m4fspeed/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/matacc.i b/crypto_kem/kyber1024/m4fspeed/matacc.i deleted file mode 120000 index e388a0ad..00000000 --- a/crypto_kem/kyber1024/m4fspeed/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/matacc_asm.S b/crypto_kem/kyber1024/m4fspeed/matacc_asm.S deleted file mode 120000 index 11b9cfc7..00000000 --- a/crypto_kem/kyber1024/m4fspeed/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/ntt.c b/crypto_kem/kyber1024/m4fspeed/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber1024/m4fspeed/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/ntt.h b/crypto_kem/kyber1024/m4fspeed/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber1024/m4fspeed/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/poly.c b/crypto_kem/kyber1024/m4fspeed/poly.c deleted file mode 120000 index ed549db6..00000000 --- a/crypto_kem/kyber1024/m4fspeed/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/poly.h b/crypto_kem/kyber1024/m4fspeed/poly.h deleted file mode 120000 index 6f495407..00000000 --- a/crypto_kem/kyber1024/m4fspeed/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/poly_asm.S b/crypto_kem/kyber1024/m4fspeed/poly_asm.S deleted file mode 120000 index 4424e11a..00000000 --- a/crypto_kem/kyber1024/m4fspeed/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/polyvec.c b/crypto_kem/kyber1024/m4fspeed/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber1024/m4fspeed/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/polyvec.h b/crypto_kem/kyber1024/m4fspeed/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber1024/m4fspeed/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/reduce.S b/crypto_kem/kyber1024/m4fspeed/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber1024/m4fspeed/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/symmetric-fips202.c b/crypto_kem/kyber1024/m4fspeed/symmetric-fips202.c deleted file mode 120000 index 98f6a1ae..00000000 --- a/crypto_kem/kyber1024/m4fspeed/symmetric-fips202.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/symmetric.h b/crypto_kem/kyber1024/m4fspeed/symmetric.h deleted file mode 120000 index 56622b89..00000000 --- a/crypto_kem/kyber1024/m4fspeed/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/verify.c b/crypto_kem/kyber1024/m4fspeed/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber1024/m4fspeed/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/verify.h b/crypto_kem/kyber1024/m4fspeed/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber1024/m4fspeed/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/cmov_int16.S b/crypto_kem/kyber1024/m4fstack/cmov_int16.S deleted file mode 120000 index e57b8b26..00000000 --- a/crypto_kem/kyber1024/m4fstack/cmov_int16.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/fastbasemul.S b/crypto_kem/kyber1024/m4fstack/fastbasemul.S deleted file mode 120000 index 7ba7f7e4..00000000 --- a/crypto_kem/kyber1024/m4fstack/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/fastinvntt.S b/crypto_kem/kyber1024/m4fstack/fastinvntt.S deleted file mode 120000 index 8b242d6c..00000000 --- a/crypto_kem/kyber1024/m4fstack/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/fastntt.S b/crypto_kem/kyber1024/m4fstack/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber1024/m4fstack/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/indcpa.c b/crypto_kem/kyber1024/m4fstack/indcpa.c deleted file mode 120000 index 7d86b771..00000000 --- a/crypto_kem/kyber1024/m4fstack/indcpa.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/indcpa.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/indcpa.h b/crypto_kem/kyber1024/m4fstack/indcpa.h deleted file mode 120000 index 66fb14f7..00000000 --- a/crypto_kem/kyber1024/m4fstack/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/matacc.c b/crypto_kem/kyber1024/m4fstack/matacc.c deleted file mode 120000 index 9934856f..00000000 --- a/crypto_kem/kyber1024/m4fstack/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/matacc.h b/crypto_kem/kyber1024/m4fstack/matacc.h deleted file mode 120000 index 17b44879..00000000 --- a/crypto_kem/kyber1024/m4fstack/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/matacc.i b/crypto_kem/kyber1024/m4fstack/matacc.i deleted file mode 120000 index 3804c85d..00000000 --- a/crypto_kem/kyber1024/m4fstack/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/matacc_asm.S b/crypto_kem/kyber1024/m4fstack/matacc_asm.S deleted file mode 120000 index 4a77c2bd..00000000 --- a/crypto_kem/kyber1024/m4fstack/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/poly.c b/crypto_kem/kyber1024/m4fstack/poly.c deleted file mode 120000 index 209dba88..00000000 --- a/crypto_kem/kyber1024/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/poly.h b/crypto_kem/kyber1024/m4fstack/poly.h deleted file mode 120000 index e02915ca..00000000 --- a/crypto_kem/kyber1024/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/poly_asm.S b/crypto_kem/kyber1024/m4fstack/poly_asm.S deleted file mode 120000 index 9b529775..00000000 --- a/crypto_kem/kyber1024/m4fstack/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/cmov_int16.S b/crypto_kem/kyber512/m4fspeed/cmov_int16.S deleted file mode 120000 index e57b8b26..00000000 --- a/crypto_kem/kyber512/m4fspeed/cmov_int16.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/fastaddsub.S b/crypto_kem/kyber512/m4fspeed/fastaddsub.S deleted file mode 120000 index 462644bb..00000000 --- a/crypto_kem/kyber512/m4fspeed/fastaddsub.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/fastbasemul.S b/crypto_kem/kyber512/m4fspeed/fastbasemul.S deleted file mode 120000 index 7156a2a8..00000000 --- a/crypto_kem/kyber512/m4fspeed/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/fastinvntt.S b/crypto_kem/kyber512/m4fspeed/fastinvntt.S deleted file mode 120000 index 38ea2e36..00000000 --- a/crypto_kem/kyber512/m4fspeed/fastinvntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/fastntt.S b/crypto_kem/kyber512/m4fspeed/fastntt.S deleted file mode 120000 index 6314b554..00000000 --- a/crypto_kem/kyber512/m4fspeed/fastntt.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/indcpa.h b/crypto_kem/kyber512/m4fspeed/indcpa.h deleted file mode 120000 index 86639d83..00000000 --- a/crypto_kem/kyber512/m4fspeed/indcpa.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/kem.c b/crypto_kem/kyber512/m4fspeed/kem.c deleted file mode 120000 index fba83bf4..00000000 --- a/crypto_kem/kyber512/m4fspeed/kem.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/macros.i b/crypto_kem/kyber512/m4fspeed/macros.i deleted file mode 120000 index d184a0fa..00000000 --- a/crypto_kem/kyber512/m4fspeed/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/matacc.c b/crypto_kem/kyber512/m4fspeed/matacc.c deleted file mode 120000 index bf2438db..00000000 --- a/crypto_kem/kyber512/m4fspeed/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/matacc.h b/crypto_kem/kyber512/m4fspeed/matacc.h deleted file mode 120000 index 3288c40f..00000000 --- a/crypto_kem/kyber512/m4fspeed/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/matacc.i b/crypto_kem/kyber512/m4fspeed/matacc.i deleted file mode 120000 index e388a0ad..00000000 --- a/crypto_kem/kyber512/m4fspeed/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/matacc_asm.S b/crypto_kem/kyber512/m4fspeed/matacc_asm.S deleted file mode 120000 index 11b9cfc7..00000000 --- a/crypto_kem/kyber512/m4fspeed/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/ntt.c b/crypto_kem/kyber512/m4fspeed/ntt.c deleted file mode 120000 index 21c83bdf..00000000 --- a/crypto_kem/kyber512/m4fspeed/ntt.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/ntt.h b/crypto_kem/kyber512/m4fspeed/ntt.h deleted file mode 120000 index bd203902..00000000 --- a/crypto_kem/kyber512/m4fspeed/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/poly_asm.S b/crypto_kem/kyber512/m4fspeed/poly_asm.S deleted file mode 120000 index 4424e11a..00000000 --- a/crypto_kem/kyber512/m4fspeed/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/polyvec.c b/crypto_kem/kyber512/m4fspeed/polyvec.c deleted file mode 120000 index 0aedeeef..00000000 --- a/crypto_kem/kyber512/m4fspeed/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/polyvec.h b/crypto_kem/kyber512/m4fspeed/polyvec.h deleted file mode 120000 index cee9bc6f..00000000 --- a/crypto_kem/kyber512/m4fspeed/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/reduce.S b/crypto_kem/kyber512/m4fspeed/reduce.S deleted file mode 120000 index 0b00788a..00000000 --- a/crypto_kem/kyber512/m4fspeed/reduce.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/symmetric-fips202.c b/crypto_kem/kyber512/m4fspeed/symmetric-fips202.c deleted file mode 120000 index 98f6a1ae..00000000 --- a/crypto_kem/kyber512/m4fspeed/symmetric-fips202.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/symmetric.h b/crypto_kem/kyber512/m4fspeed/symmetric.h deleted file mode 120000 index 56622b89..00000000 --- a/crypto_kem/kyber512/m4fspeed/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/verify.c b/crypto_kem/kyber512/m4fspeed/verify.c deleted file mode 120000 index 56596267..00000000 --- a/crypto_kem/kyber512/m4fspeed/verify.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/verify.h b/crypto_kem/kyber512/m4fspeed/verify.h deleted file mode 120000 index 72b107fb..00000000 --- a/crypto_kem/kyber512/m4fspeed/verify.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/cmov_int16.S b/crypto_kem/kyber512/m4fstack/cmov_int16.S deleted file mode 120000 index e57b8b26..00000000 --- a/crypto_kem/kyber512/m4fstack/cmov_int16.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/fastbasemul.S b/crypto_kem/kyber512/m4fstack/fastbasemul.S deleted file mode 120000 index 7ba7f7e4..00000000 --- a/crypto_kem/kyber512/m4fstack/fastbasemul.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/fastinvntt.S b/crypto_kem/kyber512/m4fstack/fastinvntt.S deleted file mode 100644 index 12577f38..00000000 --- a/crypto_kem/kyber512/m4fstack/fastinvntt.S +++ /dev/null @@ -1,356 +0,0 @@ -/****************************************************************************** -* Integrating the improved Plantard arithmetic into Kyber. -* -* Efficient Plantard arithmetic enables a faster Kyber implementation with the -* same stack usage. -* -* See the paper at https://eprint.iacr.org/2022/956.pdf for more details. -* -* @author Junhao Huang, BNU-HKBU United International College, Zhuhai, China -* jhhuang_nuaa@126.com -* -* @date September 2022 -******************************************************************************/ -#include "macros.i" - -.syntax unified -.cpu cortex-m4 -.thumb - -.macro mul_twiddle_plant a, twiddle, tmp, q, qa - smulwb \tmp, \twiddle, \a - smulwt \a, \twiddle, \a - smlabt \tmp, \tmp, \q, \qa - smlabt \a, \a, \q, \qa - pkhtb \a, \a, \tmp, asr#16 -.endm - -.macro doublebutterfly_plant a0, a1, twiddle, tmp, q, qa - smulwb \tmp, \twiddle, \a1 - smulwt \a1, \twiddle, \a1 - smlabt \tmp, \tmp, \q, \qa - smlabt \a1, \a1, \q, \qa - pkhtb \tmp, \a1, \tmp, asr#16 - usub16 \a1, \a0, \tmp - uadd16 \a0, \a0, \tmp -.endm - -.macro two_doublebutterfly_plant a0, a1, a2, a3, twiddle0, twiddle1, tmp, q, qa - doublebutterfly_plant \a0, \a1, \twiddle0, \tmp, \q, \qa - doublebutterfly_plant \a2, \a3, \twiddle1, \tmp, \q, \qa -.endm - -.macro fullplant a0, a1, a2, a3, a4, a5, a6, a7, tmp, q, qa, plantconst - movw \plantconst, #44984 - movt \plantconst, #19 - doubleplant \a0, \tmp, \q, \qa, \plantconst - doubleplant \a1, \tmp, \q, \qa, \plantconst - doubleplant \a2, \tmp, \q, \qa, \plantconst - doubleplant \a3, \tmp, \q, \qa, \plantconst - doubleplant \a4, \tmp, \q, \qa, \plantconst - doubleplant \a5, \tmp, \q, \qa, \plantconst - doubleplant \a6, \tmp, \q, \qa, \plantconst - doubleplant \a7, \tmp, \q, \qa, \plantconst -.endm - -.macro halfplant a0, a1, a2, a3, tmp, q, qa, plantconst - movw \plantconst, #44984 - movt \plantconst, #19 - doubleplant \a0, \tmp, \q, \qa, \plantconst - doubleplant \a1, \tmp, \q, \qa, \plantconst - doubleplant \a2, \tmp, \q, \qa, \plantconst - doubleplant \a3, \tmp, \q, \qa, \plantconst -.endm - - -// input: 0.5/1q -.macro _3_layer_double_inv_CT_16_plant_light c0, c1, c2, c3, c4, c5, c6, c7, xi2, xi4, xi5, xi6, twiddle1, tmp2, q, qa, tmp - - // layer 1 - sadd16.w \tmp, \c0, \c1 // c0, c1 - ssub16.w \c1, \c0, \c1 - sadd16.w \tmp2, \c2, \c3 // c2, c3 - ssub16.w \c3, \c2, \c3 - // tmp, c1, tmp2, c3: 1q maximum - sadd16.w \c0, \c4, \c5 // c4, c5 - ssub16.w \c5, \c4, \c5 - sadd16.w \c2, \c6, \c7 // c6, c7 - ssub16.w \c7, \c6, \c7 - // c4, c6 are free at this point - // c0,c5,c2,c7 1q maximum - - // layer 2 - sadd16.w \c6, \tmp, \tmp2 // c0, c2 - ssub16.w \tmp2, \tmp, \tmp2 - sadd16.w \c4, \c0, \c2 // c4, c6 - ssub16.w \c2, \c0, \c2 - // c6, tmp2, c4, c2: 2q maximum - - vmov.w \twiddle1, \xi2 - doublebutterfly_plant \c1, \c3, \twiddle1, \tmp, \q, \qa - doublebutterfly_plant \c5, \c7, \twiddle1, \tmp, \q, \qa - // c1, c3, c7, c5: 1.5q maximum; - - // tmp and c0 are free at this point - // layer 3 - sadd16.w \c0, \c6, \c4 // c0, c4 - ssub16.w \c4, \c6, \c4 - // c0, c4: 4q - // c6 are free at this point - vmov.w \twiddle1, \xi4 - doublebutterfly_plant \c1, \c5, \twiddle1, \tmp, \q, \qa - // c1, c5: 2q maximum - - vmov.w \twiddle1, \xi5 - // this block is one doublebutterfly - smulwb \tmp, \twiddle1, \c2 // c2, c6 - smulwt \c2, \twiddle1, \c2 - smlabt \tmp, \tmp, \q, \qa - smlabt \c2, \c2, \q, \qa - pkhtb \tmp, \c2, \tmp, asr#16 - ssub16.w \c6, \tmp2, \tmp - sadd16.w \c2, \tmp2, \tmp - //c6, c2: 4.5q - vmov.w \twiddle1, \xi6 - doublebutterfly_plant \c3, \c7, \twiddle1, \tmp, \q, \qa - //c3, c7: 2.5q maximum -.endm -.macro _3_layer_double_inv_CT_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - // layer 3 - ldr.w \twiddle1, [\twiddle_ptr], #4 - two_doublebutterfly_plant \c0, \c1, \c2, \c3, \twiddle1, \twiddle1, \tmp, \q, \qa - two_doublebutterfly_plant \c4, \c5, \c6, \c7, \twiddle1, \twiddle1, \tmp, \q, \qa - - // layer 2 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c2, \c1, \c3, \twiddle1, \twiddle2, \tmp, \q, \qa - - two_doublebutterfly_plant \c4, \c6, \c5, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa - - // layer 1 - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c0, \c4, \c1, \c5, \twiddle1, \twiddle2, \tmp, \q, \qa - - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - two_doublebutterfly_plant \c2, \c6, \c3, \c7, \twiddle1, \twiddle2, \tmp, \q, \qa -.endm - -.macro _3_layer_double_inv_twist_16_plant c0, c1, c2, c3, c4, c5, c6, c7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c0, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c1, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c2, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c3, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c4, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c5, \twiddle2, \tmp, \q, \qa - ldrd \twiddle1, \twiddle2, [\twiddle_ptr], #8 - mul_twiddle_plant \c6, \twiddle1, \tmp, \q, \qa - mul_twiddle_plant \c7, \twiddle2, \tmp, \q, \qa -.endm - -.global invntt_fast -.type invntt_fast, %function -.align 2 -invntt_fast: - push {r4-r11, r14} - vpush.w {s16-s23} - poly .req r0 - twiddle_ptr .req r1 - poly0 .req r2 - poly1 .req r3 - poly2 .req r4 - poly3 .req r5 - poly4 .req r6 - poly5 .req r7 - poly6 .req r8 - poly7 .req r9 - twiddle1 .req r10 - twiddle2 .req r11 - q .req r12 - // at the top of r12 - qa .req r0 - // qa=2^a q;a=3; at the bottom of r12 - tmp .req r14 - - movt q, #3329 - - ### LAYER 7+6+5+4 - .equ distance, 16 - .equ offset, 32 - .equ strincr, 64 - - // pre-load twiddle factors to FPU registers - vldm twiddle_ptr!, {s8-s22} - - add.w tmp, poly, #8*strincr - vmov s8, tmp - 1: - vmov s23, poly - // load a1, a3, ..., a15 - load poly, poly0, poly1, poly2, poly3, #offset, #distance/4+offset, #2*distance/4+offset, #3*distance/4+offset - load poly, poly4, poly5, poly6, poly7, #distance+offset, #5*distance/4+offset, #6*distance/4+offset, #7*distance/4+offset - - movw qa, #26632 - - // NTT on a1, a3, ..., a15 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - - // multiply coeffs by layer 4 twiddles for later use - // vmov twiddle1, s15 - vmov twiddle2, s16 - // mul_twiddle_plant poly0, twiddle1, tmp, q, qa // could be omitted but kept for reduction only - mul_twiddle_plant poly1, twiddle2, tmp, q, qa - - vmov twiddle1, s17 - vmov twiddle2, s18 - mul_twiddle_plant poly2, twiddle1, tmp, q, qa - mul_twiddle_plant poly3, twiddle2, tmp, q, qa - - vmov twiddle1, s19 - vmov twiddle2, s20 - mul_twiddle_plant poly4, twiddle1, tmp, q, qa - mul_twiddle_plant poly5, twiddle2, tmp, q, qa - - vmov twiddle1, s21 - vmov twiddle2, s22 - mul_twiddle_plant poly6, twiddle1, tmp, q, qa - mul_twiddle_plant poly7, twiddle2, tmp, q, qa - - vmov s0, poly0 // a1 - vmov s1, poly1 // a3 - vmov s2, poly2 // a5 - vmov s3, poly3 // a7 - vmov s4, poly4 // a9 - vmov s5, poly5 // a11 - vmov s6, poly6 // a13 - vmov s7, poly7 // a15 - // 0.5q - // ---------- - - vmov poly, s23 - // load a0, a2, ..., a14 - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #26632 - // NTT on a0, a2, ..., a14 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s10, s12, s13, s14, twiddle1, twiddle2, q, qa, tmp - // 1,3,5,7: <5q; 0,2,4,6:<1q - // layer 4 - 1 - // addsub: (a2, a6, a10, a14), (a3, a7, a11, a15) - vmov poly, s23 - vmov twiddle2, s1 // load a3 - uadd16 tmp, poly1, twiddle2 - usub16 poly1, poly1, twiddle2 - str.w tmp, [poly, #1*distance/4] - str.w poly1, [poly, #1*distance/4+offset] - - vmov twiddle2, s3 // load a7 - uadd16 tmp, poly3, twiddle2 - usub16 poly3, poly3, twiddle2 - str.w tmp, [poly, #3*distance/4] - str.w poly3, [poly, #3*distance/4+offset] - - vmov twiddle2, s5 // load a11 - uadd16 tmp, poly5, twiddle2 - usub16 poly5, poly5, twiddle2 - str.w tmp, [poly, #5*distance/4] - str.w poly5, [poly, #5*distance/4+offset] - - vmov twiddle2, s7 // load a15 - uadd16 tmp, poly7, twiddle2 - usub16 poly7, poly7, twiddle2 - str.w tmp, [poly, #7*distance/4] - str.w poly7, [poly, #7*distance/4+offset] - //1,3,5,7: < 5.5q - - // layer 4 - 2 - // addsub: (a0, a4, a8, a12), (a1, a5, a9, a13) - vmov poly3, s2 // load a5 - uadd16 tmp, poly2, poly3 - usub16 twiddle2, poly2, poly3 - str.w tmp, [poly, #2*distance/4] - str.w twiddle2, [poly, #2*distance/4+offset] - - vmov poly5, s4 // load a9 - uadd16 tmp, poly4, poly5 - usub16 twiddle2, poly4, poly5 - str.w tmp, [poly, #4*distance/4] - str.w twiddle2, [poly, #4*distance/4+offset] - - vmov poly7, s6 // load a13 - uadd16 tmp, poly6, poly7 - usub16 twiddle2, poly6, poly7 - str.w tmp, [poly, #6*distance/4] - str.w twiddle2, [poly, #6*distance/4+offset] - - vmov poly1, s0 // load a1 - uadd16 tmp, poly0, poly1 - usub16 twiddle2, poly0, poly1 - str.w twiddle2, [poly, #offset] - str.w tmp, [poly], #strincr // increase 2*8*4 = 64 (2 * 8 loads of 4 bytes each) - //0,2,4,6: < 1.5q - vmov tmp, s8 - cmp.w poly, tmp - bne.w 1b - - sub.w poly, #8*strincr - - ### LAYER 3+2+1 - - .equ distance, distance*16 - .equ strincr, 4 - - // ITER 0 - vmov s6, poly - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - vldm twiddle_ptr!, {s0-s5} - movw qa, #26632 - fullplant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7 tmp, q, qa, twiddle1 - // twiddle2 is used as tmp2 - _3_layer_double_inv_CT_16_plant_light poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, s1, s3, s4, s5, twiddle1, twiddle2, q, qa, tmp - - // twisting - _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - vmov poly, s6 - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - // ITER 1-15 - add.w tmp, poly, #strincr*3*(5) - vmov s14, tmp - 2: - vmov s6, poly - // polys upto 5.5q - load poly, poly0, poly1, poly2, poly3, #0, #distance/4, #2*distance/4, #3*distance/4 - load poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - - movw qa, #26632 - _3_layer_double_inv_CT_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - // twisting - _3_layer_double_inv_twist_16_plant poly0, poly1, poly2, poly3, poly4, poly5, poly6, poly7, twiddle1, twiddle2, twiddle_ptr, q, qa, tmp - - vmov poly, s6 - store poly, poly4, poly5, poly6, poly7, #distance, #5*distance/4, #6*distance/4, #7*distance/4 - str.w poly1, [poly, #distance/4] - str.w poly2, [poly, #2*distance/4] - str.w poly3, [poly, #3*distance/4] - str.w poly0, [poly], #4 - - vmov tmp, s14 - cmp.w poly, tmp - bne.w 2b - - vpop.w {s16-s23} - pop {r4-r11, pc} diff --git a/crypto_kem/kyber512/m4fstack/matacc.c b/crypto_kem/kyber512/m4fstack/matacc.c deleted file mode 120000 index 9934856f..00000000 --- a/crypto_kem/kyber512/m4fstack/matacc.c +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/matacc.h b/crypto_kem/kyber512/m4fstack/matacc.h deleted file mode 120000 index 17b44879..00000000 --- a/crypto_kem/kyber512/m4fstack/matacc.h +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/matacc.i b/crypto_kem/kyber512/m4fstack/matacc.i deleted file mode 120000 index 3804c85d..00000000 --- a/crypto_kem/kyber512/m4fstack/matacc.i +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/matacc_asm.S b/crypto_kem/kyber512/m4fstack/matacc_asm.S deleted file mode 120000 index 4a77c2bd..00000000 --- a/crypto_kem/kyber512/m4fstack/matacc_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/poly_asm.S b/crypto_kem/kyber512/m4fstack/poly_asm.S deleted file mode 120000 index 9b529775..00000000 --- a/crypto_kem/kyber512/m4fstack/poly_asm.S +++ /dev/null @@ -1 +0,0 @@ -../../kyber768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber768/m4fstack/symmetric-fips202.c b/crypto_kem/kyber768/m4fstack/symmetric-fips202.c deleted file mode 120000 index fa4ba9ac..00000000 --- a/crypto_kem/kyber768/m4fstack/symmetric-fips202.c +++ /dev/null @@ -1 +0,0 @@ -../m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/api.h b/crypto_kem/ml-kem-1024/m4fspeed/api.h similarity index 100% rename from crypto_kem/kyber1024/m4fspeed/api.h rename to crypto_kem/ml-kem-1024/m4fspeed/api.h diff --git a/crypto_kem/ml-kem-1024/m4fspeed/cbd.c b/crypto_kem/ml-kem-1024/m4fspeed/cbd.c new file mode 120000 index 00000000..801f7f81 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/cbd.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cbd.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/cbd.h b/crypto_kem/ml-kem-1024/m4fspeed/cbd.h new file mode 120000 index 00000000..4f9e3afa --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/cbd.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cbd.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/cmov_int16.S b/crypto_kem/ml-kem-1024/m4fspeed/cmov_int16.S new file mode 120000 index 00000000..bdef6f46 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/cmov_int16.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/fastaddsub.S b/crypto_kem/ml-kem-1024/m4fspeed/fastaddsub.S new file mode 120000 index 00000000..aa555642 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/fastaddsub.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/fastbasemul.S b/crypto_kem/ml-kem-1024/m4fspeed/fastbasemul.S new file mode 120000 index 00000000..4384e1d1 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/fastbasemul.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/fastinvntt.S b/crypto_kem/ml-kem-1024/m4fspeed/fastinvntt.S new file mode 120000 index 00000000..ede60d79 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/fastinvntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/fastntt.S b/crypto_kem/ml-kem-1024/m4fspeed/fastntt.S new file mode 120000 index 00000000..d34524f9 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/fastntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/indcpa.c b/crypto_kem/ml-kem-1024/m4fspeed/indcpa.c new file mode 120000 index 00000000..25db6b1a --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/indcpa.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/indcpa.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/indcpa.h b/crypto_kem/ml-kem-1024/m4fspeed/indcpa.h new file mode 120000 index 00000000..e6f36626 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/indcpa.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/kem.c b/crypto_kem/ml-kem-1024/m4fspeed/kem.c new file mode 120000 index 00000000..489b6f94 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/kem.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/macros.i b/crypto_kem/ml-kem-1024/m4fspeed/macros.i new file mode 120000 index 00000000..a7d8e742 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/macros.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/matacc.c b/crypto_kem/ml-kem-1024/m4fspeed/matacc.c new file mode 120000 index 00000000..71d72340 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/matacc.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/matacc.h b/crypto_kem/ml-kem-1024/m4fspeed/matacc.h new file mode 120000 index 00000000..19b67726 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/matacc.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/matacc.i b/crypto_kem/ml-kem-1024/m4fspeed/matacc.i new file mode 120000 index 00000000..39b6e23d --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/matacc.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/matacc_asm.S b/crypto_kem/ml-kem-1024/m4fspeed/matacc_asm.S new file mode 120000 index 00000000..3c7d05e1 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/matacc_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/ntt.c b/crypto_kem/ml-kem-1024/m4fspeed/ntt.c new file mode 120000 index 00000000..971c6b0c --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/ntt.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/ntt.h b/crypto_kem/ml-kem-1024/m4fspeed/ntt.h new file mode 120000 index 00000000..11e111d3 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/ntt.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fspeed/params.h b/crypto_kem/ml-kem-1024/m4fspeed/params.h similarity index 100% rename from crypto_kem/kyber1024/m4fspeed/params.h rename to crypto_kem/ml-kem-1024/m4fspeed/params.h diff --git a/crypto_kem/ml-kem-1024/m4fspeed/poly.c b/crypto_kem/ml-kem-1024/m4fspeed/poly.c new file mode 120000 index 00000000..b432b8a0 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/poly.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/poly.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/poly.h b/crypto_kem/ml-kem-1024/m4fspeed/poly.h new file mode 120000 index 00000000..6003dc34 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/poly.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/poly.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/poly_asm.S b/crypto_kem/ml-kem-1024/m4fspeed/poly_asm.S new file mode 120000 index 00000000..c4bda05f --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/poly_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/polyvec.c b/crypto_kem/ml-kem-1024/m4fspeed/polyvec.c new file mode 120000 index 00000000..c3f7d0a6 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/polyvec.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/polyvec.h b/crypto_kem/ml-kem-1024/m4fspeed/polyvec.h new file mode 120000 index 00000000..47cf6c34 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/polyvec.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/reduce.S b/crypto_kem/ml-kem-1024/m4fspeed/reduce.S new file mode 120000 index 00000000..2edf10c8 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/reduce.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/symmetric-fips202.c b/crypto_kem/ml-kem-1024/m4fspeed/symmetric-fips202.c new file mode 120000 index 00000000..5adc9ae6 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/symmetric-fips202.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/symmetric.h b/crypto_kem/ml-kem-1024/m4fspeed/symmetric.h new file mode 120000 index 00000000..698a10dc --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/symmetric.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/verify.c b/crypto_kem/ml-kem-1024/m4fspeed/verify.c new file mode 120000 index 00000000..85d7f505 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/verify.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fspeed/verify.h b/crypto_kem/ml-kem-1024/m4fspeed/verify.h new file mode 120000 index 00000000..e19a3016 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fspeed/verify.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/api.h b/crypto_kem/ml-kem-1024/m4fstack/api.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/api.h rename to crypto_kem/ml-kem-1024/m4fstack/api.h diff --git a/crypto_kem/kyber1024/m4fstack/cbd.c b/crypto_kem/ml-kem-1024/m4fstack/cbd.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/cbd.c rename to crypto_kem/ml-kem-1024/m4fstack/cbd.c diff --git a/crypto_kem/kyber1024/m4fstack/cbd.h b/crypto_kem/ml-kem-1024/m4fstack/cbd.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/cbd.h rename to crypto_kem/ml-kem-1024/m4fstack/cbd.h diff --git a/crypto_kem/ml-kem-1024/m4fstack/cmov_int16.S b/crypto_kem/ml-kem-1024/m4fstack/cmov_int16.S new file mode 120000 index 00000000..bdef6f46 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/cmov_int16.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/fastaddsub.S b/crypto_kem/ml-kem-1024/m4fstack/fastaddsub.S similarity index 100% rename from crypto_kem/kyber1024/m4fstack/fastaddsub.S rename to crypto_kem/ml-kem-1024/m4fstack/fastaddsub.S diff --git a/crypto_kem/ml-kem-1024/m4fstack/fastbasemul.S b/crypto_kem/ml-kem-1024/m4fstack/fastbasemul.S new file mode 120000 index 00000000..531385d1 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/fastbasemul.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/fastinvntt.S b/crypto_kem/ml-kem-1024/m4fstack/fastinvntt.S new file mode 120000 index 00000000..ede60d79 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/fastinvntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/fastntt.S b/crypto_kem/ml-kem-1024/m4fstack/fastntt.S new file mode 120000 index 00000000..d34524f9 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/fastntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/indcpa.c b/crypto_kem/ml-kem-1024/m4fstack/indcpa.c new file mode 120000 index 00000000..a4103b16 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/indcpa.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/indcpa.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/indcpa.h b/crypto_kem/ml-kem-1024/m4fstack/indcpa.h new file mode 120000 index 00000000..9e56c804 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/indcpa.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/indcpa.h \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/kem.c b/crypto_kem/ml-kem-1024/m4fstack/kem.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/kem.c rename to crypto_kem/ml-kem-1024/m4fstack/kem.c diff --git a/crypto_kem/kyber1024/m4fstack/macros.i b/crypto_kem/ml-kem-1024/m4fstack/macros.i similarity index 100% rename from crypto_kem/kyber1024/m4fstack/macros.i rename to crypto_kem/ml-kem-1024/m4fstack/macros.i diff --git a/crypto_kem/ml-kem-1024/m4fstack/matacc.c b/crypto_kem/ml-kem-1024/m4fstack/matacc.c new file mode 120000 index 00000000..5558ec8f --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/matacc.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/matacc.h b/crypto_kem/ml-kem-1024/m4fstack/matacc.h new file mode 120000 index 00000000..4eb7706e --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/matacc.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/matacc.i b/crypto_kem/ml-kem-1024/m4fstack/matacc.i new file mode 120000 index 00000000..0d39b07b --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/matacc.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/matacc_asm.S b/crypto_kem/ml-kem-1024/m4fstack/matacc_asm.S new file mode 120000 index 00000000..0079bb51 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/matacc_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/ntt.c b/crypto_kem/ml-kem-1024/m4fstack/ntt.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/ntt.c rename to crypto_kem/ml-kem-1024/m4fstack/ntt.c diff --git a/crypto_kem/kyber1024/m4fstack/ntt.h b/crypto_kem/ml-kem-1024/m4fstack/ntt.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/ntt.h rename to crypto_kem/ml-kem-1024/m4fstack/ntt.h diff --git a/crypto_kem/kyber1024/m4fstack/params.h b/crypto_kem/ml-kem-1024/m4fstack/params.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/params.h rename to crypto_kem/ml-kem-1024/m4fstack/params.h diff --git a/crypto_kem/ml-kem-1024/m4fstack/poly.c b/crypto_kem/ml-kem-1024/m4fstack/poly.c new file mode 120000 index 00000000..df6f119a --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/poly.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/poly.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/poly.h b/crypto_kem/ml-kem-1024/m4fstack/poly.h new file mode 120000 index 00000000..ad89400e --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/poly.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/poly.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-1024/m4fstack/poly_asm.S b/crypto_kem/ml-kem-1024/m4fstack/poly_asm.S new file mode 120000 index 00000000..167ee5ee --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/poly_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/polyvec.c b/crypto_kem/ml-kem-1024/m4fstack/polyvec.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/polyvec.c rename to crypto_kem/ml-kem-1024/m4fstack/polyvec.c diff --git a/crypto_kem/kyber1024/m4fstack/polyvec.h b/crypto_kem/ml-kem-1024/m4fstack/polyvec.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/polyvec.h rename to crypto_kem/ml-kem-1024/m4fstack/polyvec.h diff --git a/crypto_kem/kyber1024/m4fstack/reduce.S b/crypto_kem/ml-kem-1024/m4fstack/reduce.S similarity index 100% rename from crypto_kem/kyber1024/m4fstack/reduce.S rename to crypto_kem/ml-kem-1024/m4fstack/reduce.S diff --git a/crypto_kem/ml-kem-1024/m4fstack/symmetric-fips202.c b/crypto_kem/ml-kem-1024/m4fstack/symmetric-fips202.c new file mode 120000 index 00000000..5adc9ae6 --- /dev/null +++ b/crypto_kem/ml-kem-1024/m4fstack/symmetric-fips202.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/kyber1024/m4fstack/symmetric.h b/crypto_kem/ml-kem-1024/m4fstack/symmetric.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/symmetric.h rename to crypto_kem/ml-kem-1024/m4fstack/symmetric.h diff --git a/crypto_kem/kyber1024/m4fstack/verify.c b/crypto_kem/ml-kem-1024/m4fstack/verify.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/verify.c rename to crypto_kem/ml-kem-1024/m4fstack/verify.c diff --git a/crypto_kem/kyber1024/m4fstack/verify.h b/crypto_kem/ml-kem-1024/m4fstack/verify.h similarity index 100% rename from crypto_kem/kyber1024/m4fstack/verify.h rename to crypto_kem/ml-kem-1024/m4fstack/verify.h diff --git a/crypto_kem/kyber512/m4fspeed/api.h b/crypto_kem/ml-kem-512/m4fspeed/api.h similarity index 100% rename from crypto_kem/kyber512/m4fspeed/api.h rename to crypto_kem/ml-kem-512/m4fspeed/api.h diff --git a/crypto_kem/kyber512/m4fspeed/cbd.c b/crypto_kem/ml-kem-512/m4fspeed/cbd.c similarity index 100% rename from crypto_kem/kyber512/m4fspeed/cbd.c rename to crypto_kem/ml-kem-512/m4fspeed/cbd.c diff --git a/crypto_kem/kyber512/m4fspeed/cbd.h b/crypto_kem/ml-kem-512/m4fspeed/cbd.h similarity index 100% rename from crypto_kem/kyber512/m4fspeed/cbd.h rename to crypto_kem/ml-kem-512/m4fspeed/cbd.h diff --git a/crypto_kem/ml-kem-512/m4fspeed/cmov_int16.S b/crypto_kem/ml-kem-512/m4fspeed/cmov_int16.S new file mode 120000 index 00000000..bdef6f46 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/cmov_int16.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/fastaddsub.S b/crypto_kem/ml-kem-512/m4fspeed/fastaddsub.S new file mode 120000 index 00000000..aa555642 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/fastaddsub.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastaddsub.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/fastbasemul.S b/crypto_kem/ml-kem-512/m4fspeed/fastbasemul.S new file mode 120000 index 00000000..4384e1d1 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/fastbasemul.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/fastinvntt.S b/crypto_kem/ml-kem-512/m4fspeed/fastinvntt.S new file mode 120000 index 00000000..ede60d79 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/fastinvntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/fastntt.S b/crypto_kem/ml-kem-512/m4fspeed/fastntt.S new file mode 120000 index 00000000..d34524f9 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/fastntt.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/fastntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/indcpa.c b/crypto_kem/ml-kem-512/m4fspeed/indcpa.c similarity index 98% rename from crypto_kem/kyber512/m4fspeed/indcpa.c rename to crypto_kem/ml-kem-512/m4fspeed/indcpa.c index 5e7fd5ca..99f5b3c1 100644 --- a/crypto_kem/kyber512/m4fspeed/indcpa.c +++ b/crypto_kem/ml-kem-512/m4fspeed/indcpa.c @@ -34,7 +34,9 @@ void indcpa_keypair_derand(unsigned char *pk, int i; unsigned char nonce = 0; - hash_g(buf, coins, KYBER_SYMBYTES); + memcpy(buf, coins, KYBER_SYMBYTES); + buf[KYBER_SYMBYTES] = KYBER_K; + hash_g(buf, buf, KYBER_SYMBYTES + 1); for (i = 0; i < KYBER_K; i++) poly_getnoise_eta1(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/ml-kem-512/m4fspeed/indcpa.h b/crypto_kem/ml-kem-512/m4fspeed/indcpa.h new file mode 120000 index 00000000..e6f36626 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/indcpa.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/indcpa.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/kem.c b/crypto_kem/ml-kem-512/m4fspeed/kem.c new file mode 120000 index 00000000..489b6f94 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/kem.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/kem.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/macros.i b/crypto_kem/ml-kem-512/m4fspeed/macros.i new file mode 120000 index 00000000..a7d8e742 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/macros.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/macros.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/matacc.c b/crypto_kem/ml-kem-512/m4fspeed/matacc.c new file mode 120000 index 00000000..71d72340 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/matacc.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/matacc.h b/crypto_kem/ml-kem-512/m4fspeed/matacc.h new file mode 120000 index 00000000..19b67726 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/matacc.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/matacc.i b/crypto_kem/ml-kem-512/m4fspeed/matacc.i new file mode 120000 index 00000000..39b6e23d --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/matacc.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/matacc_asm.S b/crypto_kem/ml-kem-512/m4fspeed/matacc_asm.S new file mode 120000 index 00000000..3c7d05e1 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/matacc_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/ntt.c b/crypto_kem/ml-kem-512/m4fspeed/ntt.c new file mode 120000 index 00000000..971c6b0c --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/ntt.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/ntt.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/ntt.h b/crypto_kem/ml-kem-512/m4fspeed/ntt.h new file mode 120000 index 00000000..11e111d3 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/ntt.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/ntt.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fspeed/params.h b/crypto_kem/ml-kem-512/m4fspeed/params.h similarity index 100% rename from crypto_kem/kyber512/m4fspeed/params.h rename to crypto_kem/ml-kem-512/m4fspeed/params.h diff --git a/crypto_kem/kyber512/m4fspeed/poly.c b/crypto_kem/ml-kem-512/m4fspeed/poly.c similarity index 100% rename from crypto_kem/kyber512/m4fspeed/poly.c rename to crypto_kem/ml-kem-512/m4fspeed/poly.c diff --git a/crypto_kem/kyber512/m4fspeed/poly.h b/crypto_kem/ml-kem-512/m4fspeed/poly.h similarity index 100% rename from crypto_kem/kyber512/m4fspeed/poly.h rename to crypto_kem/ml-kem-512/m4fspeed/poly.h diff --git a/crypto_kem/ml-kem-512/m4fspeed/poly_asm.S b/crypto_kem/ml-kem-512/m4fspeed/poly_asm.S new file mode 120000 index 00000000..c4bda05f --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/poly_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/polyvec.c b/crypto_kem/ml-kem-512/m4fspeed/polyvec.c new file mode 120000 index 00000000..c3f7d0a6 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/polyvec.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/polyvec.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/polyvec.h b/crypto_kem/ml-kem-512/m4fspeed/polyvec.h new file mode 120000 index 00000000..47cf6c34 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/polyvec.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/polyvec.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/reduce.S b/crypto_kem/ml-kem-512/m4fspeed/reduce.S new file mode 120000 index 00000000..2edf10c8 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/reduce.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/reduce.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. b/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. new file mode 120000 index 00000000..e49ba066 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric-fips202. \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202.c b/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202.c new file mode 120000 index 00000000..5adc9ae6 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric-fips202.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/symmetric.h b/crypto_kem/ml-kem-512/m4fspeed/symmetric.h new file mode 120000 index 00000000..698a10dc --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/symmetric.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/symmetric.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/verify.c b/crypto_kem/ml-kem-512/m4fspeed/verify.c new file mode 120000 index 00000000..85d7f505 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/verify.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/verify.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fspeed/verify.h b/crypto_kem/ml-kem-512/m4fspeed/verify.h new file mode 120000 index 00000000..e19a3016 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fspeed/verify.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/verify.h \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/api.h b/crypto_kem/ml-kem-512/m4fstack/api.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/api.h rename to crypto_kem/ml-kem-512/m4fstack/api.h diff --git a/crypto_kem/kyber512/m4fstack/cbd.c b/crypto_kem/ml-kem-512/m4fstack/cbd.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/cbd.c rename to crypto_kem/ml-kem-512/m4fstack/cbd.c diff --git a/crypto_kem/kyber512/m4fstack/cbd.h b/crypto_kem/ml-kem-512/m4fstack/cbd.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/cbd.h rename to crypto_kem/ml-kem-512/m4fstack/cbd.h diff --git a/crypto_kem/ml-kem-512/m4fstack/cmov_int16.S b/crypto_kem/ml-kem-512/m4fstack/cmov_int16.S new file mode 120000 index 00000000..bdef6f46 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/cmov_int16.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fspeed/cmov_int16.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/fastaddsub.S b/crypto_kem/ml-kem-512/m4fstack/fastaddsub.S similarity index 100% rename from crypto_kem/kyber512/m4fstack/fastaddsub.S rename to crypto_kem/ml-kem-512/m4fstack/fastaddsub.S diff --git a/crypto_kem/ml-kem-512/m4fstack/fastbasemul.S b/crypto_kem/ml-kem-512/m4fstack/fastbasemul.S new file mode 120000 index 00000000..531385d1 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/fastbasemul.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/fastbasemul.S \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fstack/fastinvntt.S b/crypto_kem/ml-kem-512/m4fstack/fastinvntt.S new file mode 120000 index 00000000..1ad2d319 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/fastinvntt.S @@ -0,0 +1 @@ +../m4fspeed/fastinvntt.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/fastntt.S b/crypto_kem/ml-kem-512/m4fstack/fastntt.S similarity index 100% rename from crypto_kem/kyber512/m4fstack/fastntt.S rename to crypto_kem/ml-kem-512/m4fstack/fastntt.S diff --git a/crypto_kem/kyber512/m4fstack/indcpa.c b/crypto_kem/ml-kem-512/m4fstack/indcpa.c similarity index 98% rename from crypto_kem/kyber512/m4fstack/indcpa.c rename to crypto_kem/ml-kem-512/m4fstack/indcpa.c index 764d494d..94d6a57a 100644 --- a/crypto_kem/kyber512/m4fstack/indcpa.c +++ b/crypto_kem/ml-kem-512/m4fstack/indcpa.c @@ -29,7 +29,9 @@ void indcpa_keypair_derand(unsigned char *pk, int i; unsigned char nonce = 0; - hash_g(buf, coins, KYBER_SYMBYTES); + memcpy(buf, coins, KYBER_SYMBYTES); + buf[KYBER_SYMBYTES] = KYBER_K; + hash_g(buf, buf, KYBER_SYMBYTES + 1); for (i = 0; i < KYBER_K; i++) poly_getnoise_eta1(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber512/m4fstack/indcpa.h b/crypto_kem/ml-kem-512/m4fstack/indcpa.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/indcpa.h rename to crypto_kem/ml-kem-512/m4fstack/indcpa.h diff --git a/crypto_kem/kyber512/m4fstack/kem.c b/crypto_kem/ml-kem-512/m4fstack/kem.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/kem.c rename to crypto_kem/ml-kem-512/m4fstack/kem.c diff --git a/crypto_kem/kyber512/m4fstack/macros.i b/crypto_kem/ml-kem-512/m4fstack/macros.i similarity index 100% rename from crypto_kem/kyber512/m4fstack/macros.i rename to crypto_kem/ml-kem-512/m4fstack/macros.i diff --git a/crypto_kem/ml-kem-512/m4fstack/matacc.c b/crypto_kem/ml-kem-512/m4fstack/matacc.c new file mode 120000 index 00000000..5558ec8f --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/matacc.c @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.c \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fstack/matacc.h b/crypto_kem/ml-kem-512/m4fstack/matacc.h new file mode 120000 index 00000000..4eb7706e --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/matacc.h @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.h \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fstack/matacc.i b/crypto_kem/ml-kem-512/m4fstack/matacc.i new file mode 120000 index 00000000..0d39b07b --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/matacc.i @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc.i \ No newline at end of file diff --git a/crypto_kem/ml-kem-512/m4fstack/matacc_asm.S b/crypto_kem/ml-kem-512/m4fstack/matacc_asm.S new file mode 120000 index 00000000..0079bb51 --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/matacc_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/matacc_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/ntt.c b/crypto_kem/ml-kem-512/m4fstack/ntt.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/ntt.c rename to crypto_kem/ml-kem-512/m4fstack/ntt.c diff --git a/crypto_kem/kyber512/m4fstack/ntt.h b/crypto_kem/ml-kem-512/m4fstack/ntt.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/ntt.h rename to crypto_kem/ml-kem-512/m4fstack/ntt.h diff --git a/crypto_kem/kyber512/m4fstack/params.h b/crypto_kem/ml-kem-512/m4fstack/params.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/params.h rename to crypto_kem/ml-kem-512/m4fstack/params.h diff --git a/crypto_kem/kyber512/m4fstack/poly.c b/crypto_kem/ml-kem-512/m4fstack/poly.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/poly.c rename to crypto_kem/ml-kem-512/m4fstack/poly.c diff --git a/crypto_kem/kyber512/m4fstack/poly.h b/crypto_kem/ml-kem-512/m4fstack/poly.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/poly.h rename to crypto_kem/ml-kem-512/m4fstack/poly.h diff --git a/crypto_kem/ml-kem-512/m4fstack/poly_asm.S b/crypto_kem/ml-kem-512/m4fstack/poly_asm.S new file mode 120000 index 00000000..167ee5ee --- /dev/null +++ b/crypto_kem/ml-kem-512/m4fstack/poly_asm.S @@ -0,0 +1 @@ +../../ml-kem-768/m4fstack/poly_asm.S \ No newline at end of file diff --git a/crypto_kem/kyber512/m4fstack/polyvec.c b/crypto_kem/ml-kem-512/m4fstack/polyvec.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/polyvec.c rename to crypto_kem/ml-kem-512/m4fstack/polyvec.c diff --git a/crypto_kem/kyber512/m4fstack/polyvec.h b/crypto_kem/ml-kem-512/m4fstack/polyvec.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/polyvec.h rename to crypto_kem/ml-kem-512/m4fstack/polyvec.h diff --git a/crypto_kem/kyber512/m4fstack/reduce.S b/crypto_kem/ml-kem-512/m4fstack/reduce.S similarity index 100% rename from crypto_kem/kyber512/m4fstack/reduce.S rename to crypto_kem/ml-kem-512/m4fstack/reduce.S diff --git a/crypto_kem/kyber1024/m4fstack/symmetric-fips202.c b/crypto_kem/ml-kem-512/m4fstack/symmetric-fips202.c similarity index 100% rename from crypto_kem/kyber1024/m4fstack/symmetric-fips202.c rename to crypto_kem/ml-kem-512/m4fstack/symmetric-fips202.c diff --git a/crypto_kem/kyber512/m4fstack/symmetric.h b/crypto_kem/ml-kem-512/m4fstack/symmetric.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/symmetric.h rename to crypto_kem/ml-kem-512/m4fstack/symmetric.h diff --git a/crypto_kem/kyber512/m4fstack/verify.c b/crypto_kem/ml-kem-512/m4fstack/verify.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/verify.c rename to crypto_kem/ml-kem-512/m4fstack/verify.c diff --git a/crypto_kem/kyber512/m4fstack/verify.h b/crypto_kem/ml-kem-512/m4fstack/verify.h similarity index 100% rename from crypto_kem/kyber512/m4fstack/verify.h rename to crypto_kem/ml-kem-512/m4fstack/verify.h diff --git a/crypto_kem/kyber768/m4fspeed/api.h b/crypto_kem/ml-kem-768/m4fspeed/api.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/api.h rename to crypto_kem/ml-kem-768/m4fspeed/api.h diff --git a/crypto_kem/kyber768/m4fspeed/cbd.c b/crypto_kem/ml-kem-768/m4fspeed/cbd.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/cbd.c rename to crypto_kem/ml-kem-768/m4fspeed/cbd.c diff --git a/crypto_kem/kyber768/m4fspeed/cbd.h b/crypto_kem/ml-kem-768/m4fspeed/cbd.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/cbd.h rename to crypto_kem/ml-kem-768/m4fspeed/cbd.h diff --git a/crypto_kem/kyber768/m4fspeed/cmov_int16.S b/crypto_kem/ml-kem-768/m4fspeed/cmov_int16.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/cmov_int16.S rename to crypto_kem/ml-kem-768/m4fspeed/cmov_int16.S diff --git a/crypto_kem/kyber768/m4fspeed/fastaddsub.S b/crypto_kem/ml-kem-768/m4fspeed/fastaddsub.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/fastaddsub.S rename to crypto_kem/ml-kem-768/m4fspeed/fastaddsub.S diff --git a/crypto_kem/kyber768/m4fspeed/fastbasemul.S b/crypto_kem/ml-kem-768/m4fspeed/fastbasemul.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/fastbasemul.S rename to crypto_kem/ml-kem-768/m4fspeed/fastbasemul.S diff --git a/crypto_kem/kyber768/m4fspeed/fastinvntt.S b/crypto_kem/ml-kem-768/m4fspeed/fastinvntt.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/fastinvntt.S rename to crypto_kem/ml-kem-768/m4fspeed/fastinvntt.S diff --git a/crypto_kem/kyber768/m4fspeed/fastntt.S b/crypto_kem/ml-kem-768/m4fspeed/fastntt.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/fastntt.S rename to crypto_kem/ml-kem-768/m4fspeed/fastntt.S diff --git a/crypto_kem/kyber768/m4fspeed/indcpa.c b/crypto_kem/ml-kem-768/m4fspeed/indcpa.c similarity index 98% rename from crypto_kem/kyber768/m4fspeed/indcpa.c rename to crypto_kem/ml-kem-768/m4fspeed/indcpa.c index 6e9d5b06..1aceabed 100644 --- a/crypto_kem/kyber768/m4fspeed/indcpa.c +++ b/crypto_kem/ml-kem-768/m4fspeed/indcpa.c @@ -32,7 +32,9 @@ void indcpa_keypair_derand(unsigned char *pk, int i; unsigned char nonce = 0; - hash_g(buf, coins, KYBER_SYMBYTES); + memcpy(buf, coins, KYBER_SYMBYTES); + buf[KYBER_SYMBYTES] = KYBER_K; + hash_g(buf, buf, KYBER_SYMBYTES + 1); for (i = 0; i < KYBER_K; i++) poly_getnoise(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber768/m4fspeed/indcpa.h b/crypto_kem/ml-kem-768/m4fspeed/indcpa.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/indcpa.h rename to crypto_kem/ml-kem-768/m4fspeed/indcpa.h diff --git a/crypto_kem/kyber768/m4fspeed/kem.c b/crypto_kem/ml-kem-768/m4fspeed/kem.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/kem.c rename to crypto_kem/ml-kem-768/m4fspeed/kem.c diff --git a/crypto_kem/kyber768/m4fspeed/macros.i b/crypto_kem/ml-kem-768/m4fspeed/macros.i similarity index 100% rename from crypto_kem/kyber768/m4fspeed/macros.i rename to crypto_kem/ml-kem-768/m4fspeed/macros.i diff --git a/crypto_kem/kyber768/m4fspeed/matacc.c b/crypto_kem/ml-kem-768/m4fspeed/matacc.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/matacc.c rename to crypto_kem/ml-kem-768/m4fspeed/matacc.c diff --git a/crypto_kem/kyber768/m4fspeed/matacc.h b/crypto_kem/ml-kem-768/m4fspeed/matacc.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/matacc.h rename to crypto_kem/ml-kem-768/m4fspeed/matacc.h diff --git a/crypto_kem/kyber768/m4fspeed/matacc.i b/crypto_kem/ml-kem-768/m4fspeed/matacc.i similarity index 100% rename from crypto_kem/kyber768/m4fspeed/matacc.i rename to crypto_kem/ml-kem-768/m4fspeed/matacc.i diff --git a/crypto_kem/kyber768/m4fspeed/matacc_asm.S b/crypto_kem/ml-kem-768/m4fspeed/matacc_asm.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/matacc_asm.S rename to crypto_kem/ml-kem-768/m4fspeed/matacc_asm.S diff --git a/crypto_kem/kyber768/m4fspeed/ntt.c b/crypto_kem/ml-kem-768/m4fspeed/ntt.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/ntt.c rename to crypto_kem/ml-kem-768/m4fspeed/ntt.c diff --git a/crypto_kem/kyber768/m4fspeed/ntt.h b/crypto_kem/ml-kem-768/m4fspeed/ntt.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/ntt.h rename to crypto_kem/ml-kem-768/m4fspeed/ntt.h diff --git a/crypto_kem/kyber768/m4fspeed/params.h b/crypto_kem/ml-kem-768/m4fspeed/params.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/params.h rename to crypto_kem/ml-kem-768/m4fspeed/params.h diff --git a/crypto_kem/kyber768/m4fspeed/poly.c b/crypto_kem/ml-kem-768/m4fspeed/poly.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/poly.c rename to crypto_kem/ml-kem-768/m4fspeed/poly.c diff --git a/crypto_kem/kyber768/m4fspeed/poly.h b/crypto_kem/ml-kem-768/m4fspeed/poly.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/poly.h rename to crypto_kem/ml-kem-768/m4fspeed/poly.h diff --git a/crypto_kem/kyber768/m4fspeed/poly_asm.S b/crypto_kem/ml-kem-768/m4fspeed/poly_asm.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/poly_asm.S rename to crypto_kem/ml-kem-768/m4fspeed/poly_asm.S diff --git a/crypto_kem/kyber768/m4fspeed/polyvec.c b/crypto_kem/ml-kem-768/m4fspeed/polyvec.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/polyvec.c rename to crypto_kem/ml-kem-768/m4fspeed/polyvec.c diff --git a/crypto_kem/kyber768/m4fspeed/polyvec.h b/crypto_kem/ml-kem-768/m4fspeed/polyvec.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/polyvec.h rename to crypto_kem/ml-kem-768/m4fspeed/polyvec.h diff --git a/crypto_kem/kyber768/m4fspeed/reduce.S b/crypto_kem/ml-kem-768/m4fspeed/reduce.S similarity index 100% rename from crypto_kem/kyber768/m4fspeed/reduce.S rename to crypto_kem/ml-kem-768/m4fspeed/reduce.S diff --git a/crypto_kem/kyber768/m4fspeed/symmetric-fips202.c b/crypto_kem/ml-kem-768/m4fspeed/symmetric-fips202.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/symmetric-fips202.c rename to crypto_kem/ml-kem-768/m4fspeed/symmetric-fips202.c diff --git a/crypto_kem/kyber768/m4fspeed/symmetric.h b/crypto_kem/ml-kem-768/m4fspeed/symmetric.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/symmetric.h rename to crypto_kem/ml-kem-768/m4fspeed/symmetric.h diff --git a/crypto_kem/kyber768/m4fspeed/verify.c b/crypto_kem/ml-kem-768/m4fspeed/verify.c similarity index 100% rename from crypto_kem/kyber768/m4fspeed/verify.c rename to crypto_kem/ml-kem-768/m4fspeed/verify.c diff --git a/crypto_kem/kyber768/m4fspeed/verify.h b/crypto_kem/ml-kem-768/m4fspeed/verify.h similarity index 100% rename from crypto_kem/kyber768/m4fspeed/verify.h rename to crypto_kem/ml-kem-768/m4fspeed/verify.h diff --git a/crypto_kem/kyber768/m4fstack/api.h b/crypto_kem/ml-kem-768/m4fstack/api.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/api.h rename to crypto_kem/ml-kem-768/m4fstack/api.h diff --git a/crypto_kem/kyber768/m4fstack/cbd.c b/crypto_kem/ml-kem-768/m4fstack/cbd.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/cbd.c rename to crypto_kem/ml-kem-768/m4fstack/cbd.c diff --git a/crypto_kem/kyber768/m4fstack/cbd.h b/crypto_kem/ml-kem-768/m4fstack/cbd.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/cbd.h rename to crypto_kem/ml-kem-768/m4fstack/cbd.h diff --git a/crypto_kem/kyber768/m4fstack/cmov_int16.S b/crypto_kem/ml-kem-768/m4fstack/cmov_int16.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/cmov_int16.S rename to crypto_kem/ml-kem-768/m4fstack/cmov_int16.S diff --git a/crypto_kem/kyber768/m4fstack/fastaddsub.S b/crypto_kem/ml-kem-768/m4fstack/fastaddsub.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/fastaddsub.S rename to crypto_kem/ml-kem-768/m4fstack/fastaddsub.S diff --git a/crypto_kem/kyber768/m4fstack/fastbasemul.S b/crypto_kem/ml-kem-768/m4fstack/fastbasemul.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/fastbasemul.S rename to crypto_kem/ml-kem-768/m4fstack/fastbasemul.S diff --git a/crypto_kem/kyber768/m4fstack/fastinvntt.S b/crypto_kem/ml-kem-768/m4fstack/fastinvntt.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/fastinvntt.S rename to crypto_kem/ml-kem-768/m4fstack/fastinvntt.S diff --git a/crypto_kem/kyber768/m4fstack/fastntt.S b/crypto_kem/ml-kem-768/m4fstack/fastntt.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/fastntt.S rename to crypto_kem/ml-kem-768/m4fstack/fastntt.S diff --git a/crypto_kem/kyber768/m4fstack/indcpa.c b/crypto_kem/ml-kem-768/m4fstack/indcpa.c similarity index 98% rename from crypto_kem/kyber768/m4fstack/indcpa.c rename to crypto_kem/ml-kem-768/m4fstack/indcpa.c index bb0ce408..38697978 100644 --- a/crypto_kem/kyber768/m4fstack/indcpa.c +++ b/crypto_kem/ml-kem-768/m4fstack/indcpa.c @@ -29,7 +29,9 @@ void indcpa_keypair_derand(unsigned char *pk, int i; unsigned char nonce = 0; - hash_g(buf, coins, KYBER_SYMBYTES); + memcpy(buf, coins, KYBER_SYMBYTES); + buf[KYBER_SYMBYTES] = KYBER_K; + hash_g(buf, buf, KYBER_SYMBYTES + 1); for (i = 0; i < KYBER_K; i++) poly_getnoise(skpv.vec + i, noiseseed, nonce++); diff --git a/crypto_kem/kyber768/m4fstack/indcpa.h b/crypto_kem/ml-kem-768/m4fstack/indcpa.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/indcpa.h rename to crypto_kem/ml-kem-768/m4fstack/indcpa.h diff --git a/crypto_kem/kyber768/m4fstack/kem.c b/crypto_kem/ml-kem-768/m4fstack/kem.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/kem.c rename to crypto_kem/ml-kem-768/m4fstack/kem.c diff --git a/crypto_kem/kyber768/m4fstack/macros.i b/crypto_kem/ml-kem-768/m4fstack/macros.i similarity index 100% rename from crypto_kem/kyber768/m4fstack/macros.i rename to crypto_kem/ml-kem-768/m4fstack/macros.i diff --git a/crypto_kem/kyber768/m4fstack/matacc.c b/crypto_kem/ml-kem-768/m4fstack/matacc.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/matacc.c rename to crypto_kem/ml-kem-768/m4fstack/matacc.c diff --git a/crypto_kem/kyber768/m4fstack/matacc.h b/crypto_kem/ml-kem-768/m4fstack/matacc.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/matacc.h rename to crypto_kem/ml-kem-768/m4fstack/matacc.h diff --git a/crypto_kem/kyber768/m4fstack/matacc.i b/crypto_kem/ml-kem-768/m4fstack/matacc.i similarity index 100% rename from crypto_kem/kyber768/m4fstack/matacc.i rename to crypto_kem/ml-kem-768/m4fstack/matacc.i diff --git a/crypto_kem/kyber768/m4fstack/matacc_asm.S b/crypto_kem/ml-kem-768/m4fstack/matacc_asm.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/matacc_asm.S rename to crypto_kem/ml-kem-768/m4fstack/matacc_asm.S diff --git a/crypto_kem/kyber768/m4fstack/ntt.c b/crypto_kem/ml-kem-768/m4fstack/ntt.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/ntt.c rename to crypto_kem/ml-kem-768/m4fstack/ntt.c diff --git a/crypto_kem/kyber768/m4fstack/ntt.h b/crypto_kem/ml-kem-768/m4fstack/ntt.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/ntt.h rename to crypto_kem/ml-kem-768/m4fstack/ntt.h diff --git a/crypto_kem/kyber768/m4fstack/params.h b/crypto_kem/ml-kem-768/m4fstack/params.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/params.h rename to crypto_kem/ml-kem-768/m4fstack/params.h diff --git a/crypto_kem/kyber768/m4fstack/poly.c b/crypto_kem/ml-kem-768/m4fstack/poly.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/poly.c rename to crypto_kem/ml-kem-768/m4fstack/poly.c diff --git a/crypto_kem/kyber768/m4fstack/poly.h b/crypto_kem/ml-kem-768/m4fstack/poly.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/poly.h rename to crypto_kem/ml-kem-768/m4fstack/poly.h diff --git a/crypto_kem/kyber768/m4fstack/poly_asm.S b/crypto_kem/ml-kem-768/m4fstack/poly_asm.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/poly_asm.S rename to crypto_kem/ml-kem-768/m4fstack/poly_asm.S diff --git a/crypto_kem/kyber768/m4fstack/polyvec.c b/crypto_kem/ml-kem-768/m4fstack/polyvec.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/polyvec.c rename to crypto_kem/ml-kem-768/m4fstack/polyvec.c diff --git a/crypto_kem/kyber768/m4fstack/polyvec.h b/crypto_kem/ml-kem-768/m4fstack/polyvec.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/polyvec.h rename to crypto_kem/ml-kem-768/m4fstack/polyvec.h diff --git a/crypto_kem/kyber768/m4fstack/reduce.S b/crypto_kem/ml-kem-768/m4fstack/reduce.S similarity index 100% rename from crypto_kem/kyber768/m4fstack/reduce.S rename to crypto_kem/ml-kem-768/m4fstack/reduce.S diff --git a/crypto_kem/kyber512/m4fstack/symmetric-fips202.c b/crypto_kem/ml-kem-768/m4fstack/symmetric-fips202.c similarity index 100% rename from crypto_kem/kyber512/m4fstack/symmetric-fips202.c rename to crypto_kem/ml-kem-768/m4fstack/symmetric-fips202.c diff --git a/crypto_kem/kyber768/m4fstack/symmetric.h b/crypto_kem/ml-kem-768/m4fstack/symmetric.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/symmetric.h rename to crypto_kem/ml-kem-768/m4fstack/symmetric.h diff --git a/crypto_kem/kyber768/m4fstack/verify.c b/crypto_kem/ml-kem-768/m4fstack/verify.c similarity index 100% rename from crypto_kem/kyber768/m4fstack/verify.c rename to crypto_kem/ml-kem-768/m4fstack/verify.c diff --git a/crypto_kem/kyber768/m4fstack/verify.h b/crypto_kem/ml-kem-768/m4fstack/verify.h similarity index 100% rename from crypto_kem/kyber768/m4fstack/verify.h rename to crypto_kem/ml-kem-768/m4fstack/verify.h diff --git a/mupq b/mupq index c15e900c..18fd6be4 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit c15e900c693afd6ca7165405bc5650efdbcce02d +Subproject commit 18fd6be462667a908a689702a46ec3005e9708fa diff --git a/skiplist.py b/skiplist.py index f483bfb7..b05b0ff5 100644 --- a/skiplist.py +++ b/skiplist.py @@ -84,15 +84,15 @@ {'scheme': 'hqc-128', 'implementation': 'clean', 'estmemory': 66560}, {'scheme': 'hqc-192', 'implementation': 'clean', 'estmemory': 130048}, {'scheme': 'hqc-256', 'implementation': 'clean', 'estmemory': 205824}, - {'scheme': 'kyber1024', 'implementation': 'clean', 'estmemory': 27648}, - {'scheme': 'kyber1024', 'implementation': 'm4fspeed', 'estmemory': 16384}, - {'scheme': 'kyber1024', 'implementation': 'm4fstack', 'estmemory': 12288}, - {'scheme': 'kyber512', 'implementation': 'clean', 'estmemory': 14336}, - {'scheme': 'kyber512', 'implementation': 'm4fspeed', 'estmemory': 10240}, - {'scheme': 'kyber512', 'implementation': 'm4fstack', 'estmemory': 7168}, - {'scheme': 'kyber768', 'implementation': 'clean', 'estmemory': 20480}, - {'scheme': 'kyber768', 'implementation': 'm4fspeed', 'estmemory': 13312}, - {'scheme': 'kyber768', 'implementation': 'm4fstack', 'estmemory': 10240}, + {'scheme': 'ml-kem-1024', 'implementation': 'clean', 'estmemory': 27648}, + {'scheme': 'ml-kem-1024', 'implementation': 'm4fspeed', 'estmemory': 16384}, + {'scheme': 'ml-kem-1024', 'implementation': 'm4fstack', 'estmemory': 12288}, + {'scheme': 'ml-kem-512', 'implementation': 'clean', 'estmemory': 14336}, + {'scheme': 'ml-kem-512', 'implementation': 'm4fspeed', 'estmemory': 10240}, + {'scheme': 'ml-kem-512', 'implementation': 'm4fstack', 'estmemory': 7168}, + {'scheme': 'ml-kem-768', 'implementation': 'clean', 'estmemory': 20480}, + {'scheme': 'ml-kem-768', 'implementation': 'm4fspeed', 'estmemory': 13312}, + {'scheme': 'ml-kem-768', 'implementation': 'm4fstack', 'estmemory': 10240}, {'scheme': 'mayo1', 'implementation': 'm4f', 'estmemory': 446464}, {'scheme': 'mayo1', 'implementation': 'ref', 'estmemory': 404480}, {'scheme': 'mayo2', 'implementation': 'm4f', 'estmemory': 287744}, From 024f636fa830e420b459eaae5571ed38913b0e08 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 15 Oct 2024 10:50:52 +0800 Subject: [PATCH 098/107] Create pull_request_template.md --- .github/.github/pull_request_template.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/.github/pull_request_template.md diff --git a/.github/.github/pull_request_template.md b/.github/.github/pull_request_template.md new file mode 100644 index 00000000..216e6426 --- /dev/null +++ b/.github/.github/pull_request_template.md @@ -0,0 +1,7 @@ +- [ ] PR changes testvectors +- [ ] Tests pass in qemu +- [ ] Testvectors pass in qemu +- [ ] Tests pass on Nucleo-L4R5ZI +- [ ] Testvectors pass on Nucleo-L4R5ZI +- [ ] Updated Benchmarks +- [ ] Updated Skiplist entries From 7664995357d12546d2c35c994e932d6128a7d919 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 15 Oct 2024 10:53:08 +0800 Subject: [PATCH 099/107] move PR template in right place --- .github/{.github => }/pull_request_template.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{.github => }/pull_request_template.md (100%) diff --git a/.github/.github/pull_request_template.md b/.github/pull_request_template.md similarity index 100% rename from .github/.github/pull_request_template.md rename to .github/pull_request_template.md From 68e1ca703c35727f8b99e428ac95e2fcacdbcb59 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 22 Oct 2024 17:15:12 +0800 Subject: [PATCH 100/107] Update to FIPS204 and rename Dilithium to ML-DSA (#363) * update Dilithium to final FIPS204 and rename * Dilithium: update and rename m4f+m4fstack implementations * switch to mupq master after merging * ML-DSA: update benchmarks * update skiplist * fix compiler warnings --- benchmarks.csv | 72 +++++++------- benchmarks.md | 72 +++++++------- crypto_sign/dilithium2/m4f/api.h | 26 ----- crypto_sign/dilithium2/m4f/sign.h | 37 ------- crypto_sign/dilithium2/m4fstack/poly.c | 1 - crypto_sign/dilithium2/m4fstack/poly.h | 1 - crypto_sign/dilithium3/m4f/api.h | 1 - crypto_sign/dilithium3/m4f/macros.i | 1 - crypto_sign/dilithium3/m4f/ntt.S | 1 - crypto_sign/dilithium3/m4f/ntt.h | 1 - crypto_sign/dilithium3/m4f/packing.c | 1 - crypto_sign/dilithium3/m4f/packing.h | 1 - crypto_sign/dilithium3/m4f/params.h | 1 - crypto_sign/dilithium3/m4f/pointwise_mont.h | 1 - crypto_sign/dilithium3/m4f/pointwise_mont.s | 1 - crypto_sign/dilithium3/m4f/poly.c | 1 - crypto_sign/dilithium3/m4f/poly.h | 1 - crypto_sign/dilithium3/m4f/polyvec.c | 1 - crypto_sign/dilithium3/m4f/polyvec.h | 1 - crypto_sign/dilithium3/m4f/reduce.h | 1 - crypto_sign/dilithium3/m4f/rounding.c | 1 - crypto_sign/dilithium3/m4f/rounding.h | 1 - crypto_sign/dilithium3/m4f/sign.c | 1 - crypto_sign/dilithium3/m4f/sign.h | 1 - crypto_sign/dilithium3/m4f/smallpoly.c | 1 - crypto_sign/dilithium3/m4f/smallpoly.h | 1 - crypto_sign/dilithium3/m4f/symmetric-shake.c | 1 - crypto_sign/dilithium3/m4f/symmetric.h | 1 - crypto_sign/dilithium3/m4f/vector.h | 1 - crypto_sign/dilithium3/m4f/vector.s | 1 - crypto_sign/dilithium3/m4fstack/api.h | 1 - crypto_sign/dilithium3/m4fstack/macros.i | 1 - .../dilithium3/m4fstack/macros_smallntt.i | 1 - crypto_sign/dilithium3/m4fstack/ntt.S | 1 - crypto_sign/dilithium3/m4fstack/ntt.h | 1 - crypto_sign/dilithium3/m4fstack/packing.c | 1 - crypto_sign/dilithium3/m4fstack/packing.h | 1 - crypto_sign/dilithium3/m4fstack/params.h | 1 - .../dilithium3/m4fstack/pointwise_mont.h | 1 - .../dilithium3/m4fstack/pointwise_mont.s | 1 - crypto_sign/dilithium3/m4fstack/poly.c | 1 - crypto_sign/dilithium3/m4fstack/poly.h | 1 - crypto_sign/dilithium3/m4fstack/polyvec.c | 1 - crypto_sign/dilithium3/m4fstack/polyvec.h | 1 - crypto_sign/dilithium3/m4fstack/reduce.h | 1 - crypto_sign/dilithium3/m4fstack/rounding.c | 1 - crypto_sign/dilithium3/m4fstack/rounding.h | 1 - crypto_sign/dilithium3/m4fstack/sign.c | 1 - crypto_sign/dilithium3/m4fstack/sign.h | 1 - crypto_sign/dilithium3/m4fstack/smallntt.h | 1 - .../dilithium3/m4fstack/smallntt_769.S | 1 - crypto_sign/dilithium3/m4fstack/smallpoly.c | 1 - crypto_sign/dilithium3/m4fstack/smallpoly.h | 1 - crypto_sign/dilithium3/m4fstack/stack.c | 1 - crypto_sign/dilithium3/m4fstack/stack.h | 1 - .../dilithium3/m4fstack/symmetric-shake.c | 1 - crypto_sign/dilithium3/m4fstack/symmetric.h | 1 - crypto_sign/dilithium3/m4fstack/vector.h | 1 - crypto_sign/dilithium3/m4fstack/vector.s | 1 - crypto_sign/dilithium5/m4f/api.h | 1 - crypto_sign/dilithium5/m4f/basemul_257.S | 1 - crypto_sign/dilithium5/m4f/fnt_257.S | 1 - crypto_sign/dilithium5/m4f/ifnt_257.S | 1 - crypto_sign/dilithium5/m4f/macros.i | 1 - crypto_sign/dilithium5/m4f/macros_fnt.i | 1 - crypto_sign/dilithium5/m4f/ntt.S | 1 - crypto_sign/dilithium5/m4f/ntt.h | 1 - crypto_sign/dilithium5/m4f/packing.c | 1 - crypto_sign/dilithium5/m4f/packing.h | 1 - crypto_sign/dilithium5/m4f/params.h | 1 - crypto_sign/dilithium5/m4f/pointwise_mont.h | 1 - crypto_sign/dilithium5/m4f/pointwise_mont.s | 1 - crypto_sign/dilithium5/m4f/poly.c | 1 - crypto_sign/dilithium5/m4f/poly.h | 1 - crypto_sign/dilithium5/m4f/polyvec.c | 1 - crypto_sign/dilithium5/m4f/polyvec.h | 1 - crypto_sign/dilithium5/m4f/reduce.h | 1 - crypto_sign/dilithium5/m4f/rounding.c | 1 - crypto_sign/dilithium5/m4f/rounding.h | 1 - crypto_sign/dilithium5/m4f/sign.c | 1 - crypto_sign/dilithium5/m4f/sign.h | 1 - crypto_sign/dilithium5/m4f/smallntt.h | 1 - crypto_sign/dilithium5/m4f/smallpoly.c | 1 - crypto_sign/dilithium5/m4f/smallpoly.h | 1 - crypto_sign/dilithium5/m4f/symmetric-shake.c | 1 - crypto_sign/dilithium5/m4f/symmetric.h | 1 - crypto_sign/dilithium5/m4f/vector.h | 1 - crypto_sign/dilithium5/m4f/vector.s | 1 - crypto_sign/dilithium5/m4fstack/api.h | 1 - crypto_sign/dilithium5/m4fstack/macros.i | 1 - .../dilithium5/m4fstack/macros_smallntt.i | 1 - crypto_sign/dilithium5/m4fstack/ntt.S | 1 - crypto_sign/dilithium5/m4fstack/ntt.h | 1 - crypto_sign/dilithium5/m4fstack/packing.c | 1 - crypto_sign/dilithium5/m4fstack/packing.h | 1 - crypto_sign/dilithium5/m4fstack/params.h | 1 - .../dilithium5/m4fstack/pointwise_mont.h | 1 - .../dilithium5/m4fstack/pointwise_mont.s | 1 - crypto_sign/dilithium5/m4fstack/poly.c | 1 - crypto_sign/dilithium5/m4fstack/poly.h | 1 - crypto_sign/dilithium5/m4fstack/polyvec.c | 1 - crypto_sign/dilithium5/m4fstack/polyvec.h | 1 - crypto_sign/dilithium5/m4fstack/reduce.h | 1 - crypto_sign/dilithium5/m4fstack/rounding.c | 1 - crypto_sign/dilithium5/m4fstack/rounding.h | 1 - crypto_sign/dilithium5/m4fstack/sign.c | 1 - crypto_sign/dilithium5/m4fstack/sign.h | 1 - crypto_sign/dilithium5/m4fstack/smallntt.h | 1 - .../dilithium5/m4fstack/smallntt_769.S | 1 - crypto_sign/dilithium5/m4fstack/smallpoly.c | 1 - crypto_sign/dilithium5/m4fstack/smallpoly.h | 1 - crypto_sign/dilithium5/m4fstack/stack.c | 1 - crypto_sign/dilithium5/m4fstack/stack.h | 1 - .../dilithium5/m4fstack/symmetric-shake.c | 1 - crypto_sign/dilithium5/m4fstack/symmetric.h | 1 - crypto_sign/dilithium5/m4fstack/vector.h | 1 - crypto_sign/dilithium5/m4fstack/vector.s | 1 - crypto_sign/ml-dsa-44/m4f/api.h | 35 +++++++ .../m4f/basemul_257.S | 0 .../{dilithium2 => ml-dsa-44}/m4f/config.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/fnt_257.S | 0 .../{dilithium2 => ml-dsa-44}/m4f/ifnt_257.S | 0 .../{dilithium2 => ml-dsa-44}/m4f/macros.i | 0 .../m4f/macros_fnt.i | 0 .../{dilithium2 => ml-dsa-44}/m4f/ntt.S | 0 .../{dilithium2 => ml-dsa-44}/m4f/ntt.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/packing.c | 0 .../{dilithium2 => ml-dsa-44}/m4f/packing.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/params.h | 0 .../m4f/pointwise_mont.h | 0 .../m4f/pointwise_mont.s | 0 .../{dilithium2 => ml-dsa-44}/m4f/poly.c | 15 +-- .../{dilithium2 => ml-dsa-44}/m4f/poly.h | 4 +- .../{dilithium2 => ml-dsa-44}/m4f/polyvec.c | 0 .../{dilithium2 => ml-dsa-44}/m4f/polyvec.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/reduce.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/rounding.c | 0 .../{dilithium2 => ml-dsa-44}/m4f/rounding.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/sign.c | 93 ++++++++++++------ crypto_sign/ml-dsa-44/m4f/sign.h | 11 +++ .../{dilithium2 => ml-dsa-44}/m4f/smallntt.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/smallpoly.c | 0 .../{dilithium2 => ml-dsa-44}/m4f/smallpoly.h | 0 .../m4f/symmetric-shake.c | 0 .../{dilithium2 => ml-dsa-44}/m4f/symmetric.h | 0 .../{dilithium2 => ml-dsa-44}/m4f/vector.h | 2 - .../{dilithium2 => ml-dsa-44}/m4f/vector.s | 54 ----------- .../{dilithium2 => ml-dsa-44}/m4fstack/api.h | 0 .../m4fstack/config.h | 0 .../m4fstack/macros.i | 0 .../m4fstack/macros_smallntt.i | 0 .../{dilithium2 => ml-dsa-44}/m4fstack/ntt.S | 0 .../{dilithium2 => ml-dsa-44}/m4fstack/ntt.h | 0 .../m4fstack/packing.c | 0 .../m4fstack/packing.h | 0 .../m4fstack/params.h | 0 .../m4fstack/pointwise_mont.h | 0 .../m4fstack/pointwise_mont.s | 0 crypto_sign/ml-dsa-44/m4fstack/poly.c | 1 + crypto_sign/ml-dsa-44/m4fstack/poly.h | 1 + .../m4fstack/polyvec.c | 0 .../m4fstack/polyvec.h | 0 .../m4fstack/reduce.h | 0 .../m4fstack/rounding.c | 0 .../m4fstack/rounding.h | 0 .../{dilithium2 => ml-dsa-44}/m4fstack/sign.c | 97 ++++++++++++------- .../{dilithium2 => ml-dsa-44}/m4fstack/sign.h | 0 .../m4fstack/smallntt.h | 0 .../m4fstack/smallntt_769.S | 0 .../m4fstack/smallpoly.c | 0 .../m4fstack/smallpoly.h | 0 .../m4fstack/stack.c | 24 +---- .../m4fstack/stack.h | 7 +- .../m4fstack/symmetric-shake.c | 0 .../m4fstack/symmetric.h | 0 .../m4fstack/vector.h | 0 .../m4fstack/vector.s | 0 crypto_sign/ml-dsa-65/m4f/api.h | 1 + .../{dilithium3 => ml-dsa-65}/m4f/config.h | 0 crypto_sign/ml-dsa-65/m4f/macros.i | 1 + .../m4f/macros_smallntt.i | 0 crypto_sign/ml-dsa-65/m4f/ntt.S | 1 + crypto_sign/ml-dsa-65/m4f/ntt.h | 1 + crypto_sign/ml-dsa-65/m4f/packing.c | 1 + crypto_sign/ml-dsa-65/m4f/packing.h | 1 + crypto_sign/ml-dsa-65/m4f/params.h | 1 + crypto_sign/ml-dsa-65/m4f/pointwise_mont.h | 1 + crypto_sign/ml-dsa-65/m4f/pointwise_mont.s | 1 + crypto_sign/ml-dsa-65/m4f/poly.c | 1 + crypto_sign/ml-dsa-65/m4f/poly.h | 1 + crypto_sign/ml-dsa-65/m4f/polyvec.c | 1 + crypto_sign/ml-dsa-65/m4f/polyvec.h | 1 + crypto_sign/ml-dsa-65/m4f/reduce.h | 1 + crypto_sign/ml-dsa-65/m4f/rounding.c | 1 + crypto_sign/ml-dsa-65/m4f/rounding.h | 1 + crypto_sign/ml-dsa-65/m4f/sign.c | 1 + crypto_sign/ml-dsa-65/m4f/sign.h | 1 + .../{dilithium3 => ml-dsa-65}/m4f/smallntt.h | 0 .../m4f/smallntt_769.S | 0 crypto_sign/ml-dsa-65/m4f/smallpoly.c | 1 + crypto_sign/ml-dsa-65/m4f/smallpoly.h | 1 + crypto_sign/ml-dsa-65/m4f/symmetric-shake.c | 1 + crypto_sign/ml-dsa-65/m4f/symmetric.h | 1 + crypto_sign/ml-dsa-65/m4f/vector.h | 1 + crypto_sign/ml-dsa-65/m4f/vector.s | 1 + crypto_sign/ml-dsa-65/m4fstack/api.h | 1 + .../m4fstack/config.h | 0 crypto_sign/ml-dsa-65/m4fstack/macros.i | 1 + .../ml-dsa-65/m4fstack/macros_smallntt.i | 1 + crypto_sign/ml-dsa-65/m4fstack/ntt.S | 1 + crypto_sign/ml-dsa-65/m4fstack/ntt.h | 1 + crypto_sign/ml-dsa-65/m4fstack/packing.c | 1 + crypto_sign/ml-dsa-65/m4fstack/packing.h | 1 + crypto_sign/ml-dsa-65/m4fstack/params.h | 1 + .../ml-dsa-65/m4fstack/pointwise_mont.h | 1 + .../ml-dsa-65/m4fstack/pointwise_mont.s | 1 + crypto_sign/ml-dsa-65/m4fstack/poly.c | 1 + crypto_sign/ml-dsa-65/m4fstack/poly.h | 1 + crypto_sign/ml-dsa-65/m4fstack/polyvec.c | 1 + crypto_sign/ml-dsa-65/m4fstack/polyvec.h | 1 + crypto_sign/ml-dsa-65/m4fstack/reduce.h | 1 + crypto_sign/ml-dsa-65/m4fstack/rounding.c | 1 + crypto_sign/ml-dsa-65/m4fstack/rounding.h | 1 + crypto_sign/ml-dsa-65/m4fstack/sign.c | 1 + crypto_sign/ml-dsa-65/m4fstack/sign.h | 1 + crypto_sign/ml-dsa-65/m4fstack/smallntt.h | 1 + crypto_sign/ml-dsa-65/m4fstack/smallntt_769.S | 1 + crypto_sign/ml-dsa-65/m4fstack/smallpoly.c | 1 + crypto_sign/ml-dsa-65/m4fstack/smallpoly.h | 1 + crypto_sign/ml-dsa-65/m4fstack/smalltt.h | 1 + crypto_sign/ml-dsa-65/m4fstack/stack.c | 1 + crypto_sign/ml-dsa-65/m4fstack/stack.h | 1 + .../ml-dsa-65/m4fstack/symmetric-shake.c | 1 + crypto_sign/ml-dsa-65/m4fstack/symmetric.h | 1 + crypto_sign/ml-dsa-65/m4fstack/vector.h | 1 + crypto_sign/ml-dsa-65/m4fstack/vector.s | 1 + crypto_sign/ml-dsa-87/m4f/api.h | 1 + crypto_sign/ml-dsa-87/m4f/basemul_257.S | 1 + .../{dilithium5 => ml-dsa-87}/m4f/config.h | 0 crypto_sign/ml-dsa-87/m4f/fnt_257.S | 1 + crypto_sign/ml-dsa-87/m4f/ifnt_257.S | 1 + crypto_sign/ml-dsa-87/m4f/macros.i | 1 + crypto_sign/ml-dsa-87/m4f/macros_fnt.i | 1 + crypto_sign/ml-dsa-87/m4f/ntt.S | 1 + crypto_sign/ml-dsa-87/m4f/ntt.h | 1 + crypto_sign/ml-dsa-87/m4f/packing.c | 1 + crypto_sign/ml-dsa-87/m4f/packing.h | 1 + crypto_sign/ml-dsa-87/m4f/params.h | 1 + crypto_sign/ml-dsa-87/m4f/pointwise_mont.h | 1 + crypto_sign/ml-dsa-87/m4f/pointwise_mont.s | 1 + crypto_sign/ml-dsa-87/m4f/poly.c | 1 + crypto_sign/ml-dsa-87/m4f/poly.h | 1 + crypto_sign/ml-dsa-87/m4f/polyvec.c | 1 + crypto_sign/ml-dsa-87/m4f/polyvec.h | 1 + crypto_sign/ml-dsa-87/m4f/reduce.h | 1 + crypto_sign/ml-dsa-87/m4f/rounding.c | 1 + crypto_sign/ml-dsa-87/m4f/rounding.h | 1 + crypto_sign/ml-dsa-87/m4f/sign.c | 1 + crypto_sign/ml-dsa-87/m4f/sign.h | 1 + crypto_sign/ml-dsa-87/m4f/smallntt.h | 1 + crypto_sign/ml-dsa-87/m4f/smallpoly.c | 1 + crypto_sign/ml-dsa-87/m4f/smallpoly.h | 1 + crypto_sign/ml-dsa-87/m4f/symmetric-shake.c | 1 + crypto_sign/ml-dsa-87/m4f/symmetric.h | 1 + crypto_sign/ml-dsa-87/m4f/vector.h | 1 + crypto_sign/ml-dsa-87/m4f/vector.s | 1 + crypto_sign/ml-dsa-87/m4fstack/api.h | 1 + .../m4fstack/config.h | 0 crypto_sign/ml-dsa-87/m4fstack/macros.i | 1 + .../ml-dsa-87/m4fstack/macros_smallntt.i | 1 + crypto_sign/ml-dsa-87/m4fstack/ntt.S | 1 + crypto_sign/ml-dsa-87/m4fstack/ntt.h | 1 + crypto_sign/ml-dsa-87/m4fstack/packing.c | 1 + crypto_sign/ml-dsa-87/m4fstack/packing.h | 1 + crypto_sign/ml-dsa-87/m4fstack/params.h | 1 + .../ml-dsa-87/m4fstack/pointwise_mont.h | 1 + .../ml-dsa-87/m4fstack/pointwise_mont.s | 1 + crypto_sign/ml-dsa-87/m4fstack/poly.c | 1 + crypto_sign/ml-dsa-87/m4fstack/poly.h | 1 + crypto_sign/ml-dsa-87/m4fstack/polyvec.c | 1 + crypto_sign/ml-dsa-87/m4fstack/polyvec.h | 1 + crypto_sign/ml-dsa-87/m4fstack/reduce.h | 1 + crypto_sign/ml-dsa-87/m4fstack/rounding.c | 1 + crypto_sign/ml-dsa-87/m4fstack/rounding.h | 1 + crypto_sign/ml-dsa-87/m4fstack/sign.c | 1 + crypto_sign/ml-dsa-87/m4fstack/sign.h | 1 + crypto_sign/ml-dsa-87/m4fstack/smallntt.h | 1 + crypto_sign/ml-dsa-87/m4fstack/smallntt_769.S | 1 + crypto_sign/ml-dsa-87/m4fstack/smallpoly.c | 1 + crypto_sign/ml-dsa-87/m4fstack/smallpoly.h | 1 + crypto_sign/ml-dsa-87/m4fstack/stack.c | 1 + crypto_sign/ml-dsa-87/m4fstack/stack.h | 1 + .../ml-dsa-87/m4fstack/symmetric-shake.c | 1 + crypto_sign/ml-dsa-87/m4fstack/symmetric.h | 1 + crypto_sign/ml-dsa-87/m4fstack/vector.h | 1 + crypto_sign/ml-dsa-87/m4fstack/vector.s | 1 + mupq | 2 +- skiplist.py | 18 ++-- 298 files changed, 372 insertions(+), 424 deletions(-) delete mode 100644 crypto_sign/dilithium2/m4f/api.h delete mode 100644 crypto_sign/dilithium2/m4f/sign.h delete mode 120000 crypto_sign/dilithium2/m4fstack/poly.c delete mode 120000 crypto_sign/dilithium2/m4fstack/poly.h delete mode 120000 crypto_sign/dilithium3/m4f/api.h delete mode 120000 crypto_sign/dilithium3/m4f/macros.i delete mode 120000 crypto_sign/dilithium3/m4f/ntt.S delete mode 120000 crypto_sign/dilithium3/m4f/ntt.h delete mode 120000 crypto_sign/dilithium3/m4f/packing.c delete mode 120000 crypto_sign/dilithium3/m4f/packing.h delete mode 120000 crypto_sign/dilithium3/m4f/params.h delete mode 120000 crypto_sign/dilithium3/m4f/pointwise_mont.h delete mode 120000 crypto_sign/dilithium3/m4f/pointwise_mont.s delete mode 120000 crypto_sign/dilithium3/m4f/poly.c delete mode 120000 crypto_sign/dilithium3/m4f/poly.h delete mode 120000 crypto_sign/dilithium3/m4f/polyvec.c delete mode 120000 crypto_sign/dilithium3/m4f/polyvec.h delete mode 120000 crypto_sign/dilithium3/m4f/reduce.h delete mode 120000 crypto_sign/dilithium3/m4f/rounding.c delete mode 120000 crypto_sign/dilithium3/m4f/rounding.h delete mode 120000 crypto_sign/dilithium3/m4f/sign.c delete mode 120000 crypto_sign/dilithium3/m4f/sign.h delete mode 120000 crypto_sign/dilithium3/m4f/smallpoly.c delete mode 120000 crypto_sign/dilithium3/m4f/smallpoly.h delete mode 120000 crypto_sign/dilithium3/m4f/symmetric-shake.c delete mode 120000 crypto_sign/dilithium3/m4f/symmetric.h delete mode 120000 crypto_sign/dilithium3/m4f/vector.h delete mode 120000 crypto_sign/dilithium3/m4f/vector.s delete mode 120000 crypto_sign/dilithium3/m4fstack/api.h delete mode 120000 crypto_sign/dilithium3/m4fstack/macros.i delete mode 120000 crypto_sign/dilithium3/m4fstack/macros_smallntt.i delete mode 120000 crypto_sign/dilithium3/m4fstack/ntt.S delete mode 120000 crypto_sign/dilithium3/m4fstack/ntt.h delete mode 120000 crypto_sign/dilithium3/m4fstack/packing.c delete mode 120000 crypto_sign/dilithium3/m4fstack/packing.h delete mode 120000 crypto_sign/dilithium3/m4fstack/params.h delete mode 120000 crypto_sign/dilithium3/m4fstack/pointwise_mont.h delete mode 120000 crypto_sign/dilithium3/m4fstack/pointwise_mont.s delete mode 120000 crypto_sign/dilithium3/m4fstack/poly.c delete mode 120000 crypto_sign/dilithium3/m4fstack/poly.h delete mode 120000 crypto_sign/dilithium3/m4fstack/polyvec.c delete mode 120000 crypto_sign/dilithium3/m4fstack/polyvec.h delete mode 120000 crypto_sign/dilithium3/m4fstack/reduce.h delete mode 120000 crypto_sign/dilithium3/m4fstack/rounding.c delete mode 120000 crypto_sign/dilithium3/m4fstack/rounding.h delete mode 120000 crypto_sign/dilithium3/m4fstack/sign.c delete mode 120000 crypto_sign/dilithium3/m4fstack/sign.h delete mode 120000 crypto_sign/dilithium3/m4fstack/smallntt.h delete mode 120000 crypto_sign/dilithium3/m4fstack/smallntt_769.S delete mode 120000 crypto_sign/dilithium3/m4fstack/smallpoly.c delete mode 120000 crypto_sign/dilithium3/m4fstack/smallpoly.h delete mode 120000 crypto_sign/dilithium3/m4fstack/stack.c delete mode 120000 crypto_sign/dilithium3/m4fstack/stack.h delete mode 120000 crypto_sign/dilithium3/m4fstack/symmetric-shake.c delete mode 120000 crypto_sign/dilithium3/m4fstack/symmetric.h delete mode 120000 crypto_sign/dilithium3/m4fstack/vector.h delete mode 120000 crypto_sign/dilithium3/m4fstack/vector.s delete mode 120000 crypto_sign/dilithium5/m4f/api.h delete mode 120000 crypto_sign/dilithium5/m4f/basemul_257.S delete mode 120000 crypto_sign/dilithium5/m4f/fnt_257.S delete mode 120000 crypto_sign/dilithium5/m4f/ifnt_257.S delete mode 120000 crypto_sign/dilithium5/m4f/macros.i delete mode 120000 crypto_sign/dilithium5/m4f/macros_fnt.i delete mode 120000 crypto_sign/dilithium5/m4f/ntt.S delete mode 120000 crypto_sign/dilithium5/m4f/ntt.h delete mode 120000 crypto_sign/dilithium5/m4f/packing.c delete mode 120000 crypto_sign/dilithium5/m4f/packing.h delete mode 120000 crypto_sign/dilithium5/m4f/params.h delete mode 120000 crypto_sign/dilithium5/m4f/pointwise_mont.h delete mode 120000 crypto_sign/dilithium5/m4f/pointwise_mont.s delete mode 120000 crypto_sign/dilithium5/m4f/poly.c delete mode 120000 crypto_sign/dilithium5/m4f/poly.h delete mode 120000 crypto_sign/dilithium5/m4f/polyvec.c delete mode 120000 crypto_sign/dilithium5/m4f/polyvec.h delete mode 120000 crypto_sign/dilithium5/m4f/reduce.h delete mode 120000 crypto_sign/dilithium5/m4f/rounding.c delete mode 120000 crypto_sign/dilithium5/m4f/rounding.h delete mode 120000 crypto_sign/dilithium5/m4f/sign.c delete mode 120000 crypto_sign/dilithium5/m4f/sign.h delete mode 120000 crypto_sign/dilithium5/m4f/smallntt.h delete mode 120000 crypto_sign/dilithium5/m4f/smallpoly.c delete mode 120000 crypto_sign/dilithium5/m4f/smallpoly.h delete mode 120000 crypto_sign/dilithium5/m4f/symmetric-shake.c delete mode 120000 crypto_sign/dilithium5/m4f/symmetric.h delete mode 120000 crypto_sign/dilithium5/m4f/vector.h delete mode 120000 crypto_sign/dilithium5/m4f/vector.s delete mode 120000 crypto_sign/dilithium5/m4fstack/api.h delete mode 120000 crypto_sign/dilithium5/m4fstack/macros.i delete mode 120000 crypto_sign/dilithium5/m4fstack/macros_smallntt.i delete mode 120000 crypto_sign/dilithium5/m4fstack/ntt.S delete mode 120000 crypto_sign/dilithium5/m4fstack/ntt.h delete mode 120000 crypto_sign/dilithium5/m4fstack/packing.c delete mode 120000 crypto_sign/dilithium5/m4fstack/packing.h delete mode 120000 crypto_sign/dilithium5/m4fstack/params.h delete mode 120000 crypto_sign/dilithium5/m4fstack/pointwise_mont.h delete mode 120000 crypto_sign/dilithium5/m4fstack/pointwise_mont.s delete mode 120000 crypto_sign/dilithium5/m4fstack/poly.c delete mode 120000 crypto_sign/dilithium5/m4fstack/poly.h delete mode 120000 crypto_sign/dilithium5/m4fstack/polyvec.c delete mode 120000 crypto_sign/dilithium5/m4fstack/polyvec.h delete mode 120000 crypto_sign/dilithium5/m4fstack/reduce.h delete mode 120000 crypto_sign/dilithium5/m4fstack/rounding.c delete mode 120000 crypto_sign/dilithium5/m4fstack/rounding.h delete mode 120000 crypto_sign/dilithium5/m4fstack/sign.c delete mode 120000 crypto_sign/dilithium5/m4fstack/sign.h delete mode 120000 crypto_sign/dilithium5/m4fstack/smallntt.h delete mode 120000 crypto_sign/dilithium5/m4fstack/smallntt_769.S delete mode 120000 crypto_sign/dilithium5/m4fstack/smallpoly.c delete mode 120000 crypto_sign/dilithium5/m4fstack/smallpoly.h delete mode 120000 crypto_sign/dilithium5/m4fstack/stack.c delete mode 120000 crypto_sign/dilithium5/m4fstack/stack.h delete mode 120000 crypto_sign/dilithium5/m4fstack/symmetric-shake.c delete mode 120000 crypto_sign/dilithium5/m4fstack/symmetric.h delete mode 120000 crypto_sign/dilithium5/m4fstack/vector.h delete mode 120000 crypto_sign/dilithium5/m4fstack/vector.s create mode 100644 crypto_sign/ml-dsa-44/m4f/api.h rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/basemul_257.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/config.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/fnt_257.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/ifnt_257.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/macros.i (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/macros_fnt.i (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/ntt.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/ntt.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/packing.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/packing.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/params.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/pointwise_mont.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/pointwise_mont.s (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/poly.c (98%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/poly.h (95%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/polyvec.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/polyvec.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/reduce.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/rounding.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/rounding.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/sign.c (82%) create mode 100644 crypto_sign/ml-dsa-44/m4f/sign.h rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/smallntt.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/smallpoly.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/smallpoly.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/symmetric-shake.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/symmetric.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/vector.h (89%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4f/vector.s (80%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/api.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/config.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/macros.i (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/macros_smallntt.i (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/ntt.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/ntt.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/packing.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/packing.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/params.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/pointwise_mont.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/pointwise_mont.s (100%) create mode 120000 crypto_sign/ml-dsa-44/m4fstack/poly.c create mode 120000 crypto_sign/ml-dsa-44/m4fstack/poly.h rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/polyvec.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/polyvec.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/reduce.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/rounding.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/rounding.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/sign.c (84%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/sign.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/smallntt.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/smallntt_769.S (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/smallpoly.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/smallpoly.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/stack.c (97%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/stack.h (91%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/symmetric-shake.c (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/symmetric.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/vector.h (100%) rename crypto_sign/{dilithium2 => ml-dsa-44}/m4fstack/vector.s (100%) create mode 120000 crypto_sign/ml-dsa-65/m4f/api.h rename crypto_sign/{dilithium3 => ml-dsa-65}/m4f/config.h (100%) create mode 120000 crypto_sign/ml-dsa-65/m4f/macros.i rename crypto_sign/{dilithium3 => ml-dsa-65}/m4f/macros_smallntt.i (100%) create mode 120000 crypto_sign/ml-dsa-65/m4f/ntt.S create mode 120000 crypto_sign/ml-dsa-65/m4f/ntt.h create mode 120000 crypto_sign/ml-dsa-65/m4f/packing.c create mode 120000 crypto_sign/ml-dsa-65/m4f/packing.h create mode 120000 crypto_sign/ml-dsa-65/m4f/params.h create mode 120000 crypto_sign/ml-dsa-65/m4f/pointwise_mont.h create mode 120000 crypto_sign/ml-dsa-65/m4f/pointwise_mont.s create mode 120000 crypto_sign/ml-dsa-65/m4f/poly.c create mode 120000 crypto_sign/ml-dsa-65/m4f/poly.h create mode 120000 crypto_sign/ml-dsa-65/m4f/polyvec.c create mode 120000 crypto_sign/ml-dsa-65/m4f/polyvec.h create mode 120000 crypto_sign/ml-dsa-65/m4f/reduce.h create mode 120000 crypto_sign/ml-dsa-65/m4f/rounding.c create mode 120000 crypto_sign/ml-dsa-65/m4f/rounding.h create mode 120000 crypto_sign/ml-dsa-65/m4f/sign.c create mode 120000 crypto_sign/ml-dsa-65/m4f/sign.h rename crypto_sign/{dilithium3 => ml-dsa-65}/m4f/smallntt.h (100%) rename crypto_sign/{dilithium3 => ml-dsa-65}/m4f/smallntt_769.S (100%) create mode 120000 crypto_sign/ml-dsa-65/m4f/smallpoly.c create mode 120000 crypto_sign/ml-dsa-65/m4f/smallpoly.h create mode 120000 crypto_sign/ml-dsa-65/m4f/symmetric-shake.c create mode 120000 crypto_sign/ml-dsa-65/m4f/symmetric.h create mode 120000 crypto_sign/ml-dsa-65/m4f/vector.h create mode 120000 crypto_sign/ml-dsa-65/m4f/vector.s create mode 120000 crypto_sign/ml-dsa-65/m4fstack/api.h rename crypto_sign/{dilithium3 => ml-dsa-65}/m4fstack/config.h (100%) create mode 120000 crypto_sign/ml-dsa-65/m4fstack/macros.i create mode 120000 crypto_sign/ml-dsa-65/m4fstack/macros_smallntt.i create mode 120000 crypto_sign/ml-dsa-65/m4fstack/ntt.S create mode 120000 crypto_sign/ml-dsa-65/m4fstack/ntt.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/packing.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/packing.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/params.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.s create mode 120000 crypto_sign/ml-dsa-65/m4fstack/poly.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/poly.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/polyvec.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/polyvec.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/reduce.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/rounding.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/rounding.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/sign.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/sign.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/smallntt.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/smallntt_769.S create mode 120000 crypto_sign/ml-dsa-65/m4fstack/smallpoly.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/smallpoly.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/smalltt.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/stack.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/stack.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/symmetric-shake.c create mode 120000 crypto_sign/ml-dsa-65/m4fstack/symmetric.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/vector.h create mode 120000 crypto_sign/ml-dsa-65/m4fstack/vector.s create mode 120000 crypto_sign/ml-dsa-87/m4f/api.h create mode 120000 crypto_sign/ml-dsa-87/m4f/basemul_257.S rename crypto_sign/{dilithium5 => ml-dsa-87}/m4f/config.h (100%) create mode 120000 crypto_sign/ml-dsa-87/m4f/fnt_257.S create mode 120000 crypto_sign/ml-dsa-87/m4f/ifnt_257.S create mode 120000 crypto_sign/ml-dsa-87/m4f/macros.i create mode 120000 crypto_sign/ml-dsa-87/m4f/macros_fnt.i create mode 120000 crypto_sign/ml-dsa-87/m4f/ntt.S create mode 120000 crypto_sign/ml-dsa-87/m4f/ntt.h create mode 120000 crypto_sign/ml-dsa-87/m4f/packing.c create mode 120000 crypto_sign/ml-dsa-87/m4f/packing.h create mode 120000 crypto_sign/ml-dsa-87/m4f/params.h create mode 120000 crypto_sign/ml-dsa-87/m4f/pointwise_mont.h create mode 120000 crypto_sign/ml-dsa-87/m4f/pointwise_mont.s create mode 120000 crypto_sign/ml-dsa-87/m4f/poly.c create mode 120000 crypto_sign/ml-dsa-87/m4f/poly.h create mode 120000 crypto_sign/ml-dsa-87/m4f/polyvec.c create mode 120000 crypto_sign/ml-dsa-87/m4f/polyvec.h create mode 120000 crypto_sign/ml-dsa-87/m4f/reduce.h create mode 120000 crypto_sign/ml-dsa-87/m4f/rounding.c create mode 120000 crypto_sign/ml-dsa-87/m4f/rounding.h create mode 120000 crypto_sign/ml-dsa-87/m4f/sign.c create mode 120000 crypto_sign/ml-dsa-87/m4f/sign.h create mode 120000 crypto_sign/ml-dsa-87/m4f/smallntt.h create mode 120000 crypto_sign/ml-dsa-87/m4f/smallpoly.c create mode 120000 crypto_sign/ml-dsa-87/m4f/smallpoly.h create mode 120000 crypto_sign/ml-dsa-87/m4f/symmetric-shake.c create mode 120000 crypto_sign/ml-dsa-87/m4f/symmetric.h create mode 120000 crypto_sign/ml-dsa-87/m4f/vector.h create mode 120000 crypto_sign/ml-dsa-87/m4f/vector.s create mode 120000 crypto_sign/ml-dsa-87/m4fstack/api.h rename crypto_sign/{dilithium5 => ml-dsa-87}/m4fstack/config.h (100%) create mode 120000 crypto_sign/ml-dsa-87/m4fstack/macros.i create mode 120000 crypto_sign/ml-dsa-87/m4fstack/macros_smallntt.i create mode 120000 crypto_sign/ml-dsa-87/m4fstack/ntt.S create mode 120000 crypto_sign/ml-dsa-87/m4fstack/ntt.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/packing.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/packing.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/params.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.s create mode 120000 crypto_sign/ml-dsa-87/m4fstack/poly.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/poly.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/polyvec.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/polyvec.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/reduce.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/rounding.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/rounding.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/sign.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/sign.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/smallntt.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/smallntt_769.S create mode 120000 crypto_sign/ml-dsa-87/m4fstack/smallpoly.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/smallpoly.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/stack.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/stack.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/symmetric-shake.c create mode 120000 crypto_sign/ml-dsa-87/m4fstack/symmetric.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/vector.h create mode 120000 crypto_sign/ml-dsa-87/m4fstack/vector.s diff --git a/benchmarks.csv b/benchmarks.csv index 0fda9e5b..77b1d42f 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -51,15 +51,6 @@ cross-sha3-r-sdpg-1-fast (10 executions),ref,290136,287742,297758,29963868,29960 cross-sha3-r-sdpg-1-small (10 executions),ref,290135,287741,297757,102853622,102847774,102861948,75137510,75126803,75159685 cross-sha3-r-sdpg-3-fast (10 executions),ref,627948,625525,637639,43573841,43565461,43582933,27513830,27493024,27525746 cross-sha3-r-sdpg-5-fast (10 executions),ref,1146280,1142409,1153794,93557878,93547167,93566329,59948216,59857434,60043852 -dilithium2 (1000 executions),clean,1874167,1827645,1914566,7493877,3321630,40762756,2062795,2062255,2063222 -dilithium2 (1000 executions),m4f,1425723,1379410,1466445,3835095,1813682,16068642,1421307,1420219,1422056 -dilithium2 (1000 executions),m4fstack,1801523,1684895,1902114,12170976,3900911,86281518,3241353,3194028,3281144 -dilithium3 (1000 executions),clean,3205551,3204090,3207411,12696585,5097364,74392293,3376992,3376581,3377393 -dilithium3 (1000 executions),m4f,2515915,2514307,2517413,6054094,2917316,27829552,2415526,2414696,2416440 -dilithium3 (1000 executions),m4fstack,3412759,3406659,3419247,23673016,6733971,145803146,5733307,5688893,5778120 -dilithium5 (1000 executions),clean,5341477,5286872,5395822,15710371,7953367,75940093,5609679,5609217,5610183 -dilithium5 (1000 executions),m4f,4275033,4220989,4350945,8349360,4882552,29688762,4192692,4191427,4193764 -dilithium5 (1000 executions),m4fstack,5816287,5474236,6115061,33452872,11170780,185259803,9912851,9845789,9981834 falcon-1024 (10 executions),clean,602066436,377135260,1488065363,136241759,136017549,136556585,1678109,1677732,1678566 falcon-1024 (10 executions),m4-ct,408725773,314885208,712370124,87706019,87549942,87839508,990541,984448,997160 falcon-1024 (10 executions),opt-ct,448194494,301446952,784390745,87699336,87550679,87857833,992822,983184,998271 @@ -109,6 +100,15 @@ mirith_hypercube_Ib_fast (10 executions),ref,2514929,2514917,2514959,205510181,2 mirith_hypercube_Ib_short (10 executions),ref,2514920,2514920,2514923,447351952,447351902,447351992,440279587,440278101,440281382 mirith_hypercube_Va_fast (10 executions),ref,6254896,6254886,6254922,808070687,808007911,808157180,792058628,792006360,792098565 mirith_hypercube_Vb_fast (10 executions),ref,8807565,8807542,8807583,1134272446,1134201632,1134368110,1117085816,1117059819,1117104354 +ml-dsa-44 (1000 executions),clean,1874405,1827873,1914904,7925955,3322507,33055004,2063096,2062599,2063590 +ml-dsa-44 (1000 executions),m4f,1425492,1379560,1466364,3822701,1814511,22969466,1421600,1420736,1422318 +ml-dsa-44 (1000 executions),m4fstack,1799062,1685053,1902006,12134284,3901973,65357843,3242333,3199001,3279836 +ml-dsa-65 (1000 executions),clean,3205533,3204116,3206864,12359056,5098254,70122163,3377305,3376896,3377714 +ml-dsa-65 (1000 executions),m4f,2516006,2514337,2517453,6193171,2918295,26008621,2415944,2415109,2416730 +ml-dsa-65 (1000 executions),m4fstack,3412622,3406495,3418945,24421526,6735243,164688347,5732397,5688990,5783258 +ml-dsa-87 (1000 executions),clean,5341863,5276084,5406569,15579513,7954385,82615659,5610203,5609675,5610695 +ml-dsa-87 (1000 executions),m4f,4274513,4210044,4340431,8204023,4883484,29488880,4193228,4192029,4194357 +ml-dsa-87 (1000 executions),m4fstack,5820537,5484663,6113363,33357899,11168408,170850278,9911514,9852116,9969829 mqom_cat1_gf251_fast (10 executions),ref,7780082,7761398,7795766,149063790,149045955,149079787,136742778,136613266,136821602 mqom_cat1_gf31_fast (10 executions),ref,8472628,8471619,8473585,243796920,243782136,243811088,244346110,244239828,244424317 ov-Ip (10 executions),m4f,139186121,139186115,139186154,2465106,2465096,2465133,993538,979943,997098 @@ -211,15 +211,6 @@ cross-sha3-r-sdpg-1-fast,ref,2328,130928,69560,,,,,, cross-sha3-r-sdpg-1-small,ref,2328,466400,245512,,,,,, cross-sha3-r-sdpg-3-fast,ref,4032,205080,108236,,,,,, cross-sha3-r-sdpg-5-fast,ref,6824,398600,213436,,,,,, -dilithium2,clean,38304,51968,36192,,,,,, -dilithium2,m4f,38296,49416,9012,,,,,, -dilithium2,m4fstack,4408,5072,2704,,,,,, -dilithium3,clean,60832,79616,57728,,,,,, -dilithium3,m4f,60824,68864,9880,,,,,, -dilithium3,m4fstack,4408,6608,2704,,,,,, -dilithium5,clean,97696,122724,92940,,,,,, -dilithium5,m4f,97688,116076,11944,,,,,, -dilithium5,m4fstack,4408,8136,2712,,,,,, falcon-1024,clean,35076,84604,8776,,,,,, falcon-1024,m4-ct,1156,2508,376,,,,,, falcon-1024,opt-ct,1204,2508,376,,,,,, @@ -269,6 +260,15 @@ mirith_hypercube_Ib_fast,ref,19064,96928,31316,,,,,, mirith_hypercube_Ib_short,ref,19064,237408,41220,,,,,, mirith_hypercube_Va_fast,ref,45000,308440,81056,,,,,, mirith_hypercube_Vb_fast,ref,62864,344832,101220,,,,,, +ml-dsa-44,clean,38304,51976,36308,,,,,, +ml-dsa-44,m4f,38296,49424,8912,,,,,, +ml-dsa-44,m4fstack,4408,5080,2712,,,,,, +ml-dsa-65,clean,60832,79624,57736,,,,,, +ml-dsa-65,m4f,60824,68872,9888,,,,,, +ml-dsa-65,m4fstack,4408,6616,2712,,,,,, +ml-dsa-87,clean,97696,122740,92948,,,,,, +ml-dsa-87,m4f,97688,116084,12060,,,,,, +ml-dsa-87,m4fstack,4408,8144,2720,,,,,, mqom_cat1_gf251_fast,ref,184356,399396,252684,,,,,, mqom_cat1_gf31_fast,ref,262888,612816,421596,,,,,, ov-Ip,m4f,15676,5216,2512,,,,,, @@ -372,15 +372,6 @@ cross-sha3-r-sdpg-1-fast,ref,71.8,74.8,77.1,,,,,, cross-sha3-r-sdpg-1-small,ref,71.8,74.7,78.4,,,,,, cross-sha3-r-sdpg-3-fast,ref,71.7,68.2,68.7,,,,,, cross-sha3-r-sdpg-5-fast,ref,71.1,66.1,66.8,,,,,, -dilithium2,clean,61.0,30.9,52.9,,,,,, -dilithium2,m4f,79.9,60.7,76.6,,,,,, -dilithium2,m4fstack,74.8,55.2,40.8,,,,,, -dilithium3,clean,64.7,31.3,56.8,,,,,, -dilithium3,m4f,82.3,60.7,79.2,,,,,, -dilithium3,m4fstack,77.1,54.6,41.0,,,,,, -dilithium5,clean,67.0,35.7,61.1,,,,,, -dilithium5,m4f,83.5,65.3,81.6,,,,,, -dilithium5,m4fstack,76.1,54.5,42.6,,,,,, falcon-1024,clean,8.9,0.3,23.7,,,,,, falcon-1024,m4-ct,8.6,0.4,32.2,,,,,, falcon-1024,opt-ct,9.8,0.4,32.2,,,,,, @@ -430,6 +421,15 @@ mirith_hypercube_Ib_fast,ref,61.2,18.7,17.0,,,,,, mirith_hypercube_Ib_short,ref,61.2,56.6,56.8,,,,,, mirith_hypercube_Va_fast,ref,64.8,13.4,12.3,,,,,, mirith_hypercube_Vb_fast,ref,64.5,11.0,10.1,,,,,, +ml-dsa-44,clean,61.0,31.0,52.9,,,,,, +ml-dsa-44,m4f,79.9,60.7,76.6,,,,,, +ml-dsa-44,m4fstack,74.9,54.8,40.8,,,,,, +ml-dsa-65,clean,64.7,31.2,56.8,,,,,, +ml-dsa-65,m4f,82.3,60.6,79.2,,,,,, +ml-dsa-65,m4fstack,77.1,54.2,41.0,,,,,, +ml-dsa-87,clean,67.0,35.9,61.1,,,,,, +ml-dsa-87,m4f,83.5,65.1,81.6,,,,,, +ml-dsa-87,m4fstack,76.1,54.0,42.6,,,,,, mqom_cat1_gf251_fast,ref,73.5,33.0,33.1,,,,,, mqom_cat1_gf31_fast,ref,64.6,19.8,19.2,,,,,, ov-Ip,m4f,7.5,0.9,1.1,,,,,, @@ -532,15 +532,6 @@ cross-sha3-r-sdpg-1-fast,ref,18605,0,208,18813,,,,, cross-sha3-r-sdpg-1-small,ref,18846,0,208,19054,,,,, cross-sha3-r-sdpg-3-fast,ref,19689,0,208,19897,,,,, cross-sha3-r-sdpg-5-fast,ref,18593,0,208,18801,,,,, -dilithium2,clean,8064,0,0,8064,,,,, -dilithium2,m4f,19180,0,0,19180,,,,, -dilithium2,m4fstack,24184,0,0,24184,,,,, -dilithium3,clean,7580,0,0,7580,,,,, -dilithium3,m4f,19188,0,0,19188,,,,, -dilithium3,m4fstack,23448,0,0,23448,,,,, -dilithium5,clean,7808,0,0,7808,,,,, -dilithium5,m4f,19096,0,0,19096,,,,, -dilithium5,m4fstack,23820,0,0,23820,,,,, falcon-1024,clean,82703,0,0,82703,,,,, falcon-1024,m4-ct,81825,0,79872,161697,,,,, falcon-1024,opt-ct,81825,0,79872,161697,,,,, @@ -590,6 +581,15 @@ mirith_hypercube_Ib_fast,ref,8820,256,0,9076,,,,, mirith_hypercube_Ib_short,ref,8825,256,0,9081,,,,, mirith_hypercube_Va_fast,ref,9140,256,0,9396,,,,, mirith_hypercube_Vb_fast,ref,9160,256,0,9416,,,,, +ml-dsa-44,clean,8212,0,0,8212,,,,, +ml-dsa-44,m4f,19324,0,0,19324,,,,, +ml-dsa-44,m4fstack,24844,0,0,24844,,,,, +ml-dsa-65,clean,7724,0,0,7724,,,,, +ml-dsa-65,m4f,19328,0,0,19328,,,,, +ml-dsa-65,m4fstack,24120,0,0,24120,,,,, +ml-dsa-87,clean,8036,0,0,8036,,,,, +ml-dsa-87,m4f,19232,0,0,19232,,,,, +ml-dsa-87,m4fstack,24516,0,0,24516,,,,, mqom_cat1_gf251_fast,ref,16865,0,0,16865,,,,, mqom_cat1_gf31_fast,ref,23718,0,0,23718,,,,, ov-Ip,m4f,118939,0,0,118939,,,,, diff --git a/benchmarks.md b/benchmarks.md index a7788590..c82aedd1 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -53,15 +53,6 @@ | cross-sha3-r-sdpg-1-small (10 executions) | ref | AVG: 290,135
MIN: 287,741
MAX: 297,757 | AVG: 102,853,622
MIN: 102,847,774
MAX: 102,861,948 | AVG: 75,137,510
MIN: 75,126,803
MAX: 75,159,685 | | cross-sha3-r-sdpg-3-fast (10 executions) | ref | AVG: 627,948
MIN: 625,525
MAX: 637,639 | AVG: 43,573,841
MIN: 43,565,461
MAX: 43,582,933 | AVG: 27,513,830
MIN: 27,493,024
MAX: 27,525,746 | | cross-sha3-r-sdpg-5-fast (10 executions) | ref | AVG: 1,146,280
MIN: 1,142,409
MAX: 1,153,794 | AVG: 93,557,878
MIN: 93,547,167
MAX: 93,566,329 | AVG: 59,948,216
MIN: 59,857,434
MAX: 60,043,852 | -| dilithium2 (1000 executions) | clean | AVG: 1,874,167
MIN: 1,827,645
MAX: 1,914,566 | AVG: 7,493,877
MIN: 3,321,630
MAX: 40,762,756 | AVG: 2,062,795
MIN: 2,062,255
MAX: 2,063,222 | -| dilithium2 (1000 executions) | m4f | AVG: 1,425,723
MIN: 1,379,410
MAX: 1,466,445 | AVG: 3,835,095
MIN: 1,813,682
MAX: 16,068,642 | AVG: 1,421,307
MIN: 1,420,219
MAX: 1,422,056 | -| dilithium2 (1000 executions) | m4fstack | AVG: 1,801,523
MIN: 1,684,895
MAX: 1,902,114 | AVG: 12,170,976
MIN: 3,900,911
MAX: 86,281,518 | AVG: 3,241,353
MIN: 3,194,028
MAX: 3,281,144 | -| dilithium3 (1000 executions) | clean | AVG: 3,205,551
MIN: 3,204,090
MAX: 3,207,411 | AVG: 12,696,585
MIN: 5,097,364
MAX: 74,392,293 | AVG: 3,376,992
MIN: 3,376,581
MAX: 3,377,393 | -| dilithium3 (1000 executions) | m4f | AVG: 2,515,915
MIN: 2,514,307
MAX: 2,517,413 | AVG: 6,054,094
MIN: 2,917,316
MAX: 27,829,552 | AVG: 2,415,526
MIN: 2,414,696
MAX: 2,416,440 | -| dilithium3 (1000 executions) | m4fstack | AVG: 3,412,759
MIN: 3,406,659
MAX: 3,419,247 | AVG: 23,673,016
MIN: 6,733,971
MAX: 145,803,146 | AVG: 5,733,307
MIN: 5,688,893
MAX: 5,778,120 | -| dilithium5 (1000 executions) | clean | AVG: 5,341,477
MIN: 5,286,872
MAX: 5,395,822 | AVG: 15,710,371
MIN: 7,953,367
MAX: 75,940,093 | AVG: 5,609,679
MIN: 5,609,217
MAX: 5,610,183 | -| dilithium5 (1000 executions) | m4f | AVG: 4,275,033
MIN: 4,220,989
MAX: 4,350,945 | AVG: 8,349,360
MIN: 4,882,552
MAX: 29,688,762 | AVG: 4,192,692
MIN: 4,191,427
MAX: 4,193,764 | -| dilithium5 (1000 executions) | m4fstack | AVG: 5,816,287
MIN: 5,474,236
MAX: 6,115,061 | AVG: 33,452,872
MIN: 11,170,780
MAX: 185,259,803 | AVG: 9,912,851
MIN: 9,845,789
MAX: 9,981,834 | | falcon-1024 (10 executions) | clean | AVG: 602,066,436
MIN: 377,135,260
MAX: 1,488,065,363 | AVG: 136,241,759
MIN: 136,017,549
MAX: 136,556,585 | AVG: 1,678,109
MIN: 1,677,732
MAX: 1,678,566 | | falcon-1024 (10 executions) | m4-ct | AVG: 408,725,773
MIN: 314,885,208
MAX: 712,370,124 | AVG: 87,706,019
MIN: 87,549,942
MAX: 87,839,508 | AVG: 990,541
MIN: 984,448
MAX: 997,160 | | falcon-1024 (10 executions) | opt-ct | AVG: 448,194,494
MIN: 301,446,952
MAX: 784,390,745 | AVG: 87,699,336
MIN: 87,550,679
MAX: 87,857,833 | AVG: 992,822
MIN: 983,184
MAX: 998,271 | @@ -111,6 +102,15 @@ | mirith_hypercube_Ib_short (10 executions) | ref | AVG: 2,514,920
MIN: 2,514,920
MAX: 2,514,923 | AVG: 447,351,952
MIN: 447,351,902
MAX: 447,351,992 | AVG: 440,279,587
MIN: 440,278,101
MAX: 440,281,382 | | mirith_hypercube_Va_fast (10 executions) | ref | AVG: 6,254,896
MIN: 6,254,886
MAX: 6,254,922 | AVG: 808,070,687
MIN: 808,007,911
MAX: 808,157,180 | AVG: 792,058,628
MIN: 792,006,360
MAX: 792,098,565 | | mirith_hypercube_Vb_fast (10 executions) | ref | AVG: 8,807,565
MIN: 8,807,542
MAX: 8,807,583 | AVG: 1,134,272,446
MIN: 1,134,201,632
MAX: 1,134,368,110 | AVG: 1,117,085,816
MIN: 1,117,059,819
MAX: 1,117,104,354 | +| ml-dsa-44 (1000 executions) | clean | AVG: 1,874,405
MIN: 1,827,873
MAX: 1,914,904 | AVG: 7,925,955
MIN: 3,322,507
MAX: 33,055,004 | AVG: 2,063,096
MIN: 2,062,599
MAX: 2,063,590 | +| ml-dsa-44 (1000 executions) | m4f | AVG: 1,425,492
MIN: 1,379,560
MAX: 1,466,364 | AVG: 3,822,701
MIN: 1,814,511
MAX: 22,969,466 | AVG: 1,421,600
MIN: 1,420,736
MAX: 1,422,318 | +| ml-dsa-44 (1000 executions) | m4fstack | AVG: 1,799,062
MIN: 1,685,053
MAX: 1,902,006 | AVG: 12,134,284
MIN: 3,901,973
MAX: 65,357,843 | AVG: 3,242,333
MIN: 3,199,001
MAX: 3,279,836 | +| ml-dsa-65 (1000 executions) | clean | AVG: 3,205,533
MIN: 3,204,116
MAX: 3,206,864 | AVG: 12,359,056
MIN: 5,098,254
MAX: 70,122,163 | AVG: 3,377,305
MIN: 3,376,896
MAX: 3,377,714 | +| ml-dsa-65 (1000 executions) | m4f | AVG: 2,516,006
MIN: 2,514,337
MAX: 2,517,453 | AVG: 6,193,171
MIN: 2,918,295
MAX: 26,008,621 | AVG: 2,415,944
MIN: 2,415,109
MAX: 2,416,730 | +| ml-dsa-65 (1000 executions) | m4fstack | AVG: 3,412,622
MIN: 3,406,495
MAX: 3,418,945 | AVG: 24,421,526
MIN: 6,735,243
MAX: 164,688,347 | AVG: 5,732,397
MIN: 5,688,990
MAX: 5,783,258 | +| ml-dsa-87 (1000 executions) | clean | AVG: 5,341,863
MIN: 5,276,084
MAX: 5,406,569 | AVG: 15,579,513
MIN: 7,954,385
MAX: 82,615,659 | AVG: 5,610,203
MIN: 5,609,675
MAX: 5,610,695 | +| ml-dsa-87 (1000 executions) | m4f | AVG: 4,274,513
MIN: 4,210,044
MAX: 4,340,431 | AVG: 8,204,023
MIN: 4,883,484
MAX: 29,488,880 | AVG: 4,193,228
MIN: 4,192,029
MAX: 4,194,357 | +| ml-dsa-87 (1000 executions) | m4fstack | AVG: 5,820,537
MIN: 5,484,663
MAX: 6,113,363 | AVG: 33,357,899
MIN: 11,168,408
MAX: 170,850,278 | AVG: 9,911,514
MIN: 9,852,116
MAX: 9,969,829 | | mqom_cat1_gf251_fast (10 executions) | ref | AVG: 7,780,082
MIN: 7,761,398
MAX: 7,795,766 | AVG: 149,063,790
MIN: 149,045,955
MAX: 149,079,787 | AVG: 136,742,778
MIN: 136,613,266
MAX: 136,821,602 | | mqom_cat1_gf31_fast (10 executions) | ref | AVG: 8,472,628
MIN: 8,471,619
MAX: 8,473,585 | AVG: 243,796,920
MIN: 243,782,136
MAX: 243,811,088 | AVG: 244,346,110
MIN: 244,239,828
MAX: 244,424,317 | | ov-Ip (10 executions) | m4f | AVG: 139,186,121
MIN: 139,186,115
MAX: 139,186,154 | AVG: 2,465,106
MIN: 2,465,096
MAX: 2,465,133 | AVG: 993,538
MIN: 979,943
MAX: 997,098 | @@ -215,15 +215,6 @@ | cross-sha3-r-sdpg-1-small | ref | 2,328 | 466,400 | 245,512 | | cross-sha3-r-sdpg-3-fast | ref | 4,032 | 205,080 | 108,236 | | cross-sha3-r-sdpg-5-fast | ref | 6,824 | 398,600 | 213,436 | -| dilithium2 | clean | 38,304 | 51,968 | 36,192 | -| dilithium2 | m4f | 38,296 | 49,416 | 9,012 | -| dilithium2 | m4fstack | 4,408 | 5,072 | 2,704 | -| dilithium3 | clean | 60,832 | 79,616 | 57,728 | -| dilithium3 | m4f | 60,824 | 68,864 | 9,880 | -| dilithium3 | m4fstack | 4,408 | 6,608 | 2,704 | -| dilithium5 | clean | 97,696 | 122,724 | 92,940 | -| dilithium5 | m4f | 97,688 | 116,076 | 11,944 | -| dilithium5 | m4fstack | 4,408 | 8,136 | 2,712 | | falcon-1024 | clean | 35,076 | 84,604 | 8,776 | | falcon-1024 | m4-ct | 1,156 | 2,508 | 376 | | falcon-1024 | opt-ct | 1,204 | 2,508 | 376 | @@ -273,6 +264,15 @@ | mirith_hypercube_Ib_short | ref | 19,064 | 237,408 | 41,220 | | mirith_hypercube_Va_fast | ref | 45,000 | 308,440 | 81,056 | | mirith_hypercube_Vb_fast | ref | 62,864 | 344,832 | 101,220 | +| ml-dsa-44 | clean | 38,304 | 51,976 | 36,308 | +| ml-dsa-44 | m4f | 38,296 | 49,424 | 8,912 | +| ml-dsa-44 | m4fstack | 4,408 | 5,080 | 2,712 | +| ml-dsa-65 | clean | 60,832 | 79,624 | 57,736 | +| ml-dsa-65 | m4f | 60,824 | 68,872 | 9,888 | +| ml-dsa-65 | m4fstack | 4,408 | 6,616 | 2,712 | +| ml-dsa-87 | clean | 97,696 | 122,740 | 92,948 | +| ml-dsa-87 | m4f | 97,688 | 116,084 | 12,060 | +| ml-dsa-87 | m4fstack | 4,408 | 8,144 | 2,720 | | mqom_cat1_gf251_fast | ref | 184,356 | 399,396 | 252,684 | | mqom_cat1_gf31_fast | ref | 262,888 | 612,816 | 421,596 | | ov-Ip | m4f | 15,676 | 5,216 | 2,512 | @@ -378,15 +378,6 @@ | cross-sha3-r-sdpg-1-small | ref | 71.8% | 74.7% | 78.4% | | cross-sha3-r-sdpg-3-fast | ref | 71.7% | 68.2% | 68.7% | | cross-sha3-r-sdpg-5-fast | ref | 71.1% | 66.1% | 66.8% | -| dilithium2 | clean | 61.0% | 30.9% | 52.9% | -| dilithium2 | m4f | 79.9% | 60.7% | 76.6% | -| dilithium2 | m4fstack | 74.8% | 55.2% | 40.8% | -| dilithium3 | clean | 64.7% | 31.3% | 56.8% | -| dilithium3 | m4f | 82.3% | 60.7% | 79.2% | -| dilithium3 | m4fstack | 77.1% | 54.6% | 41.0% | -| dilithium5 | clean | 67.0% | 35.7% | 61.1% | -| dilithium5 | m4f | 83.5% | 65.3% | 81.6% | -| dilithium5 | m4fstack | 76.1% | 54.5% | 42.6% | | falcon-1024 | clean | 8.9% | 0.3% | 23.7% | | falcon-1024 | m4-ct | 8.6% | 0.4% | 32.2% | | falcon-1024 | opt-ct | 9.8% | 0.4% | 32.2% | @@ -436,6 +427,15 @@ | mirith_hypercube_Ib_short | ref | 61.2% | 56.6% | 56.8% | | mirith_hypercube_Va_fast | ref | 64.8% | 13.4% | 12.3% | | mirith_hypercube_Vb_fast | ref | 64.5% | 11.0% | 10.1% | +| ml-dsa-44 | clean | 61.0% | 31.0% | 52.9% | +| ml-dsa-44 | m4f | 79.9% | 60.7% | 76.6% | +| ml-dsa-44 | m4fstack | 74.9% | 54.8% | 40.8% | +| ml-dsa-65 | clean | 64.7% | 31.2% | 56.8% | +| ml-dsa-65 | m4f | 82.3% | 60.6% | 79.2% | +| ml-dsa-65 | m4fstack | 77.1% | 54.2% | 41.0% | +| ml-dsa-87 | clean | 67.0% | 35.9% | 61.1% | +| ml-dsa-87 | m4f | 83.5% | 65.1% | 81.6% | +| ml-dsa-87 | m4fstack | 76.1% | 54.0% | 42.6% | | mqom_cat1_gf251_fast | ref | 73.5% | 33.0% | 33.1% | | mqom_cat1_gf31_fast | ref | 64.6% | 19.8% | 19.2% | | ov-Ip | m4f | 7.5% | 0.9% | 1.1% | @@ -540,15 +540,6 @@ | cross-sha3-r-sdpg-1-small | ref | 18,846 | 0 | 208 | 19,054 | | cross-sha3-r-sdpg-3-fast | ref | 19,689 | 0 | 208 | 19,897 | | cross-sha3-r-sdpg-5-fast | ref | 18,593 | 0 | 208 | 18,801 | -| dilithium2 | clean | 8,064 | 0 | 0 | 8,064 | -| dilithium2 | m4f | 19,180 | 0 | 0 | 19,180 | -| dilithium2 | m4fstack | 24,184 | 0 | 0 | 24,184 | -| dilithium3 | clean | 7,580 | 0 | 0 | 7,580 | -| dilithium3 | m4f | 19,188 | 0 | 0 | 19,188 | -| dilithium3 | m4fstack | 23,448 | 0 | 0 | 23,448 | -| dilithium5 | clean | 7,808 | 0 | 0 | 7,808 | -| dilithium5 | m4f | 19,096 | 0 | 0 | 19,096 | -| dilithium5 | m4fstack | 23,820 | 0 | 0 | 23,820 | | falcon-1024 | clean | 82,703 | 0 | 0 | 82,703 | | falcon-1024 | m4-ct | 81,825 | 0 | 79,872 | 161,697 | | falcon-1024 | opt-ct | 81,825 | 0 | 79,872 | 161,697 | @@ -598,6 +589,15 @@ | mirith_hypercube_Ib_short | ref | 8,825 | 256 | 0 | 9,081 | | mirith_hypercube_Va_fast | ref | 9,140 | 256 | 0 | 9,396 | | mirith_hypercube_Vb_fast | ref | 9,160 | 256 | 0 | 9,416 | +| ml-dsa-44 | clean | 8,212 | 0 | 0 | 8,212 | +| ml-dsa-44 | m4f | 19,324 | 0 | 0 | 19,324 | +| ml-dsa-44 | m4fstack | 24,844 | 0 | 0 | 24,844 | +| ml-dsa-65 | clean | 7,724 | 0 | 0 | 7,724 | +| ml-dsa-65 | m4f | 19,328 | 0 | 0 | 19,328 | +| ml-dsa-65 | m4fstack | 24,120 | 0 | 0 | 24,120 | +| ml-dsa-87 | clean | 8,036 | 0 | 0 | 8,036 | +| ml-dsa-87 | m4f | 19,232 | 0 | 0 | 19,232 | +| ml-dsa-87 | m4fstack | 24,516 | 0 | 0 | 24,516 | | mqom_cat1_gf251_fast | ref | 16,865 | 0 | 0 | 16,865 | | mqom_cat1_gf31_fast | ref | 23,718 | 0 | 0 | 23,718 | | ov-Ip | m4f | 118,939 | 0 | 0 | 118,939 | diff --git a/crypto_sign/dilithium2/m4f/api.h b/crypto_sign/dilithium2/m4f/api.h deleted file mode 100644 index a289632c..00000000 --- a/crypto_sign/dilithium2/m4f/api.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef API_H -#define API_H - -#include -#include -#include "params.h" - -int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -int crypto_sign_signature(uint8_t *sig, size_t *siglen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -int crypto_sign(uint8_t *sm, size_t *smlen, - const uint8_t *m, size_t mlen, - const uint8_t *sk); - -int crypto_sign_verify(const uint8_t *sig, size_t siglen, - const uint8_t *m, size_t mlen, - const uint8_t *pk); - -int crypto_sign_open(uint8_t *m, size_t *mlen, - const uint8_t *sm, size_t smlen, - const uint8_t *pk); - -#endif diff --git a/crypto_sign/dilithium2/m4f/sign.h b/crypto_sign/dilithium2/m4f/sign.h deleted file mode 100644 index 42240b30..00000000 --- a/crypto_sign/dilithium2/m4f/sign.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef SIGN_H -#define SIGN_H - -#include -#include -#include "params.h" -#include "api.h" -#include "polyvec.h" -#include "poly.h" - -#define challenge DILITHIUM_NAMESPACE(challenge) -void challenge(poly *c, const uint8_t seed[SEEDBYTES]); - -// #define crypto_sign_keypair DILITHIUM_NAMESPACE(crypto_sign_keypair) -// int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); - -// #define crypto_sign_signature DILITHIUM_NAMESPACE(signature) -// int crypto_sign_signature(uint8_t *sig, size_t *siglen, -// const uint8_t *m, size_t mlen, -// const uint8_t *sk); - -// #define crypto_sign DILITHIUM_NAMESPACE(crypto_sign) -// int crypto_sign(uint8_t *sm, size_t *smlen, -// const uint8_t *m, size_t mlen, -// const uint8_t *sk); - -// #define crypto_sign_verify DILITHIUM_NAMESPACE(verify) -// int crypto_sign_verify(const uint8_t *sig, size_t siglen, -// const uint8_t *m, size_t mlen, -// const uint8_t *pk); - -// #define crypto_sign_open DILITHIUM_NAMESPACE(crypto_sign_open) -// int crypto_sign_open(uint8_t *m, size_t *mlen, -// const uint8_t *sm, size_t smlen, -// const uint8_t *pk); - -#endif diff --git a/crypto_sign/dilithium2/m4fstack/poly.c b/crypto_sign/dilithium2/m4fstack/poly.c deleted file mode 120000 index 2544e75b..00000000 --- a/crypto_sign/dilithium2/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/poly.h b/crypto_sign/dilithium2/m4fstack/poly.h deleted file mode 120000 index 7ef70e53..00000000 --- a/crypto_sign/dilithium2/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/api.h b/crypto_sign/dilithium3/m4f/api.h deleted file mode 120000 index 9d1668d8..00000000 --- a/crypto_sign/dilithium3/m4f/api.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/macros.i b/crypto_sign/dilithium3/m4f/macros.i deleted file mode 120000 index e3f2469a..00000000 --- a/crypto_sign/dilithium3/m4f/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/ntt.S b/crypto_sign/dilithium3/m4f/ntt.S deleted file mode 120000 index 6fbceff1..00000000 --- a/crypto_sign/dilithium3/m4f/ntt.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/ntt.h b/crypto_sign/dilithium3/m4f/ntt.h deleted file mode 120000 index 43729fef..00000000 --- a/crypto_sign/dilithium3/m4f/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/packing.c b/crypto_sign/dilithium3/m4f/packing.c deleted file mode 120000 index b41782c2..00000000 --- a/crypto_sign/dilithium3/m4f/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/packing.h b/crypto_sign/dilithium3/m4f/packing.h deleted file mode 120000 index ba1a6b3b..00000000 --- a/crypto_sign/dilithium3/m4f/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/params.h b/crypto_sign/dilithium3/m4f/params.h deleted file mode 120000 index a6a4d8b6..00000000 --- a/crypto_sign/dilithium3/m4f/params.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/pointwise_mont.h b/crypto_sign/dilithium3/m4f/pointwise_mont.h deleted file mode 120000 index 0a6f8b9f..00000000 --- a/crypto_sign/dilithium3/m4f/pointwise_mont.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/pointwise_mont.s b/crypto_sign/dilithium3/m4f/pointwise_mont.s deleted file mode 120000 index c4ddb96c..00000000 --- a/crypto_sign/dilithium3/m4f/pointwise_mont.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/poly.c b/crypto_sign/dilithium3/m4f/poly.c deleted file mode 120000 index 2544e75b..00000000 --- a/crypto_sign/dilithium3/m4f/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/poly.h b/crypto_sign/dilithium3/m4f/poly.h deleted file mode 120000 index 7ef70e53..00000000 --- a/crypto_sign/dilithium3/m4f/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/polyvec.c b/crypto_sign/dilithium3/m4f/polyvec.c deleted file mode 120000 index a8edd0d0..00000000 --- a/crypto_sign/dilithium3/m4f/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/polyvec.h b/crypto_sign/dilithium3/m4f/polyvec.h deleted file mode 120000 index cabd6a93..00000000 --- a/crypto_sign/dilithium3/m4f/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/reduce.h b/crypto_sign/dilithium3/m4f/reduce.h deleted file mode 120000 index 6c13df5f..00000000 --- a/crypto_sign/dilithium3/m4f/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/rounding.c b/crypto_sign/dilithium3/m4f/rounding.c deleted file mode 120000 index 80b8dce2..00000000 --- a/crypto_sign/dilithium3/m4f/rounding.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/rounding.h b/crypto_sign/dilithium3/m4f/rounding.h deleted file mode 120000 index 74c40c5e..00000000 --- a/crypto_sign/dilithium3/m4f/rounding.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/sign.c b/crypto_sign/dilithium3/m4f/sign.c deleted file mode 120000 index b7ccdf0b..00000000 --- a/crypto_sign/dilithium3/m4f/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/sign.h b/crypto_sign/dilithium3/m4f/sign.h deleted file mode 120000 index b7f1e89c..00000000 --- a/crypto_sign/dilithium3/m4f/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/smallpoly.c b/crypto_sign/dilithium3/m4f/smallpoly.c deleted file mode 120000 index b59f668a..00000000 --- a/crypto_sign/dilithium3/m4f/smallpoly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/smallpoly.h b/crypto_sign/dilithium3/m4f/smallpoly.h deleted file mode 120000 index 9d46a7a5..00000000 --- a/crypto_sign/dilithium3/m4f/smallpoly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/symmetric-shake.c b/crypto_sign/dilithium3/m4f/symmetric-shake.c deleted file mode 120000 index 6ad80541..00000000 --- a/crypto_sign/dilithium3/m4f/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/symmetric.h b/crypto_sign/dilithium3/m4f/symmetric.h deleted file mode 120000 index 90ad5c07..00000000 --- a/crypto_sign/dilithium3/m4f/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/vector.h b/crypto_sign/dilithium3/m4f/vector.h deleted file mode 120000 index 6e2280f0..00000000 --- a/crypto_sign/dilithium3/m4f/vector.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/vector.s b/crypto_sign/dilithium3/m4f/vector.s deleted file mode 120000 index 2d2b4dcf..00000000 --- a/crypto_sign/dilithium3/m4f/vector.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/api.h b/crypto_sign/dilithium3/m4fstack/api.h deleted file mode 120000 index 9d1668d8..00000000 --- a/crypto_sign/dilithium3/m4fstack/api.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/macros.i b/crypto_sign/dilithium3/m4fstack/macros.i deleted file mode 120000 index e3f2469a..00000000 --- a/crypto_sign/dilithium3/m4fstack/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i b/crypto_sign/dilithium3/m4fstack/macros_smallntt.i deleted file mode 120000 index 37838a21..00000000 --- a/crypto_sign/dilithium3/m4fstack/macros_smallntt.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/ntt.S b/crypto_sign/dilithium3/m4fstack/ntt.S deleted file mode 120000 index 6fbceff1..00000000 --- a/crypto_sign/dilithium3/m4fstack/ntt.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/ntt.h b/crypto_sign/dilithium3/m4fstack/ntt.h deleted file mode 120000 index 43729fef..00000000 --- a/crypto_sign/dilithium3/m4fstack/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.c b/crypto_sign/dilithium3/m4fstack/packing.c deleted file mode 120000 index b41782c2..00000000 --- a/crypto_sign/dilithium3/m4fstack/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/packing.h b/crypto_sign/dilithium3/m4fstack/packing.h deleted file mode 120000 index ba1a6b3b..00000000 --- a/crypto_sign/dilithium3/m4fstack/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/params.h b/crypto_sign/dilithium3/m4fstack/params.h deleted file mode 120000 index a6a4d8b6..00000000 --- a/crypto_sign/dilithium3/m4fstack/params.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h b/crypto_sign/dilithium3/m4fstack/pointwise_mont.h deleted file mode 120000 index 0a6f8b9f..00000000 --- a/crypto_sign/dilithium3/m4fstack/pointwise_mont.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s b/crypto_sign/dilithium3/m4fstack/pointwise_mont.s deleted file mode 120000 index c4ddb96c..00000000 --- a/crypto_sign/dilithium3/m4fstack/pointwise_mont.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/poly.c b/crypto_sign/dilithium3/m4fstack/poly.c deleted file mode 120000 index 2544e75b..00000000 --- a/crypto_sign/dilithium3/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/poly.h b/crypto_sign/dilithium3/m4fstack/poly.h deleted file mode 120000 index 7ef70e53..00000000 --- a/crypto_sign/dilithium3/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.c b/crypto_sign/dilithium3/m4fstack/polyvec.c deleted file mode 120000 index a8edd0d0..00000000 --- a/crypto_sign/dilithium3/m4fstack/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/polyvec.h b/crypto_sign/dilithium3/m4fstack/polyvec.h deleted file mode 120000 index cabd6a93..00000000 --- a/crypto_sign/dilithium3/m4fstack/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/reduce.h b/crypto_sign/dilithium3/m4fstack/reduce.h deleted file mode 120000 index f1e2b389..00000000 --- a/crypto_sign/dilithium3/m4fstack/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/rounding.c b/crypto_sign/dilithium3/m4fstack/rounding.c deleted file mode 120000 index 80b8dce2..00000000 --- a/crypto_sign/dilithium3/m4fstack/rounding.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/rounding.h b/crypto_sign/dilithium3/m4fstack/rounding.h deleted file mode 120000 index 74c40c5e..00000000 --- a/crypto_sign/dilithium3/m4fstack/rounding.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/sign.c b/crypto_sign/dilithium3/m4fstack/sign.c deleted file mode 120000 index 39f6ec48..00000000 --- a/crypto_sign/dilithium3/m4fstack/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/sign.h b/crypto_sign/dilithium3/m4fstack/sign.h deleted file mode 120000 index b7f1e89c..00000000 --- a/crypto_sign/dilithium3/m4fstack/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallntt.h b/crypto_sign/dilithium3/m4fstack/smallntt.h deleted file mode 120000 index 60f2d18a..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallntt_769.S b/crypto_sign/dilithium3/m4fstack/smallntt_769.S deleted file mode 120000 index 4ae2f9bb..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallntt_769.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.c b/crypto_sign/dilithium3/m4fstack/smallpoly.c deleted file mode 120000 index 9c350567..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallpoly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/smallpoly.h b/crypto_sign/dilithium3/m4fstack/smallpoly.h deleted file mode 120000 index 45701a42..00000000 --- a/crypto_sign/dilithium3/m4fstack/smallpoly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.c b/crypto_sign/dilithium3/m4fstack/stack.c deleted file mode 120000 index d25ed6f7..00000000 --- a/crypto_sign/dilithium3/m4fstack/stack.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/stack.h b/crypto_sign/dilithium3/m4fstack/stack.h deleted file mode 120000 index beab8ca2..00000000 --- a/crypto_sign/dilithium3/m4fstack/stack.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c b/crypto_sign/dilithium3/m4fstack/symmetric-shake.c deleted file mode 120000 index 6ad80541..00000000 --- a/crypto_sign/dilithium3/m4fstack/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/symmetric.h b/crypto_sign/dilithium3/m4fstack/symmetric.h deleted file mode 120000 index 90ad5c07..00000000 --- a/crypto_sign/dilithium3/m4fstack/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/vector.h b/crypto_sign/dilithium3/m4fstack/vector.h deleted file mode 120000 index 6e2280f0..00000000 --- a/crypto_sign/dilithium3/m4fstack/vector.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/vector.s b/crypto_sign/dilithium3/m4fstack/vector.s deleted file mode 120000 index 2d2b4dcf..00000000 --- a/crypto_sign/dilithium3/m4fstack/vector.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/api.h b/crypto_sign/dilithium5/m4f/api.h deleted file mode 120000 index 9d1668d8..00000000 --- a/crypto_sign/dilithium5/m4f/api.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/basemul_257.S b/crypto_sign/dilithium5/m4f/basemul_257.S deleted file mode 120000 index 800dbb53..00000000 --- a/crypto_sign/dilithium5/m4f/basemul_257.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/basemul_257.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/fnt_257.S b/crypto_sign/dilithium5/m4f/fnt_257.S deleted file mode 120000 index 2a616c62..00000000 --- a/crypto_sign/dilithium5/m4f/fnt_257.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/fnt_257.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/ifnt_257.S b/crypto_sign/dilithium5/m4f/ifnt_257.S deleted file mode 120000 index 65c99ba9..00000000 --- a/crypto_sign/dilithium5/m4f/ifnt_257.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ifnt_257.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/macros.i b/crypto_sign/dilithium5/m4f/macros.i deleted file mode 120000 index e3f2469a..00000000 --- a/crypto_sign/dilithium5/m4f/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/macros_fnt.i b/crypto_sign/dilithium5/m4f/macros_fnt.i deleted file mode 120000 index 1abff093..00000000 --- a/crypto_sign/dilithium5/m4f/macros_fnt.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros_fnt.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/ntt.S b/crypto_sign/dilithium5/m4f/ntt.S deleted file mode 120000 index 6fbceff1..00000000 --- a/crypto_sign/dilithium5/m4f/ntt.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/ntt.h b/crypto_sign/dilithium5/m4f/ntt.h deleted file mode 120000 index 43729fef..00000000 --- a/crypto_sign/dilithium5/m4f/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/packing.c b/crypto_sign/dilithium5/m4f/packing.c deleted file mode 120000 index b41782c2..00000000 --- a/crypto_sign/dilithium5/m4f/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/packing.h b/crypto_sign/dilithium5/m4f/packing.h deleted file mode 120000 index ba1a6b3b..00000000 --- a/crypto_sign/dilithium5/m4f/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/params.h b/crypto_sign/dilithium5/m4f/params.h deleted file mode 120000 index a6a4d8b6..00000000 --- a/crypto_sign/dilithium5/m4f/params.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/pointwise_mont.h b/crypto_sign/dilithium5/m4f/pointwise_mont.h deleted file mode 120000 index 0a6f8b9f..00000000 --- a/crypto_sign/dilithium5/m4f/pointwise_mont.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/pointwise_mont.s b/crypto_sign/dilithium5/m4f/pointwise_mont.s deleted file mode 120000 index c4ddb96c..00000000 --- a/crypto_sign/dilithium5/m4f/pointwise_mont.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/poly.c b/crypto_sign/dilithium5/m4f/poly.c deleted file mode 120000 index 2544e75b..00000000 --- a/crypto_sign/dilithium5/m4f/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/poly.h b/crypto_sign/dilithium5/m4f/poly.h deleted file mode 120000 index 7ef70e53..00000000 --- a/crypto_sign/dilithium5/m4f/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/polyvec.c b/crypto_sign/dilithium5/m4f/polyvec.c deleted file mode 120000 index a8edd0d0..00000000 --- a/crypto_sign/dilithium5/m4f/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/polyvec.h b/crypto_sign/dilithium5/m4f/polyvec.h deleted file mode 120000 index cabd6a93..00000000 --- a/crypto_sign/dilithium5/m4f/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/reduce.h b/crypto_sign/dilithium5/m4f/reduce.h deleted file mode 120000 index 6c13df5f..00000000 --- a/crypto_sign/dilithium5/m4f/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/rounding.c b/crypto_sign/dilithium5/m4f/rounding.c deleted file mode 120000 index 80b8dce2..00000000 --- a/crypto_sign/dilithium5/m4f/rounding.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/rounding.h b/crypto_sign/dilithium5/m4f/rounding.h deleted file mode 120000 index 74c40c5e..00000000 --- a/crypto_sign/dilithium5/m4f/rounding.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/sign.c b/crypto_sign/dilithium5/m4f/sign.c deleted file mode 120000 index b7ccdf0b..00000000 --- a/crypto_sign/dilithium5/m4f/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/sign.h b/crypto_sign/dilithium5/m4f/sign.h deleted file mode 120000 index b7f1e89c..00000000 --- a/crypto_sign/dilithium5/m4f/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/smallntt.h b/crypto_sign/dilithium5/m4f/smallntt.h deleted file mode 120000 index 9b2baf47..00000000 --- a/crypto_sign/dilithium5/m4f/smallntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/smallpoly.c b/crypto_sign/dilithium5/m4f/smallpoly.c deleted file mode 120000 index b59f668a..00000000 --- a/crypto_sign/dilithium5/m4f/smallpoly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/smallpoly.h b/crypto_sign/dilithium5/m4f/smallpoly.h deleted file mode 120000 index 9d46a7a5..00000000 --- a/crypto_sign/dilithium5/m4f/smallpoly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/symmetric-shake.c b/crypto_sign/dilithium5/m4f/symmetric-shake.c deleted file mode 120000 index 6ad80541..00000000 --- a/crypto_sign/dilithium5/m4f/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/symmetric.h b/crypto_sign/dilithium5/m4f/symmetric.h deleted file mode 120000 index 90ad5c07..00000000 --- a/crypto_sign/dilithium5/m4f/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/vector.h b/crypto_sign/dilithium5/m4f/vector.h deleted file mode 120000 index 6e2280f0..00000000 --- a/crypto_sign/dilithium5/m4f/vector.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/vector.s b/crypto_sign/dilithium5/m4f/vector.s deleted file mode 120000 index 2d2b4dcf..00000000 --- a/crypto_sign/dilithium5/m4f/vector.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/api.h b/crypto_sign/dilithium5/m4fstack/api.h deleted file mode 120000 index 9d1668d8..00000000 --- a/crypto_sign/dilithium5/m4fstack/api.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros.i b/crypto_sign/dilithium5/m4fstack/macros.i deleted file mode 120000 index e3f2469a..00000000 --- a/crypto_sign/dilithium5/m4fstack/macros.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/macros_smallntt.i b/crypto_sign/dilithium5/m4fstack/macros_smallntt.i deleted file mode 120000 index 37838a21..00000000 --- a/crypto_sign/dilithium5/m4fstack/macros_smallntt.i +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.S b/crypto_sign/dilithium5/m4fstack/ntt.S deleted file mode 120000 index 6fbceff1..00000000 --- a/crypto_sign/dilithium5/m4fstack/ntt.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/ntt.h b/crypto_sign/dilithium5/m4fstack/ntt.h deleted file mode 120000 index 43729fef..00000000 --- a/crypto_sign/dilithium5/m4fstack/ntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.c b/crypto_sign/dilithium5/m4fstack/packing.c deleted file mode 120000 index b41782c2..00000000 --- a/crypto_sign/dilithium5/m4fstack/packing.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/packing.h b/crypto_sign/dilithium5/m4fstack/packing.h deleted file mode 120000 index ba1a6b3b..00000000 --- a/crypto_sign/dilithium5/m4fstack/packing.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/params.h b/crypto_sign/dilithium5/m4fstack/params.h deleted file mode 120000 index a6a4d8b6..00000000 --- a/crypto_sign/dilithium5/m4fstack/params.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.h b/crypto_sign/dilithium5/m4fstack/pointwise_mont.h deleted file mode 120000 index 0a6f8b9f..00000000 --- a/crypto_sign/dilithium5/m4fstack/pointwise_mont.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/pointwise_mont.s b/crypto_sign/dilithium5/m4fstack/pointwise_mont.s deleted file mode 120000 index c4ddb96c..00000000 --- a/crypto_sign/dilithium5/m4fstack/pointwise_mont.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.c b/crypto_sign/dilithium5/m4fstack/poly.c deleted file mode 120000 index 2544e75b..00000000 --- a/crypto_sign/dilithium5/m4fstack/poly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/poly.h b/crypto_sign/dilithium5/m4fstack/poly.h deleted file mode 120000 index 7ef70e53..00000000 --- a/crypto_sign/dilithium5/m4fstack/poly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.c b/crypto_sign/dilithium5/m4fstack/polyvec.c deleted file mode 120000 index a8edd0d0..00000000 --- a/crypto_sign/dilithium5/m4fstack/polyvec.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/polyvec.h b/crypto_sign/dilithium5/m4fstack/polyvec.h deleted file mode 120000 index cabd6a93..00000000 --- a/crypto_sign/dilithium5/m4fstack/polyvec.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/reduce.h b/crypto_sign/dilithium5/m4fstack/reduce.h deleted file mode 120000 index f1e2b389..00000000 --- a/crypto_sign/dilithium5/m4fstack/reduce.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.c b/crypto_sign/dilithium5/m4fstack/rounding.c deleted file mode 120000 index 80b8dce2..00000000 --- a/crypto_sign/dilithium5/m4fstack/rounding.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/rounding.h b/crypto_sign/dilithium5/m4fstack/rounding.h deleted file mode 120000 index 74c40c5e..00000000 --- a/crypto_sign/dilithium5/m4fstack/rounding.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.c b/crypto_sign/dilithium5/m4fstack/sign.c deleted file mode 120000 index 39f6ec48..00000000 --- a/crypto_sign/dilithium5/m4fstack/sign.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/sign.h b/crypto_sign/dilithium5/m4fstack/sign.h deleted file mode 120000 index b7f1e89c..00000000 --- a/crypto_sign/dilithium5/m4fstack/sign.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt.h b/crypto_sign/dilithium5/m4fstack/smallntt.h deleted file mode 120000 index 60f2d18a..00000000 --- a/crypto_sign/dilithium5/m4fstack/smallntt.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallntt_769.S b/crypto_sign/dilithium5/m4fstack/smallntt_769.S deleted file mode 120000 index 4ae2f9bb..00000000 --- a/crypto_sign/dilithium5/m4fstack/smallntt_769.S +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.c b/crypto_sign/dilithium5/m4fstack/smallpoly.c deleted file mode 120000 index 9c350567..00000000 --- a/crypto_sign/dilithium5/m4fstack/smallpoly.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/smallpoly.h b/crypto_sign/dilithium5/m4fstack/smallpoly.h deleted file mode 120000 index 45701a42..00000000 --- a/crypto_sign/dilithium5/m4fstack/smallpoly.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.c b/crypto_sign/dilithium5/m4fstack/stack.c deleted file mode 120000 index d25ed6f7..00000000 --- a/crypto_sign/dilithium5/m4fstack/stack.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/stack.h b/crypto_sign/dilithium5/m4fstack/stack.h deleted file mode 120000 index beab8ca2..00000000 --- a/crypto_sign/dilithium5/m4fstack/stack.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric-shake.c b/crypto_sign/dilithium5/m4fstack/symmetric-shake.c deleted file mode 120000 index 6ad80541..00000000 --- a/crypto_sign/dilithium5/m4fstack/symmetric-shake.c +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/symmetric.h b/crypto_sign/dilithium5/m4fstack/symmetric.h deleted file mode 120000 index 90ad5c07..00000000 --- a/crypto_sign/dilithium5/m4fstack/symmetric.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.h b/crypto_sign/dilithium5/m4fstack/vector.h deleted file mode 120000 index 6e2280f0..00000000 --- a/crypto_sign/dilithium5/m4fstack/vector.h +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/vector.s b/crypto_sign/dilithium5/m4fstack/vector.s deleted file mode 120000 index 2d2b4dcf..00000000 --- a/crypto_sign/dilithium5/m4fstack/vector.s +++ /dev/null @@ -1 +0,0 @@ -../../dilithium2/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-44/m4f/api.h b/crypto_sign/ml-dsa-44/m4f/api.h new file mode 100644 index 00000000..31c5a878 --- /dev/null +++ b/crypto_sign/ml-dsa-44/m4f/api.h @@ -0,0 +1,35 @@ +#ifndef API_H +#define API_H + +#include +#include +#include "params.h" + +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +int crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int crypto_sign_ctx(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *sk); + +int crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +int crypto_sign_open_ctx(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *ctx, size_t ctxlen, + const uint8_t *pk); + +#define crypto_sign_signature(sig, siglen, m, mlen, sk) crypto_sign_signature_ctx(sig, siglen, m, mlen, NULL, 0, sk) +#define crypto_sign(sm, smlen, m, mlen, sk) crypto_sign_ctx(sm, smlen, m, mlen, NULL, 0, sk) +#define crypto_sign_verify(sig, siglen, m, mlen, pk) crypto_sign_verify_ctx(sig, siglen, m, mlen, NULL, 0, pk) +#define crypto_sign_open(m, mlen, sm, smlen, pk) crypto_sign_open_ctx(m, mlen, sm, smlen, NULL, 0, pk) + +#endif diff --git a/crypto_sign/dilithium2/m4f/basemul_257.S b/crypto_sign/ml-dsa-44/m4f/basemul_257.S similarity index 100% rename from crypto_sign/dilithium2/m4f/basemul_257.S rename to crypto_sign/ml-dsa-44/m4f/basemul_257.S diff --git a/crypto_sign/dilithium2/m4f/config.h b/crypto_sign/ml-dsa-44/m4f/config.h similarity index 100% rename from crypto_sign/dilithium2/m4f/config.h rename to crypto_sign/ml-dsa-44/m4f/config.h diff --git a/crypto_sign/dilithium2/m4f/fnt_257.S b/crypto_sign/ml-dsa-44/m4f/fnt_257.S similarity index 100% rename from crypto_sign/dilithium2/m4f/fnt_257.S rename to crypto_sign/ml-dsa-44/m4f/fnt_257.S diff --git a/crypto_sign/dilithium2/m4f/ifnt_257.S b/crypto_sign/ml-dsa-44/m4f/ifnt_257.S similarity index 100% rename from crypto_sign/dilithium2/m4f/ifnt_257.S rename to crypto_sign/ml-dsa-44/m4f/ifnt_257.S diff --git a/crypto_sign/dilithium2/m4f/macros.i b/crypto_sign/ml-dsa-44/m4f/macros.i similarity index 100% rename from crypto_sign/dilithium2/m4f/macros.i rename to crypto_sign/ml-dsa-44/m4f/macros.i diff --git a/crypto_sign/dilithium2/m4f/macros_fnt.i b/crypto_sign/ml-dsa-44/m4f/macros_fnt.i similarity index 100% rename from crypto_sign/dilithium2/m4f/macros_fnt.i rename to crypto_sign/ml-dsa-44/m4f/macros_fnt.i diff --git a/crypto_sign/dilithium2/m4f/ntt.S b/crypto_sign/ml-dsa-44/m4f/ntt.S similarity index 100% rename from crypto_sign/dilithium2/m4f/ntt.S rename to crypto_sign/ml-dsa-44/m4f/ntt.S diff --git a/crypto_sign/dilithium2/m4f/ntt.h b/crypto_sign/ml-dsa-44/m4f/ntt.h similarity index 100% rename from crypto_sign/dilithium2/m4f/ntt.h rename to crypto_sign/ml-dsa-44/m4f/ntt.h diff --git a/crypto_sign/dilithium2/m4f/packing.c b/crypto_sign/ml-dsa-44/m4f/packing.c similarity index 100% rename from crypto_sign/dilithium2/m4f/packing.c rename to crypto_sign/ml-dsa-44/m4f/packing.c diff --git a/crypto_sign/dilithium2/m4f/packing.h b/crypto_sign/ml-dsa-44/m4f/packing.h similarity index 100% rename from crypto_sign/dilithium2/m4f/packing.h rename to crypto_sign/ml-dsa-44/m4f/packing.h diff --git a/crypto_sign/dilithium2/m4f/params.h b/crypto_sign/ml-dsa-44/m4f/params.h similarity index 100% rename from crypto_sign/dilithium2/m4f/params.h rename to crypto_sign/ml-dsa-44/m4f/params.h diff --git a/crypto_sign/dilithium2/m4f/pointwise_mont.h b/crypto_sign/ml-dsa-44/m4f/pointwise_mont.h similarity index 100% rename from crypto_sign/dilithium2/m4f/pointwise_mont.h rename to crypto_sign/ml-dsa-44/m4f/pointwise_mont.h diff --git a/crypto_sign/dilithium2/m4f/pointwise_mont.s b/crypto_sign/ml-dsa-44/m4f/pointwise_mont.s similarity index 100% rename from crypto_sign/dilithium2/m4f/pointwise_mont.s rename to crypto_sign/ml-dsa-44/m4f/pointwise_mont.s diff --git a/crypto_sign/dilithium2/m4f/poly.c b/crypto_sign/ml-dsa-44/m4f/poly.c similarity index 98% rename from crypto_sign/dilithium2/m4f/poly.c rename to crypto_sign/ml-dsa-44/m4f/poly.c index 654f4f23..511afd49 100644 --- a/crypto_sign/dilithium2/m4f/poly.c +++ b/crypto_sign/ml-dsa-44/m4f/poly.c @@ -45,17 +45,6 @@ void poly_caddq(poly *a) { asm_caddq(a->coeffs); } -/************************************************* -* Name: poly_csubq -* -* Description: For all coefficients of input polynomial subtract Q if -* coefficient is bigger than Q; add Q if coefficient is negative. -* -* Arguments: - poly *a: pointer to input/output polynomial -**************************************************/ -void poly_csubq(poly *a) { - asm_caddq(a->coeffs); -} #if 0 /************************************************* @@ -485,14 +474,14 @@ void poly_uniform_gamma1(poly *a, * Arguments: - poly *c: pointer to output polynomial * - const uint8_t mu[]: byte array containing seed of length SEEDBYTES **************************************************/ -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]) { +void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]) { unsigned int i, b, pos; uint64_t signs; uint8_t buf[SHAKE256_RATE]; shake256incctx state; shake256_inc_init(&state); - shake256_inc_absorb(&state, seed, SEEDBYTES); + shake256_inc_absorb(&state, seed, CTILDEBYTES); shake256_inc_finalize(&state); shake256_inc_squeezeblocks(buf, 1, &state); diff --git a/crypto_sign/dilithium2/m4f/poly.h b/crypto_sign/ml-dsa-44/m4f/poly.h similarity index 95% rename from crypto_sign/dilithium2/m4f/poly.h rename to crypto_sign/ml-dsa-44/m4f/poly.h index af9e7a50..31123a9a 100644 --- a/crypto_sign/dilithium2/m4f/poly.h +++ b/crypto_sign/ml-dsa-44/m4f/poly.h @@ -12,8 +12,6 @@ typedef struct { void poly_reduce(poly *a); #define poly_caddq DILITHIUM_NAMESPACE(poly_caddq) void poly_caddq(poly *a); -#define poly_csubq DILITHIUM_NAMESPACE(poly_csubq) -void poly_csubq(poly *a); #define poly_freeze DILITHIUM_NAMESPACE(poly_freeze) void poly_freeze(poly *a); @@ -58,7 +56,7 @@ void poly_uniform_gamma1(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce); #define poly_challenge DILITHIUM_NAMESPACE(poly_challenge) -void poly_challenge(poly *c, const uint8_t seed[SEEDBYTES]); +void poly_challenge(poly *c, const uint8_t seed[CTILDEBYTES]); #define polyeta_pack DILITHIUM_NAMESPACE(polyeta_pack) void polyeta_pack(uint8_t *r, const poly *a); diff --git a/crypto_sign/dilithium2/m4f/polyvec.c b/crypto_sign/ml-dsa-44/m4f/polyvec.c similarity index 100% rename from crypto_sign/dilithium2/m4f/polyvec.c rename to crypto_sign/ml-dsa-44/m4f/polyvec.c diff --git a/crypto_sign/dilithium2/m4f/polyvec.h b/crypto_sign/ml-dsa-44/m4f/polyvec.h similarity index 100% rename from crypto_sign/dilithium2/m4f/polyvec.h rename to crypto_sign/ml-dsa-44/m4f/polyvec.h diff --git a/crypto_sign/dilithium2/m4f/reduce.h b/crypto_sign/ml-dsa-44/m4f/reduce.h similarity index 100% rename from crypto_sign/dilithium2/m4f/reduce.h rename to crypto_sign/ml-dsa-44/m4f/reduce.h diff --git a/crypto_sign/dilithium2/m4f/rounding.c b/crypto_sign/ml-dsa-44/m4f/rounding.c similarity index 100% rename from crypto_sign/dilithium2/m4f/rounding.c rename to crypto_sign/ml-dsa-44/m4f/rounding.c diff --git a/crypto_sign/dilithium2/m4f/rounding.h b/crypto_sign/ml-dsa-44/m4f/rounding.h similarity index 100% rename from crypto_sign/dilithium2/m4f/rounding.h rename to crypto_sign/ml-dsa-44/m4f/rounding.h diff --git a/crypto_sign/dilithium2/m4f/sign.c b/crypto_sign/ml-dsa-44/m4f/sign.c similarity index 82% rename from crypto_sign/dilithium2/m4f/sign.c rename to crypto_sign/ml-dsa-44/m4f/sign.c index d1c5222b..b43f34fc 100644 --- a/crypto_sign/dilithium2/m4f/sign.c +++ b/crypto_sign/ml-dsa-44/m4f/sign.c @@ -21,7 +21,7 @@ * Returns 0 (success) **************************************************/ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { - uint8_t seedbuf[2*SEEDBYTES + CRHBYTES]; + uint8_t seedbuf[2 * SEEDBYTES + CRHBYTES]; uint8_t tr[TRBYTES]; const uint8_t *rho, *rhoprime, *key; polyvecl mat[K]; @@ -30,7 +30,9 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { /* Get randomness for rho, rhoprime and key */ randombytes(seedbuf, SEEDBYTES); - shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES); + seedbuf[SEEDBYTES + 0] = K; + seedbuf[SEEDBYTES + 1] = L; + shake256(seedbuf, 2 * SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES + 2); rho = seedbuf; rhoprime = rho + SEEDBYTES; key = rhoprime + CRHBYTES; @@ -64,7 +66,6 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { return 0; } - /************************************************* * Name: crypto_sign_signature * @@ -74,20 +75,22 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { * - size_t *siglen: pointer to output length of signature * - uint8_t *m: pointer to message to be signed * - size_t mlen: length of message +* - uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string * - uint8_t *sk: pointer to bit-packed secret key * -* Returns 0 (success) +* Returns 0 (success) or -1 (context string too long) **************************************************/ -int crypto_sign_signature(uint8_t *sig, +int crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, - const uint8_t *sk) -{ + const uint8_t *ctx, + size_t ctxlen, + const uint8_t *sk) { uint8_t seedbuf[2 * SEEDBYTES + TRBYTES + RNDBYTES + 2 * CRHBYTES]; uint8_t *rho, *tr, *key, *mu, *rhoprime, *rnd; uint16_t nonce = 0; - unsigned int n; polyvecl mat[K], y, z; polyveck t0, w1, w0; poly cp; @@ -98,6 +101,10 @@ int crypto_sign_signature(uint8_t *sig, smallpoly cp_small; smallhalfpoly cp_small_prime; + if (ctxlen > 255) { + return -1; + } + rho = seedbuf; tr = rho + SEEDBYTES; key = tr + TRBYTES; @@ -106,16 +113,18 @@ int crypto_sign_signature(uint8_t *sig, rhoprime = mu + CRHBYTES; unpack_sk(rho, tr, key, &t0, s1_prime, s2_prime, sk); - /* Compute mu = CRH(tr, msg) */ + /* Compute mu = CRH(tr, 0, ctxlen, ctx, msg) */ + mu[0] = 0; + mu[1] = (uint8_t)ctxlen; shake256_inc_init(&state); shake256_inc_absorb(&state, tr, TRBYTES); + shake256_inc_absorb(&state, mu, 2); + shake256_inc_absorb(&state, ctx, ctxlen); shake256_inc_absorb(&state, m, mlen); shake256_inc_finalize(&state); shake256_inc_squeeze(mu, CRHBYTES, &state); - for (n = 0; n < RNDBYTES; n++) { - rnd[n] = 0; - } + randombytes(rnd, RNDBYTES); shake256(rhoprime, CRHBYTES, key, SEEDBYTES + RNDBYTES + CRHBYTES); /* Expand matrix and transform vectors */ @@ -143,7 +152,7 @@ int crypto_sign_signature(uint8_t *sig, shake256_inc_init(&state); shake256_inc_absorb(&state, mu, CRHBYTES); - shake256_inc_absorb(&state, sig, K*POLYW1_PACKEDBYTES); + shake256_inc_absorb(&state, sig, K * POLYW1_PACKEDBYTES); shake256_inc_finalize(&state); shake256_inc_squeeze(sig, CTILDEBYTES, &state); poly_challenge(&cp, sig); @@ -156,8 +165,9 @@ int crypto_sign_signature(uint8_t *sig, polyvecl_add(&z, &z, &y); polyvecl_reduce(&z); - if(polyvecl_chknorm(&z, GAMMA1 - BETA)) + if(polyvecl_chknorm(&z, GAMMA1 - BETA)) { goto rej; + } /* Write signature */ @@ -211,19 +221,23 @@ int crypto_sign_signature(uint8_t *sig, * * Returns 0 (success) **************************************************/ -int crypto_sign(uint8_t *sm, +int crypto_sign_ctx(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *sk) { + int ret; size_t i; - for(i = 0; i < mlen; ++i) + for(i = 0; i < mlen; ++i) { sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + } + ret = crypto_sign_signature_ctx(sm, smlen, sm + CRYPTO_BYTES, mlen, ctx, ctxlen, sk); *smlen += mlen; - return 0; + return ret; } /************************************************* * Name: expand_mat_elem @@ -251,14 +265,18 @@ static void expand_mat_elem(poly *mat_elem, const unsigned char rho[SEEDBYTES], * - size_t siglen: length of signature * - const uint8_t *m: pointer to message * - size_t mlen: length of message + * - const uint8_t *ctx: pointer to context string + * - size_t ctxlen: length of context string * - const uint8_t *pk: pointer to bit-packed public key * * Returns 0 if signature could be verified correctly and -1 otherwise **************************************************/ -int crypto_sign_verify(const uint8_t *sig, +int crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *pk) { unsigned int i; @@ -272,8 +290,10 @@ int crypto_sign_verify(const uint8_t *sig, poly tmp_elem, w1_elem; - if (siglen != CRYPTO_BYTES) - return -1; + if (ctxlen > 255 || siglen != CRYPTO_BYTES) { + return -1; + } + if (unpack_sig_z(&z, sig) != 0) { return -1; @@ -281,10 +301,14 @@ int crypto_sign_verify(const uint8_t *sig, if (polyvecl_chknorm(&z, GAMMA1 - BETA)) return -1; - /* Compute CRH(h(rho, t1), msg) */ - shake256(mu, CRHBYTES, pk, CRYPTO_PUBLICKEYBYTES); + /* Compute mu = CRH(H(rho, t1), 0, ctxlen, ctx, msg) */ + shake256(mu, TRBYTES, pk, CRYPTO_PUBLICKEYBYTES); shake256_inc_init(&state); - shake256_inc_absorb(&state, mu, CRHBYTES); + shake256_inc_absorb(&state, mu, TRBYTES); + mu[0] = 0; + mu[1] = (uint8_t)ctxlen; + shake256_inc_absorb(&state, mu, 2); + shake256_inc_absorb(&state, ctx, ctxlen); shake256_inc_absorb(&state, m, mlen); shake256_inc_finalize(&state); shake256_inc_squeeze(mu, CRHBYTES, &state); @@ -325,7 +349,7 @@ int crypto_sign_verify(const uint8_t *sig, poly_invntt_tomont(&w1_elem); // Reconstruct w1 - poly_csubq(&w1_elem); + poly_caddq(&w1_elem); if (unpack_sig_h(&tmp_elem, k_idx, sig) != 0) { return -1; } @@ -339,9 +363,10 @@ int crypto_sign_verify(const uint8_t *sig, /* Call random oracle and verify challenge */ shake256_inc_finalize(&state); shake256_inc_squeeze(c2, CTILDEBYTES, &state); - for (i = 0; i < CTILDEBYTES; ++i) + for (i = 0; i < CTILDEBYTES; ++i) { if (c[i] != c2[i]) return -1; + } return 0; } @@ -356,14 +381,18 @@ int crypto_sign_verify(const uint8_t *sig, * - size_t *mlen: pointer to output length of message * - const uint8_t *sm: pointer to signed message * - size_t smlen: length of signed message +* - const uint8_t *ctx: pointer to context tring +* - size_t ctxlen: length of context string * - const uint8_t *pk: pointer to bit-packed public key * * Returns 0 if signed message could be verified correctly and -1 otherwise **************************************************/ -int crypto_sign_open(uint8_t *m, +int crypto_sign_open_ctx(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *pk) { size_t i; @@ -372,20 +401,22 @@ int crypto_sign_open(uint8_t *m, goto badsig; *mlen = smlen - CRYPTO_BYTES; - if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + if(crypto_sign_verify_ctx(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) goto badsig; else { /* All good, copy msg, return 0 */ - for(i = 0; i < *mlen; ++i) + for (i = 0; i < *mlen; ++i) { m[i] = sm[CRYPTO_BYTES + i]; + } return 0; } badsig: /* Signature verification failed */ - *mlen = -1; - for(i = 0; i < smlen; ++i) + *mlen = 0; + for (i = 0; i < smlen; ++i) { m[i] = 0; + } return -1; } diff --git a/crypto_sign/ml-dsa-44/m4f/sign.h b/crypto_sign/ml-dsa-44/m4f/sign.h new file mode 100644 index 00000000..8c4ae7dc --- /dev/null +++ b/crypto_sign/ml-dsa-44/m4f/sign.h @@ -0,0 +1,11 @@ +#ifndef SIGN_H +#define SIGN_H + +#include +#include +#include "params.h" +#include "api.h" +#include "polyvec.h" +#include "poly.h" + +#endif diff --git a/crypto_sign/dilithium2/m4f/smallntt.h b/crypto_sign/ml-dsa-44/m4f/smallntt.h similarity index 100% rename from crypto_sign/dilithium2/m4f/smallntt.h rename to crypto_sign/ml-dsa-44/m4f/smallntt.h diff --git a/crypto_sign/dilithium2/m4f/smallpoly.c b/crypto_sign/ml-dsa-44/m4f/smallpoly.c similarity index 100% rename from crypto_sign/dilithium2/m4f/smallpoly.c rename to crypto_sign/ml-dsa-44/m4f/smallpoly.c diff --git a/crypto_sign/dilithium2/m4f/smallpoly.h b/crypto_sign/ml-dsa-44/m4f/smallpoly.h similarity index 100% rename from crypto_sign/dilithium2/m4f/smallpoly.h rename to crypto_sign/ml-dsa-44/m4f/smallpoly.h diff --git a/crypto_sign/dilithium2/m4f/symmetric-shake.c b/crypto_sign/ml-dsa-44/m4f/symmetric-shake.c similarity index 100% rename from crypto_sign/dilithium2/m4f/symmetric-shake.c rename to crypto_sign/ml-dsa-44/m4f/symmetric-shake.c diff --git a/crypto_sign/dilithium2/m4f/symmetric.h b/crypto_sign/ml-dsa-44/m4f/symmetric.h similarity index 100% rename from crypto_sign/dilithium2/m4f/symmetric.h rename to crypto_sign/ml-dsa-44/m4f/symmetric.h diff --git a/crypto_sign/dilithium2/m4f/vector.h b/crypto_sign/ml-dsa-44/m4f/vector.h similarity index 89% rename from crypto_sign/dilithium2/m4f/vector.h rename to crypto_sign/ml-dsa-44/m4f/vector.h index 183ddc83..e5c5dda3 100644 --- a/crypto_sign/dilithium2/m4f/vector.h +++ b/crypto_sign/ml-dsa-44/m4f/vector.h @@ -10,8 +10,6 @@ void asm_reduce32(int32_t a[N]); void small_asm_reduce32_central(int32_t a[N]); #define asm_caddq DILITHIUM_NAMESPACE(asm_caddq) void asm_caddq(int32_t a[N]); -#define asm_csubq DILITHIUM_NAMESPACE(asm_csubq) -void asm_csubq(int32_t a[N]); #define asm_freeze DILITHIUM_NAMESPACE(asm_freeze) void asm_freeze(int32_t a[N]); #define asm_rej_uniform DILITHIUM_NAMESPACE(asm_rej_uniform) diff --git a/crypto_sign/dilithium2/m4f/vector.s b/crypto_sign/ml-dsa-44/m4f/vector.s similarity index 80% rename from crypto_sign/dilithium2/m4f/vector.s rename to crypto_sign/ml-dsa-44/m4f/vector.s index a393c914..376a1fbf 100644 --- a/crypto_sign/dilithium2/m4f/vector.s +++ b/crypto_sign/ml-dsa-44/m4f/vector.s @@ -169,60 +169,6 @@ pqcrystals_dilithium_asm_caddq: bx lr .size pqcrystals_dilithium_asm_caddq, .-pqcrystals_dilithium_asm_caddq -.macro csubq a, tmp, q - cmp.n \a, \q - it ge - subge.w \a, \a, \q - cmp \a, #0 - it mi - addmi.w \a, \a, \q -.endm - -// void asm_csubq(int32_t a[N]); -.global pqcrystals_dilithium_asm_csubq -.type pqcrystals_dilithium_asm_csubq, %function -.align 2 -pqcrystals_dilithium_asm_csubq: - push {r4-r10} - - movw r12,#:lower16:8380417 - movt r12,#:upper16:8380417 - - movw r10, #32 - 1: - ldr.w r1, [r0] - ldr.w r2, [r0, #1*4] - ldr.w r3, [r0, #2*4] - ldr.w r4, [r0, #3*4] - ldr.w r5, [r0, #4*4] - ldr.w r6, [r0, #5*4] - ldr.w r7, [r0, #6*4] - ldr.w r8, [r0, #7*4] - - csubq r1, r9, r12 - csubq r2, r9, r12 - csubq r3, r9, r12 - csubq r4, r9, r12 - csubq r5, r9, r12 - csubq r6, r9, r12 - csubq r7, r9, r12 - csubq r8, r9, r12 - - str.w r2, [r0, #1*4] - str.w r3, [r0, #2*4] - str.w r4, [r0, #3*4] - str.w r5, [r0, #4*4] - str.w r6, [r0, #5*4] - str.w r7, [r0, #6*4] - str.w r8, [r0, #7*4] - str r1, [r0], #8*4 - subs r10, #1 - bne.w 1b - - pop {r4-r10} - bx lr -.size pqcrystals_dilithium_asm_csubq, .-pqcrystals_dilithium_asm_csubq - // asm_rej_uniform(int32_t *a,unsigned int len,const unsigned char *buf, unsigned int buflen); .global pqcrystals_dilithium_asm_rej_uniform .type pqcrystals_dilithium_asm_rej_uniform, %function diff --git a/crypto_sign/dilithium2/m4fstack/api.h b/crypto_sign/ml-dsa-44/m4fstack/api.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/api.h rename to crypto_sign/ml-dsa-44/m4fstack/api.h diff --git a/crypto_sign/dilithium2/m4fstack/config.h b/crypto_sign/ml-dsa-44/m4fstack/config.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/config.h rename to crypto_sign/ml-dsa-44/m4fstack/config.h diff --git a/crypto_sign/dilithium2/m4fstack/macros.i b/crypto_sign/ml-dsa-44/m4fstack/macros.i similarity index 100% rename from crypto_sign/dilithium2/m4fstack/macros.i rename to crypto_sign/ml-dsa-44/m4fstack/macros.i diff --git a/crypto_sign/dilithium2/m4fstack/macros_smallntt.i b/crypto_sign/ml-dsa-44/m4fstack/macros_smallntt.i similarity index 100% rename from crypto_sign/dilithium2/m4fstack/macros_smallntt.i rename to crypto_sign/ml-dsa-44/m4fstack/macros_smallntt.i diff --git a/crypto_sign/dilithium2/m4fstack/ntt.S b/crypto_sign/ml-dsa-44/m4fstack/ntt.S similarity index 100% rename from crypto_sign/dilithium2/m4fstack/ntt.S rename to crypto_sign/ml-dsa-44/m4fstack/ntt.S diff --git a/crypto_sign/dilithium2/m4fstack/ntt.h b/crypto_sign/ml-dsa-44/m4fstack/ntt.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/ntt.h rename to crypto_sign/ml-dsa-44/m4fstack/ntt.h diff --git a/crypto_sign/dilithium2/m4fstack/packing.c b/crypto_sign/ml-dsa-44/m4fstack/packing.c similarity index 100% rename from crypto_sign/dilithium2/m4fstack/packing.c rename to crypto_sign/ml-dsa-44/m4fstack/packing.c diff --git a/crypto_sign/dilithium2/m4fstack/packing.h b/crypto_sign/ml-dsa-44/m4fstack/packing.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/packing.h rename to crypto_sign/ml-dsa-44/m4fstack/packing.h diff --git a/crypto_sign/dilithium2/m4fstack/params.h b/crypto_sign/ml-dsa-44/m4fstack/params.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/params.h rename to crypto_sign/ml-dsa-44/m4fstack/params.h diff --git a/crypto_sign/dilithium2/m4fstack/pointwise_mont.h b/crypto_sign/ml-dsa-44/m4fstack/pointwise_mont.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/pointwise_mont.h rename to crypto_sign/ml-dsa-44/m4fstack/pointwise_mont.h diff --git a/crypto_sign/dilithium2/m4fstack/pointwise_mont.s b/crypto_sign/ml-dsa-44/m4fstack/pointwise_mont.s similarity index 100% rename from crypto_sign/dilithium2/m4fstack/pointwise_mont.s rename to crypto_sign/ml-dsa-44/m4fstack/pointwise_mont.s diff --git a/crypto_sign/ml-dsa-44/m4fstack/poly.c b/crypto_sign/ml-dsa-44/m4fstack/poly.c new file mode 120000 index 00000000..b5bdaa81 --- /dev/null +++ b/crypto_sign/ml-dsa-44/m4fstack/poly.c @@ -0,0 +1 @@ +../m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-44/m4fstack/poly.h b/crypto_sign/ml-dsa-44/m4fstack/poly.h new file mode 120000 index 00000000..bd94e469 --- /dev/null +++ b/crypto_sign/ml-dsa-44/m4fstack/poly.h @@ -0,0 +1 @@ +../m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/dilithium2/m4fstack/polyvec.c b/crypto_sign/ml-dsa-44/m4fstack/polyvec.c similarity index 100% rename from crypto_sign/dilithium2/m4fstack/polyvec.c rename to crypto_sign/ml-dsa-44/m4fstack/polyvec.c diff --git a/crypto_sign/dilithium2/m4fstack/polyvec.h b/crypto_sign/ml-dsa-44/m4fstack/polyvec.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/polyvec.h rename to crypto_sign/ml-dsa-44/m4fstack/polyvec.h diff --git a/crypto_sign/dilithium2/m4fstack/reduce.h b/crypto_sign/ml-dsa-44/m4fstack/reduce.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/reduce.h rename to crypto_sign/ml-dsa-44/m4fstack/reduce.h diff --git a/crypto_sign/dilithium2/m4fstack/rounding.c b/crypto_sign/ml-dsa-44/m4fstack/rounding.c similarity index 100% rename from crypto_sign/dilithium2/m4fstack/rounding.c rename to crypto_sign/ml-dsa-44/m4fstack/rounding.c diff --git a/crypto_sign/dilithium2/m4fstack/rounding.h b/crypto_sign/ml-dsa-44/m4fstack/rounding.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/rounding.h rename to crypto_sign/ml-dsa-44/m4fstack/rounding.h diff --git a/crypto_sign/dilithium2/m4fstack/sign.c b/crypto_sign/ml-dsa-44/m4fstack/sign.c similarity index 84% rename from crypto_sign/dilithium2/m4fstack/sign.c rename to crypto_sign/ml-dsa-44/m4fstack/sign.c index 71cff9bb..a08d6d6a 100644 --- a/crypto_sign/dilithium2/m4fstack/sign.c +++ b/crypto_sign/ml-dsa-44/m4fstack/sign.c @@ -37,13 +37,15 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { } data; shake256incctx *s256 = &data.s256; - uint8_t *tr = &data.tr; + uint8_t *tr = &data.tr[0]; poly *tC = &data.tC; /* Get randomness for rho, rhoprime and key */ randombytes(seedbuf, SEEDBYTES); + seedbuf[SEEDBYTES + 0] = K; + seedbuf[SEEDBYTES + 1] = L; shake256_inc_init(s256); - shake256_inc_absorb(s256, seedbuf, SEEDBYTES); + shake256_inc_absorb(s256, seedbuf, SEEDBYTES + 2); shake256_inc_finalize(s256); shake256_inc_squeeze(seedbuf, 2*SEEDBYTES + CRHBYTES, s256); @@ -116,21 +118,23 @@ int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) { * - size_t *siglen: pointer to output length of signature * - uint8_t *m: pointer to message to be signed * - size_t mlen: length of message +* - uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string * - uint8_t *sk: pointer to bit-packed secret key * -* Returns 0 (success) +* Returns 0 (success) or -1 (context string too long) **************************************************/ -int crypto_sign_signature(uint8_t *sig, +int crypto_sign_signature_ctx(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, - const uint8_t *sk) -{ + const uint8_t *ctx, + size_t ctxlen, + const uint8_t *sk) { uint8_t buf[2 * CRHBYTES]; uint8_t *mu, *rhoprime, *rnd; const uint8_t *rho, *tr, *key; uint16_t nonce = 0; - unsigned int n; uint8_t wcomp[K][768]; uint8_t ccomp[68]; @@ -158,19 +162,23 @@ int crypto_sign_signature(uint8_t *sig, mu = buf; rnd = mu + CRHBYTES; rhoprime = mu + CRHBYTES; - unpack_sk_stack(rho, tr, key, sk); - /* Compute mu = CRH(tr, msg) */ + if (ctxlen > 255) { + return -1; + } + + /* Compute mu = CRH(tr, 0, ctxlen, ctx, msg) */ + mu[0] = 0; + mu[1] = (uint8_t)ctxlen; shake256_inc_init(&state.s256); shake256_inc_absorb(&state.s256, tr, TRBYTES); + shake256_inc_absorb(&state.s256, mu, 2); + shake256_inc_absorb(&state.s256, ctx, ctxlen); shake256_inc_absorb(&state.s256, m, mlen); shake256_inc_finalize(&state.s256); shake256_inc_squeeze(mu, CRHBYTES, &state.s256); - // Note: RNDBYTES < CRHBYTES, so buffer has proper size - for (n = 0; n < RNDBYTES; n++) { - rnd[n] = 0; - } + randombytes(rnd, RNDBYTES); shake256_inc_init(&state.s256); shake256_inc_absorb(&state.s256, key, SEEDBYTES); @@ -301,19 +309,23 @@ int crypto_sign_signature(uint8_t *sig, * * Returns 0 (success) **************************************************/ -int crypto_sign(uint8_t *sm, +int crypto_sign_ctx(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *sk) { + int ret; size_t i; - for(i = 0; i < mlen; ++i) + for(i = 0; i < mlen; ++i) { sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i]; - crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk); + } + ret = crypto_sign_signature_ctx(sm, smlen, sm + CRYPTO_BYTES, mlen, ctx, ctxlen, sk); *smlen += mlen; - return 0; + return ret; } /************************************************* @@ -325,14 +337,18 @@ int crypto_sign(uint8_t *sm, * - size_t siglen: length of signature * - const uint8_t *m: pointer to message * - size_t mlen: length of message +* - const uint8_t *ctx: pointer to context string +* - size_t ctxlen: length of context string * - const uint8_t *pk: pointer to bit-packed public key * * Returns 0 if signature could be verified correctly and -1 otherwise **************************************************/ -int crypto_sign_verify(const uint8_t *sig, +int crypto_sign_verify_ctx(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *pk) { unsigned int i; @@ -343,15 +359,15 @@ int crypto_sign_verify(const uint8_t *sig, uint8_t w1_packed[POLYW1_PACKEDBYTES]; uint8_t wcomp[768]; } w1_packed_comp; - uint8_t *w1_packed = &w1_packed_comp.w1_packed; - uint8_t *wcomp = &w1_packed_comp.wcomp; + uint8_t *w1_packed = &w1_packed_comp.w1_packed[0]; + uint8_t *wcomp = &w1_packed_comp.wcomp[0]; union { uint8_t ccomp[68]; uint8_t mu[CRHBYTES]; } ccomp_mu; - uint8_t *ccomp = &ccomp_mu.ccomp; - uint8_t *mu = &ccomp_mu.mu; + uint8_t *ccomp = &ccomp_mu.ccomp[0]; + uint8_t *mu = &ccomp_mu.mu[0]; shake256incctx s256; @@ -361,21 +377,25 @@ int crypto_sign_verify(const uint8_t *sig, uint8_t c2[CTILDEBYTES]; } shake_hint; - uint8_t *hint_ones = &shake_hint.hint_ones; + uint8_t *hint_ones = &shake_hint.hint_ones[0]; shake128incctx *s128 = &shake_hint.s128; - uint8_t *c2 = &shake_hint.c2; + uint8_t *c2 = &shake_hint.c2[0]; - if(siglen != CRYPTO_BYTES) - return -1; + if (ctxlen > 255 || siglen != CRYPTO_BYTES) { + return -1; + } - /* Compute CRH(h(rho, t1), msg) */ + /* Compute mu = CRH(H(rho, t1), 0, ctxlen, ctx, msg) */ shake256_inc_init(&s256); shake256_inc_absorb(&s256, pk, CRYPTO_PUBLICKEYBYTES); shake256_inc_finalize(&s256); shake256_inc_squeeze(mu, CRHBYTES, &s256); - shake256_inc_init(&s256); shake256_inc_absorb(&s256, mu, TRBYTES); + mu[0] = 0; + mu[1] = (uint8_t)ctxlen; + shake256_inc_absorb(&s256, mu, 2); + shake256_inc_absorb(&s256, ctx, ctxlen); shake256_inc_absorb(&s256, m, mlen); shake256_inc_finalize(&s256); shake256_inc_squeeze(mu, CRHBYTES, &s256); @@ -432,9 +452,10 @@ int crypto_sign_verify(const uint8_t *sig, /* Call random oracle and verify challenge */ shake256_inc_finalize(&s256); shake256_inc_squeeze(c2, CTILDEBYTES, &s256); - for(i = 0; i < CTILDEBYTES; ++i) - if(sig[i] != c2[i]) + for (i = 0; i < CTILDEBYTES; ++i) { + if (sig[i] != c2[i]) return -1; + } return 0; } @@ -449,14 +470,18 @@ int crypto_sign_verify(const uint8_t *sig, * - size_t *mlen: pointer to output length of message * - const uint8_t *sm: pointer to signed message * - size_t smlen: length of signed message +* - const uint8_t *ctx: pointer to context tring +* - size_t ctxlen: length of context string * - const uint8_t *pk: pointer to bit-packed public key * * Returns 0 if signed message could be verified correctly and -1 otherwise **************************************************/ -int crypto_sign_open(uint8_t *m, +int crypto_sign_open_ctx(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen, + const uint8_t *ctx, + size_t ctxlen, const uint8_t *pk) { size_t i; @@ -465,20 +490,22 @@ int crypto_sign_open(uint8_t *m, goto badsig; *mlen = smlen - CRYPTO_BYTES; - if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk)) + if(crypto_sign_verify_ctx(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, ctx, ctxlen, pk)) goto badsig; else { /* All good, copy msg, return 0 */ - for(i = 0; i < *mlen; ++i) + for (i = 0; i < *mlen; ++i) { m[i] = sm[CRYPTO_BYTES + i]; + } return 0; } badsig: /* Signature verification failed */ - *mlen = -1; - for(i = 0; i < smlen; ++i) + *mlen = 0; + for (i = 0; i < smlen; ++i) { m[i] = 0; + } return -1; } diff --git a/crypto_sign/dilithium2/m4fstack/sign.h b/crypto_sign/ml-dsa-44/m4fstack/sign.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/sign.h rename to crypto_sign/ml-dsa-44/m4fstack/sign.h diff --git a/crypto_sign/dilithium2/m4fstack/smallntt.h b/crypto_sign/ml-dsa-44/m4fstack/smallntt.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/smallntt.h rename to crypto_sign/ml-dsa-44/m4fstack/smallntt.h diff --git a/crypto_sign/dilithium2/m4fstack/smallntt_769.S b/crypto_sign/ml-dsa-44/m4fstack/smallntt_769.S similarity index 100% rename from crypto_sign/dilithium2/m4fstack/smallntt_769.S rename to crypto_sign/ml-dsa-44/m4fstack/smallntt_769.S diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.c b/crypto_sign/ml-dsa-44/m4fstack/smallpoly.c similarity index 100% rename from crypto_sign/dilithium2/m4fstack/smallpoly.c rename to crypto_sign/ml-dsa-44/m4fstack/smallpoly.c diff --git a/crypto_sign/dilithium2/m4fstack/smallpoly.h b/crypto_sign/ml-dsa-44/m4fstack/smallpoly.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/smallpoly.h rename to crypto_sign/ml-dsa-44/m4fstack/smallpoly.h diff --git a/crypto_sign/dilithium2/m4fstack/stack.c b/crypto_sign/ml-dsa-44/m4fstack/stack.c similarity index 97% rename from crypto_sign/dilithium2/m4fstack/stack.c rename to crypto_sign/ml-dsa-44/m4fstack/stack.c index b45f7021..a00183fc 100644 --- a/crypto_sign/dilithium2/m4fstack/stack.c +++ b/crypto_sign/ml-dsa-44/m4fstack/stack.c @@ -438,26 +438,6 @@ size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]){ return hints_n; } -void unpack_sk_stack(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]) -{ - unsigned int i; - - for(i = 0; i < SEEDBYTES; ++i) - rho[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < SEEDBYTES; ++i) - key[i] = sk[i]; - sk += SEEDBYTES; - - for(i = 0; i < TRBYTES; ++i) - tr[i] = sk[i]; - sk += TRBYTES; -} - /************************************************* * Name: unpack_sig_h_indices * @@ -679,14 +659,14 @@ void pack_sk_tr(unsigned char sk[CRYPTO_SECRETKEYBYTES], * - const uint8_t mu[]: byte array containing seed of length SEEDBYTES **************************************************/ #define CHALLENGE_STACK_BUF_SIZE 8 -void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]) { +void poly_challenge_stack(poly *c, const uint8_t seed[CTILDEBYTES]) { unsigned int i, b, pos; uint64_t signs; uint8_t buf[CHALLENGE_STACK_BUF_SIZE]; shake256incctx state; shake256_inc_init(&state); - shake256_inc_absorb(&state, seed, SEEDBYTES); + shake256_inc_absorb(&state, seed, CTILDEBYTES); shake256_inc_finalize(&state); shake256_inc_squeeze(buf, CHALLENGE_STACK_BUF_SIZE, &state); signs = 0; diff --git a/crypto_sign/dilithium2/m4fstack/stack.h b/crypto_sign/ml-dsa-44/m4fstack/stack.h similarity index 91% rename from crypto_sign/dilithium2/m4fstack/stack.h rename to crypto_sign/ml-dsa-44/m4fstack/stack.h index 06c8c576..e8023062 100644 --- a/crypto_sign/dilithium2/m4fstack/stack.h +++ b/crypto_sign/ml-dsa-44/m4fstack/stack.h @@ -28,17 +28,12 @@ void unpack_sk_s2(smallpoly *a, const uint8_t *sk, size_t idx); void poly_uniform_pointwise_montgomery_polywadd_stack(uint8_t wcomp[3*N], poly *b, const uint8_t seed[SEEDBYTES], uint16_t nonce, shake128incctx *state); void poly_uniform_gamma1_stack(poly *a, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); void poly_uniform_gamma1_add_stack(poly *a, poly *b, const uint8_t seed[CRHBYTES], uint16_t nonce, shake256incctx *state); -void poly_challenge_stack(poly *c, const uint8_t seed[SEEDBYTES]); +void poly_challenge_stack(poly *c, const uint8_t seed[CTILDEBYTES]); size_t poly_make_hint_stack(poly *a, poly *t, uint8_t w[768]); int unpack_sig_h_indices(uint8_t h_i[OMEGA], unsigned int * number_of_hints, unsigned int idx, const unsigned char sig[CRYPTO_BYTES]); void poly_use_hint_stack(poly *b, const poly *a, uint8_t h_i[OMEGA], unsigned int number_of_hints); -void unpack_sk_stack(uint8_t rho[SEEDBYTES], - uint8_t tr[TRBYTES], - uint8_t key[SEEDBYTES], - const uint8_t sk[CRYPTO_SECRETKEYBYTES]); - void pack_pk_rho(unsigned char pk[CRYPTO_PUBLICKEYBYTES], const unsigned char rho[SEEDBYTES]); diff --git a/crypto_sign/dilithium2/m4fstack/symmetric-shake.c b/crypto_sign/ml-dsa-44/m4fstack/symmetric-shake.c similarity index 100% rename from crypto_sign/dilithium2/m4fstack/symmetric-shake.c rename to crypto_sign/ml-dsa-44/m4fstack/symmetric-shake.c diff --git a/crypto_sign/dilithium2/m4fstack/symmetric.h b/crypto_sign/ml-dsa-44/m4fstack/symmetric.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/symmetric.h rename to crypto_sign/ml-dsa-44/m4fstack/symmetric.h diff --git a/crypto_sign/dilithium2/m4fstack/vector.h b/crypto_sign/ml-dsa-44/m4fstack/vector.h similarity index 100% rename from crypto_sign/dilithium2/m4fstack/vector.h rename to crypto_sign/ml-dsa-44/m4fstack/vector.h diff --git a/crypto_sign/dilithium2/m4fstack/vector.s b/crypto_sign/ml-dsa-44/m4fstack/vector.s similarity index 100% rename from crypto_sign/dilithium2/m4fstack/vector.s rename to crypto_sign/ml-dsa-44/m4fstack/vector.s diff --git a/crypto_sign/ml-dsa-65/m4f/api.h b/crypto_sign/ml-dsa-65/m4f/api.h new file mode 120000 index 00000000..03cb18f0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/api.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/config.h b/crypto_sign/ml-dsa-65/m4f/config.h similarity index 100% rename from crypto_sign/dilithium3/m4f/config.h rename to crypto_sign/ml-dsa-65/m4f/config.h diff --git a/crypto_sign/ml-dsa-65/m4f/macros.i b/crypto_sign/ml-dsa-65/m4f/macros.i new file mode 120000 index 00000000..bd2e3c94 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/macros.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/macros_smallntt.i b/crypto_sign/ml-dsa-65/m4f/macros_smallntt.i similarity index 100% rename from crypto_sign/dilithium3/m4f/macros_smallntt.i rename to crypto_sign/ml-dsa-65/m4f/macros_smallntt.i diff --git a/crypto_sign/ml-dsa-65/m4f/ntt.S b/crypto_sign/ml-dsa-65/m4f/ntt.S new file mode 120000 index 00000000..8a8bf002 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/ntt.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/ntt.h b/crypto_sign/ml-dsa-65/m4f/ntt.h new file mode 120000 index 00000000..4b77c946 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/ntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/packing.c b/crypto_sign/ml-dsa-65/m4f/packing.c new file mode 120000 index 00000000..633bc4b4 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/packing.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/packing.h b/crypto_sign/ml-dsa-65/m4f/packing.h new file mode 120000 index 00000000..8a69f40a --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/packing.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/params.h b/crypto_sign/ml-dsa-65/m4f/params.h new file mode 120000 index 00000000..42d7959e --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/params.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/pointwise_mont.h b/crypto_sign/ml-dsa-65/m4f/pointwise_mont.h new file mode 120000 index 00000000..9b66a64f --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/pointwise_mont.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/pointwise_mont.s b/crypto_sign/ml-dsa-65/m4f/pointwise_mont.s new file mode 120000 index 00000000..52f839c0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/pointwise_mont.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/poly.c b/crypto_sign/ml-dsa-65/m4f/poly.c new file mode 120000 index 00000000..916b08a2 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/poly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/poly.h b/crypto_sign/ml-dsa-65/m4f/poly.h new file mode 120000 index 00000000..b0e447c2 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/poly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/polyvec.c b/crypto_sign/ml-dsa-65/m4f/polyvec.c new file mode 120000 index 00000000..44cc87fd --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/polyvec.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/polyvec.h b/crypto_sign/ml-dsa-65/m4f/polyvec.h new file mode 120000 index 00000000..f2b32c13 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/polyvec.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/reduce.h b/crypto_sign/ml-dsa-65/m4f/reduce.h new file mode 120000 index 00000000..2de0b830 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/reduce.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/rounding.c b/crypto_sign/ml-dsa-65/m4f/rounding.c new file mode 120000 index 00000000..07b2aa32 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/rounding.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/rounding.h b/crypto_sign/ml-dsa-65/m4f/rounding.h new file mode 120000 index 00000000..c2be1162 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/rounding.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/sign.c b/crypto_sign/ml-dsa-65/m4f/sign.c new file mode 120000 index 00000000..0a50b490 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/sign.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/sign.h b/crypto_sign/ml-dsa-65/m4f/sign.h new file mode 120000 index 00000000..3f20c1bf --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/sign.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4f/smallntt.h b/crypto_sign/ml-dsa-65/m4f/smallntt.h similarity index 100% rename from crypto_sign/dilithium3/m4f/smallntt.h rename to crypto_sign/ml-dsa-65/m4f/smallntt.h diff --git a/crypto_sign/dilithium3/m4f/smallntt_769.S b/crypto_sign/ml-dsa-65/m4f/smallntt_769.S similarity index 100% rename from crypto_sign/dilithium3/m4f/smallntt_769.S rename to crypto_sign/ml-dsa-65/m4f/smallntt_769.S diff --git a/crypto_sign/ml-dsa-65/m4f/smallpoly.c b/crypto_sign/ml-dsa-65/m4f/smallpoly.c new file mode 120000 index 00000000..fc1b21f0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/smallpoly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/smallpoly.h b/crypto_sign/ml-dsa-65/m4f/smallpoly.h new file mode 120000 index 00000000..5269aad8 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/smallpoly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/symmetric-shake.c b/crypto_sign/ml-dsa-65/m4f/symmetric-shake.c new file mode 120000 index 00000000..cf760e6d --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/symmetric-shake.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/symmetric.h b/crypto_sign/ml-dsa-65/m4f/symmetric.h new file mode 120000 index 00000000..b9fb54d0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/symmetric.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/vector.h b/crypto_sign/ml-dsa-65/m4f/vector.h new file mode 120000 index 00000000..d47bca44 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/vector.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4f/vector.s b/crypto_sign/ml-dsa-65/m4f/vector.s new file mode 120000 index 00000000..6f060a79 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4f/vector.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/api.h b/crypto_sign/ml-dsa-65/m4fstack/api.h new file mode 120000 index 00000000..03cb18f0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/api.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium3/m4fstack/config.h b/crypto_sign/ml-dsa-65/m4fstack/config.h similarity index 100% rename from crypto_sign/dilithium3/m4fstack/config.h rename to crypto_sign/ml-dsa-65/m4fstack/config.h diff --git a/crypto_sign/ml-dsa-65/m4fstack/macros.i b/crypto_sign/ml-dsa-65/m4fstack/macros.i new file mode 120000 index 00000000..bd2e3c94 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/macros.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/macros_smallntt.i b/crypto_sign/ml-dsa-65/m4fstack/macros_smallntt.i new file mode 120000 index 00000000..eaef2f26 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/macros_smallntt.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/ntt.S b/crypto_sign/ml-dsa-65/m4fstack/ntt.S new file mode 120000 index 00000000..8a8bf002 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/ntt.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/ntt.h b/crypto_sign/ml-dsa-65/m4fstack/ntt.h new file mode 120000 index 00000000..4b77c946 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/ntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/packing.c b/crypto_sign/ml-dsa-65/m4fstack/packing.c new file mode 120000 index 00000000..633bc4b4 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/packing.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/packing.h b/crypto_sign/ml-dsa-65/m4fstack/packing.h new file mode 120000 index 00000000..8a69f40a --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/packing.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/params.h b/crypto_sign/ml-dsa-65/m4fstack/params.h new file mode 120000 index 00000000..42d7959e --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/params.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.h b/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.h new file mode 120000 index 00000000..9b66a64f --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.s b/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.s new file mode 120000 index 00000000..52f839c0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/pointwise_mont.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/poly.c b/crypto_sign/ml-dsa-65/m4fstack/poly.c new file mode 120000 index 00000000..916b08a2 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/poly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/poly.h b/crypto_sign/ml-dsa-65/m4fstack/poly.h new file mode 120000 index 00000000..b0e447c2 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/poly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/polyvec.c b/crypto_sign/ml-dsa-65/m4fstack/polyvec.c new file mode 120000 index 00000000..44cc87fd --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/polyvec.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/polyvec.h b/crypto_sign/ml-dsa-65/m4fstack/polyvec.h new file mode 120000 index 00000000..f2b32c13 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/polyvec.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/reduce.h b/crypto_sign/ml-dsa-65/m4fstack/reduce.h new file mode 120000 index 00000000..df4da75e --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/reduce.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/rounding.c b/crypto_sign/ml-dsa-65/m4fstack/rounding.c new file mode 120000 index 00000000..07b2aa32 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/rounding.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/rounding.h b/crypto_sign/ml-dsa-65/m4fstack/rounding.h new file mode 120000 index 00000000..c2be1162 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/rounding.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/sign.c b/crypto_sign/ml-dsa-65/m4fstack/sign.c new file mode 120000 index 00000000..cc2dd37e --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/sign.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/sign.h b/crypto_sign/ml-dsa-65/m4fstack/sign.h new file mode 120000 index 00000000..3f20c1bf --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/sign.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smallntt.h b/crypto_sign/ml-dsa-65/m4fstack/smallntt.h new file mode 120000 index 00000000..a265dd0e --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/smallntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smallntt_769.S b/crypto_sign/ml-dsa-65/m4fstack/smallntt_769.S new file mode 120000 index 00000000..a29e0ce8 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/smallntt_769.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smallpoly.c b/crypto_sign/ml-dsa-65/m4fstack/smallpoly.c new file mode 120000 index 00000000..e3c6bc8d --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/smallpoly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smallpoly.h b/crypto_sign/ml-dsa-65/m4fstack/smallpoly.h new file mode 120000 index 00000000..8349208f --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/smallpoly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smalltt.h b/crypto_sign/ml-dsa-65/m4fstack/smalltt.h new file mode 120000 index 00000000..5c449aee --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/smalltt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smalltt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/stack.c b/crypto_sign/ml-dsa-65/m4fstack/stack.c new file mode 120000 index 00000000..ce95fcf4 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/stack.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/stack.h b/crypto_sign/ml-dsa-65/m4fstack/stack.h new file mode 120000 index 00000000..5135ee55 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/stack.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/symmetric-shake.c b/crypto_sign/ml-dsa-65/m4fstack/symmetric-shake.c new file mode 120000 index 00000000..cf760e6d --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/symmetric-shake.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/symmetric.h b/crypto_sign/ml-dsa-65/m4fstack/symmetric.h new file mode 120000 index 00000000..b9fb54d0 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/symmetric.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/vector.h b/crypto_sign/ml-dsa-65/m4fstack/vector.h new file mode 120000 index 00000000..d47bca44 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/vector.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/vector.s b/crypto_sign/ml-dsa-65/m4fstack/vector.s new file mode 120000 index 00000000..6f060a79 --- /dev/null +++ b/crypto_sign/ml-dsa-65/m4fstack/vector.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/api.h b/crypto_sign/ml-dsa-87/m4f/api.h new file mode 120000 index 00000000..03cb18f0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/api.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/basemul_257.S b/crypto_sign/ml-dsa-87/m4f/basemul_257.S new file mode 120000 index 00000000..1de045d0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/basemul_257.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/basemul_257.S \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4f/config.h b/crypto_sign/ml-dsa-87/m4f/config.h similarity index 100% rename from crypto_sign/dilithium5/m4f/config.h rename to crypto_sign/ml-dsa-87/m4f/config.h diff --git a/crypto_sign/ml-dsa-87/m4f/fnt_257.S b/crypto_sign/ml-dsa-87/m4f/fnt_257.S new file mode 120000 index 00000000..72ae5ccf --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/fnt_257.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/fnt_257.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/ifnt_257.S b/crypto_sign/ml-dsa-87/m4f/ifnt_257.S new file mode 120000 index 00000000..6af79318 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/ifnt_257.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ifnt_257.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/macros.i b/crypto_sign/ml-dsa-87/m4f/macros.i new file mode 120000 index 00000000..bd2e3c94 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/macros.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/macros_fnt.i b/crypto_sign/ml-dsa-87/m4f/macros_fnt.i new file mode 120000 index 00000000..a2ad5aa0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/macros_fnt.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/macros_fnt.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/ntt.S b/crypto_sign/ml-dsa-87/m4f/ntt.S new file mode 120000 index 00000000..8a8bf002 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/ntt.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/ntt.h b/crypto_sign/ml-dsa-87/m4f/ntt.h new file mode 120000 index 00000000..4b77c946 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/ntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/packing.c b/crypto_sign/ml-dsa-87/m4f/packing.c new file mode 120000 index 00000000..633bc4b4 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/packing.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/packing.h b/crypto_sign/ml-dsa-87/m4f/packing.h new file mode 120000 index 00000000..8a69f40a --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/packing.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/params.h b/crypto_sign/ml-dsa-87/m4f/params.h new file mode 120000 index 00000000..42d7959e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/params.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/pointwise_mont.h b/crypto_sign/ml-dsa-87/m4f/pointwise_mont.h new file mode 120000 index 00000000..9b66a64f --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/pointwise_mont.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/pointwise_mont.s b/crypto_sign/ml-dsa-87/m4f/pointwise_mont.s new file mode 120000 index 00000000..52f839c0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/pointwise_mont.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/poly.c b/crypto_sign/ml-dsa-87/m4f/poly.c new file mode 120000 index 00000000..916b08a2 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/poly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/poly.h b/crypto_sign/ml-dsa-87/m4f/poly.h new file mode 120000 index 00000000..b0e447c2 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/poly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/polyvec.c b/crypto_sign/ml-dsa-87/m4f/polyvec.c new file mode 120000 index 00000000..44cc87fd --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/polyvec.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/polyvec.h b/crypto_sign/ml-dsa-87/m4f/polyvec.h new file mode 120000 index 00000000..f2b32c13 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/polyvec.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/reduce.h b/crypto_sign/ml-dsa-87/m4f/reduce.h new file mode 120000 index 00000000..2de0b830 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/reduce.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/reduce.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/rounding.c b/crypto_sign/ml-dsa-87/m4f/rounding.c new file mode 120000 index 00000000..07b2aa32 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/rounding.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/rounding.h b/crypto_sign/ml-dsa-87/m4f/rounding.h new file mode 120000 index 00000000..c2be1162 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/rounding.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/sign.c b/crypto_sign/ml-dsa-87/m4f/sign.c new file mode 120000 index 00000000..0a50b490 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/sign.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/sign.h b/crypto_sign/ml-dsa-87/m4f/sign.h new file mode 120000 index 00000000..3f20c1bf --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/sign.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/smallntt.h b/crypto_sign/ml-dsa-87/m4f/smallntt.h new file mode 120000 index 00000000..6d52912e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/smallntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/smallntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/smallpoly.c b/crypto_sign/ml-dsa-87/m4f/smallpoly.c new file mode 120000 index 00000000..fc1b21f0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/smallpoly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/smallpoly.h b/crypto_sign/ml-dsa-87/m4f/smallpoly.h new file mode 120000 index 00000000..5269aad8 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/smallpoly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/symmetric-shake.c b/crypto_sign/ml-dsa-87/m4f/symmetric-shake.c new file mode 120000 index 00000000..cf760e6d --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/symmetric-shake.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/symmetric.h b/crypto_sign/ml-dsa-87/m4f/symmetric.h new file mode 120000 index 00000000..b9fb54d0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/symmetric.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/vector.h b/crypto_sign/ml-dsa-87/m4f/vector.h new file mode 120000 index 00000000..d47bca44 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/vector.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4f/vector.s b/crypto_sign/ml-dsa-87/m4f/vector.s new file mode 120000 index 00000000..6f060a79 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4f/vector.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/api.h b/crypto_sign/ml-dsa-87/m4fstack/api.h new file mode 120000 index 00000000..03cb18f0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/api.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/api.h \ No newline at end of file diff --git a/crypto_sign/dilithium5/m4fstack/config.h b/crypto_sign/ml-dsa-87/m4fstack/config.h similarity index 100% rename from crypto_sign/dilithium5/m4fstack/config.h rename to crypto_sign/ml-dsa-87/m4fstack/config.h diff --git a/crypto_sign/ml-dsa-87/m4fstack/macros.i b/crypto_sign/ml-dsa-87/m4fstack/macros.i new file mode 120000 index 00000000..bd2e3c94 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/macros.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/macros.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/macros_smallntt.i b/crypto_sign/ml-dsa-87/m4fstack/macros_smallntt.i new file mode 120000 index 00000000..eaef2f26 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/macros_smallntt.i @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/macros_smallntt.i \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/ntt.S b/crypto_sign/ml-dsa-87/m4fstack/ntt.S new file mode 120000 index 00000000..8a8bf002 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/ntt.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/ntt.h b/crypto_sign/ml-dsa-87/m4fstack/ntt.h new file mode 120000 index 00000000..4b77c946 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/ntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/ntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/packing.c b/crypto_sign/ml-dsa-87/m4fstack/packing.c new file mode 120000 index 00000000..633bc4b4 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/packing.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/packing.h b/crypto_sign/ml-dsa-87/m4fstack/packing.h new file mode 120000 index 00000000..8a69f40a --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/packing.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/packing.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/params.h b/crypto_sign/ml-dsa-87/m4fstack/params.h new file mode 120000 index 00000000..42d7959e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/params.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/params.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.h b/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.h new file mode 120000 index 00000000..9b66a64f --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.s b/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.s new file mode 120000 index 00000000..52f839c0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/pointwise_mont.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/pointwise_mont.s \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/poly.c b/crypto_sign/ml-dsa-87/m4fstack/poly.c new file mode 120000 index 00000000..916b08a2 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/poly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/poly.h b/crypto_sign/ml-dsa-87/m4fstack/poly.h new file mode 120000 index 00000000..b0e447c2 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/poly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/poly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/polyvec.c b/crypto_sign/ml-dsa-87/m4fstack/polyvec.c new file mode 120000 index 00000000..44cc87fd --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/polyvec.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/polyvec.h b/crypto_sign/ml-dsa-87/m4fstack/polyvec.h new file mode 120000 index 00000000..f2b32c13 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/polyvec.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/polyvec.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/reduce.h b/crypto_sign/ml-dsa-87/m4fstack/reduce.h new file mode 120000 index 00000000..df4da75e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/reduce.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/reduce.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/rounding.c b/crypto_sign/ml-dsa-87/m4fstack/rounding.c new file mode 120000 index 00000000..07b2aa32 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/rounding.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/rounding.h b/crypto_sign/ml-dsa-87/m4fstack/rounding.h new file mode 120000 index 00000000..c2be1162 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/rounding.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/rounding.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/sign.c b/crypto_sign/ml-dsa-87/m4fstack/sign.c new file mode 120000 index 00000000..cc2dd37e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/sign.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/sign.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/sign.h b/crypto_sign/ml-dsa-87/m4fstack/sign.h new file mode 120000 index 00000000..3f20c1bf --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/sign.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/sign.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/smallntt.h b/crypto_sign/ml-dsa-87/m4fstack/smallntt.h new file mode 120000 index 00000000..a265dd0e --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/smallntt.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallntt.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/smallntt_769.S b/crypto_sign/ml-dsa-87/m4fstack/smallntt_769.S new file mode 120000 index 00000000..a29e0ce8 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/smallntt_769.S @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallntt_769.S \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/smallpoly.c b/crypto_sign/ml-dsa-87/m4fstack/smallpoly.c new file mode 120000 index 00000000..e3c6bc8d --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/smallpoly.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallpoly.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/smallpoly.h b/crypto_sign/ml-dsa-87/m4fstack/smallpoly.h new file mode 120000 index 00000000..8349208f --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/smallpoly.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/smallpoly.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/stack.c b/crypto_sign/ml-dsa-87/m4fstack/stack.c new file mode 120000 index 00000000..ce95fcf4 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/stack.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/stack.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/stack.h b/crypto_sign/ml-dsa-87/m4fstack/stack.h new file mode 120000 index 00000000..5135ee55 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/stack.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4fstack/stack.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/symmetric-shake.c b/crypto_sign/ml-dsa-87/m4fstack/symmetric-shake.c new file mode 120000 index 00000000..cf760e6d --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/symmetric-shake.c @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric-shake.c \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/symmetric.h b/crypto_sign/ml-dsa-87/m4fstack/symmetric.h new file mode 120000 index 00000000..b9fb54d0 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/symmetric.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/symmetric.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/vector.h b/crypto_sign/ml-dsa-87/m4fstack/vector.h new file mode 120000 index 00000000..d47bca44 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/vector.h @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.h \ No newline at end of file diff --git a/crypto_sign/ml-dsa-87/m4fstack/vector.s b/crypto_sign/ml-dsa-87/m4fstack/vector.s new file mode 120000 index 00000000..6f060a79 --- /dev/null +++ b/crypto_sign/ml-dsa-87/m4fstack/vector.s @@ -0,0 +1 @@ +../../ml-dsa-44/m4f/vector.s \ No newline at end of file diff --git a/mupq b/mupq index 18fd6be4..8e62b94b 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 18fd6be462667a908a689702a46ec3005e9708fa +Subproject commit 8e62b94bfb8125fc81ac2774f8aa8b44120bc619 diff --git a/skiplist.py b/skiplist.py index b05b0ff5..ac08857a 100644 --- a/skiplist.py +++ b/skiplist.py @@ -53,12 +53,6 @@ {'scheme': 'cross-sha3-r-sdpg-3-small', 'implementation': 'ref', 'estmemory': 776192}, {'scheme': 'cross-sha3-r-sdpg-5-fast', 'implementation': 'ref', 'estmemory': 440320}, {'scheme': 'cross-sha3-r-sdpg-5-small', 'implementation': 'ref', 'estmemory': 1063936}, - {'scheme': 'dilithium2', 'implementation': 'clean', 'estmemory': 59392}, - {'scheme': 'dilithium2', 'implementation': 'm4f', 'estmemory': 57344}, - {'scheme': 'dilithium3', 'implementation': 'clean', 'estmemory': 90112}, - {'scheme': 'dilithium3', 'implementation': 'm4f', 'estmemory': 79872}, - {'scheme': 'dilithium5', 'implementation': 'clean', 'estmemory': 136192}, - {'scheme': 'dilithium5', 'implementation': 'm4f', 'estmemory': 129024}, {'scheme': 'falcon-1024', 'implementation': 'clean', 'estmemory': 91136}, {'scheme': 'falcon-1024', 'implementation': 'm4-ct', 'estmemory': 89088}, {'scheme': 'falcon-1024', 'implementation': 'opt-ct', 'estmemory': 89088}, @@ -242,9 +236,15 @@ {'scheme': 'tuov_is_pkc_skc', 'implementation': 'ref', 'estmemory': 1275904}, {'scheme': 'tuov_v_pkc', 'implementation': 'ref', 'estmemory': 7083008}, {'scheme': 'tuov_v_pkc_skc', 'implementation': 'ref', 'estmemory': 4639744}, - {'scheme': 'dilithium2', 'implementation': 'm4fstack', 'estmemory': 12288}, - {'scheme': 'dilithium5', 'implementation': 'm4fstack', 'estmemory': 21504}, - {'scheme': 'dilithium3', 'implementation': 'm4fstack', 'estmemory': 17408}, {'scheme': 'falcon-padded-1024', 'implementation': 'clean', 'estmemory': 91136}, {'scheme': 'falcon-padded-512', 'implementation': 'clean', 'estmemory': 48128}, + {'scheme': 'ml-dsa-87', 'implementation': 'm4fstack', 'estmemory': 21504}, + {'scheme': 'ml-dsa-87', 'implementation': 'm4f', 'estmemory': 129024}, + {'scheme': 'ml-dsa-65', 'implementation': 'm4fstack', 'estmemory': 17408}, + {'scheme': 'ml-dsa-65', 'implementation': 'm4f', 'estmemory': 79872}, + {'scheme': 'ml-dsa-44', 'implementation': 'm4fstack', 'estmemory': 12288}, + {'scheme': 'ml-dsa-44', 'implementation': 'm4f', 'estmemory': 57344}, + {'scheme': 'ml-dsa-87', 'implementation': 'clean', 'estmemory': 136192}, + {'scheme': 'ml-dsa-65', 'implementation': 'clean', 'estmemory': 90112}, + {'scheme': 'ml-dsa-44', 'implementation': 'clean', 'estmemory': 59392}, ] From 47fd99735bb0de83287211425fcd024cb4e38c67 Mon Sep 17 00:00:00 2001 From: Sangyub Lee Date: Thu, 31 Oct 2024 15:00:50 +0900 Subject: [PATCH 101/107] Add AIMer implementations(m4speed, m4stack) for all NIST security levels (#361) * Add AIMer implementations(m4speed, m4stack) for all NIST security levels * change aimer128f to symlinks * Symlinks updates for AIMer --------- Co-authored-by: Matthias J. Kannwischer --- crypto_sign/aimer128f/m4speed/__asm_field.S | 544 +++++++++++++++ crypto_sign/aimer128f/m4speed/aim2.c | 459 +++++++++++++ crypto_sign/aimer128f/m4speed/aim2.h | 307 +++++++++ crypto_sign/aimer128f/m4speed/api.h | 44 ++ crypto_sign/aimer128f/m4speed/field.c | 406 ++++++++++++ crypto_sign/aimer128f/m4speed/field.h | 41 ++ crypto_sign/aimer128f/m4speed/hash.c | 41 ++ crypto_sign/aimer128f/m4speed/hash.h | 35 + crypto_sign/aimer128f/m4speed/params.h | 28 + crypto_sign/aimer128f/m4speed/sign.c | 547 +++++++++++++++ crypto_sign/aimer128f/m4speed/sign.h | 69 ++ crypto_sign/aimer128f/m4speed/tree.c | 94 +++ crypto_sign/aimer128f/m4speed/tree.h | 26 + crypto_sign/aimer128f/m4stack/__asm_field.S | 1 + crypto_sign/aimer128f/m4stack/aim2.c | 1 + crypto_sign/aimer128f/m4stack/aim2.h | 1 + crypto_sign/aimer128f/m4stack/api.h | 1 + crypto_sign/aimer128f/m4stack/field.c | 1 + crypto_sign/aimer128f/m4stack/field.h | 1 + crypto_sign/aimer128f/m4stack/hash.c | 1 + crypto_sign/aimer128f/m4stack/hash.h | 1 + crypto_sign/aimer128f/m4stack/params.h | 28 + crypto_sign/aimer128f/m4stack/sign.c | 626 ++++++++++++++++++ crypto_sign/aimer128f/m4stack/sign.h | 73 ++ crypto_sign/aimer128f/m4stack/tree.c | 94 +++ crypto_sign/aimer128f/m4stack/tree.h | 28 + crypto_sign/aimer128s/m4speed/__asm_field.S | 1 + crypto_sign/aimer128s/m4speed/aim2.c | 1 + crypto_sign/aimer128s/m4speed/aim2.h | 1 + crypto_sign/aimer128s/m4speed/api.h | 44 ++ crypto_sign/aimer128s/m4speed/field.c | 1 + crypto_sign/aimer128s/m4speed/field.h | 1 + crypto_sign/aimer128s/m4speed/hash.c | 71 ++ crypto_sign/aimer128s/m4speed/hash.h | 37 ++ crypto_sign/aimer128s/m4speed/params.h | 30 + crypto_sign/aimer128s/m4speed/sign.c | 662 +++++++++++++++++++ crypto_sign/aimer128s/m4speed/sign.h | 82 +++ crypto_sign/aimer128s/m4speed/tree.c | 116 ++++ crypto_sign/aimer128s/m4speed/tree.h | 33 + crypto_sign/aimer128s/m4stack/__asm_field.S | 1 + crypto_sign/aimer128s/m4stack/aim2.c | 1 + crypto_sign/aimer128s/m4stack/aim2.h | 1 + crypto_sign/aimer128s/m4stack/api.h | 1 + crypto_sign/aimer128s/m4stack/field.c | 1 + crypto_sign/aimer128s/m4stack/field.h | 1 + crypto_sign/aimer128s/m4stack/hash.c | 1 + crypto_sign/aimer128s/m4stack/hash.h | 1 + crypto_sign/aimer128s/m4stack/params.h | 28 + crypto_sign/aimer128s/m4stack/sign.c | 626 ++++++++++++++++++ crypto_sign/aimer128s/m4stack/sign.h | 1 + crypto_sign/aimer128s/m4stack/tree.c | 1 + crypto_sign/aimer128s/m4stack/tree.h | 1 + crypto_sign/aimer192f/m4speed/__asm_field.S | 617 +++++++++++++++++ crypto_sign/aimer192f/m4speed/aim2.c | 491 ++++++++++++++ crypto_sign/aimer192f/m4speed/aim2.h | 435 ++++++++++++ crypto_sign/aimer192f/m4speed/api.h | 44 ++ crypto_sign/aimer192f/m4speed/field.c | 482 ++++++++++++++ crypto_sign/aimer192f/m4speed/field.h | 41 ++ crypto_sign/aimer192f/m4speed/hash.c | 41 ++ crypto_sign/aimer192f/m4speed/hash.h | 35 + crypto_sign/aimer192f/m4speed/params.h | 28 + crypto_sign/aimer192f/m4speed/sign.c | 549 ++++++++++++++++ crypto_sign/aimer192f/m4speed/sign.h | 1 + crypto_sign/aimer192f/m4speed/tree.c | 1 + crypto_sign/aimer192f/m4speed/tree.h | 1 + crypto_sign/aimer192f/m4stack/__asm_field.S | 1 + crypto_sign/aimer192f/m4stack/aim2.c | 1 + crypto_sign/aimer192f/m4stack/aim2.h | 1 + crypto_sign/aimer192f/m4stack/api.h | 1 + crypto_sign/aimer192f/m4stack/field.c | 1 + crypto_sign/aimer192f/m4stack/field.h | 1 + crypto_sign/aimer192f/m4stack/hash.c | 1 + crypto_sign/aimer192f/m4stack/hash.h | 1 + crypto_sign/aimer192f/m4stack/params.h | 28 + crypto_sign/aimer192f/m4stack/sign.c | 628 ++++++++++++++++++ crypto_sign/aimer192f/m4stack/sign.h | 1 + crypto_sign/aimer192f/m4stack/tree.c | 1 + crypto_sign/aimer192f/m4stack/tree.h | 1 + crypto_sign/aimer192s/m4speed/__asm_field.S | 1 + crypto_sign/aimer192s/m4speed/aim2.c | 1 + crypto_sign/aimer192s/m4speed/aim2.h | 1 + crypto_sign/aimer192s/m4speed/api.h | 44 ++ crypto_sign/aimer192s/m4speed/field.c | 1 + crypto_sign/aimer192s/m4speed/field.h | 1 + crypto_sign/aimer192s/m4speed/hash.c | 71 ++ crypto_sign/aimer192s/m4speed/hash.h | 37 ++ crypto_sign/aimer192s/m4speed/params.h | 30 + crypto_sign/aimer192s/m4speed/sign.c | 664 +++++++++++++++++++ crypto_sign/aimer192s/m4speed/sign.h | 1 + crypto_sign/aimer192s/m4speed/tree.c | 1 + crypto_sign/aimer192s/m4speed/tree.h | 1 + crypto_sign/aimer192s/m4stack/__asm_field.S | 1 + crypto_sign/aimer192s/m4stack/aim2.c | 1 + crypto_sign/aimer192s/m4stack/aim2.h | 1 + crypto_sign/aimer192s/m4stack/api.h | 1 + crypto_sign/aimer192s/m4stack/field.c | 1 + crypto_sign/aimer192s/m4stack/field.h | 1 + crypto_sign/aimer192s/m4stack/hash.c | 1 + crypto_sign/aimer192s/m4stack/hash.h | 1 + crypto_sign/aimer192s/m4stack/params.h | 28 + crypto_sign/aimer192s/m4stack/sign.c | 628 ++++++++++++++++++ crypto_sign/aimer192s/m4stack/sign.h | 1 + crypto_sign/aimer192s/m4stack/tree.c | 1 + crypto_sign/aimer192s/m4stack/tree.h | 1 + crypto_sign/aimer256f/m4speed/__asm_field.S | 695 ++++++++++++++++++++ crypto_sign/aimer256f/m4speed/aim2.c | 598 +++++++++++++++++ crypto_sign/aimer256f/m4speed/aim2.h | 306 +++++++++ crypto_sign/aimer256f/m4speed/api.h | 44 ++ crypto_sign/aimer256f/m4speed/field.c | 608 +++++++++++++++++ crypto_sign/aimer256f/m4speed/field.h | 41 ++ crypto_sign/aimer256f/m4speed/hash.c | 1 + crypto_sign/aimer256f/m4speed/hash.h | 1 + crypto_sign/aimer256f/m4speed/params.h | 28 + crypto_sign/aimer256f/m4speed/sign.c | 573 ++++++++++++++++ crypto_sign/aimer256f/m4speed/sign.h | 1 + crypto_sign/aimer256f/m4speed/tree.c | 1 + crypto_sign/aimer256f/m4speed/tree.h | 1 + crypto_sign/aimer256f/m4stack/__asm_field.S | 1 + crypto_sign/aimer256f/m4stack/aim2.c | 1 + crypto_sign/aimer256f/m4stack/aim2.h | 1 + crypto_sign/aimer256f/m4stack/api.h | 1 + crypto_sign/aimer256f/m4stack/field.c | 1 + crypto_sign/aimer256f/m4stack/field.h | 1 + crypto_sign/aimer256f/m4stack/hash.c | 1 + crypto_sign/aimer256f/m4stack/hash.h | 1 + crypto_sign/aimer256f/m4stack/params.h | 28 + crypto_sign/aimer256f/m4stack/sign.c | 654 ++++++++++++++++++ crypto_sign/aimer256f/m4stack/sign.h | 1 + crypto_sign/aimer256f/m4stack/tree.c | 1 + crypto_sign/aimer256f/m4stack/tree.h | 1 + crypto_sign/aimer256s/m4speed/__asm_field.S | 1 + crypto_sign/aimer256s/m4speed/aim2.c | 1 + crypto_sign/aimer256s/m4speed/aim2.h | 1 + crypto_sign/aimer256s/m4speed/api.h | 44 ++ crypto_sign/aimer256s/m4speed/field.c | 1 + crypto_sign/aimer256s/m4speed/field.h | 1 + crypto_sign/aimer256s/m4speed/hash.c | 1 + crypto_sign/aimer256s/m4speed/hash.h | 1 + crypto_sign/aimer256s/m4speed/params.h | 30 + crypto_sign/aimer256s/m4speed/sign.c | 690 +++++++++++++++++++ crypto_sign/aimer256s/m4speed/sign.h | 1 + crypto_sign/aimer256s/m4speed/tree.c | 1 + crypto_sign/aimer256s/m4speed/tree.h | 1 + crypto_sign/aimer256s/m4stack/__asm_field.S | 1 + crypto_sign/aimer256s/m4stack/aim2.c | 1 + crypto_sign/aimer256s/m4stack/aim2.h | 1 + crypto_sign/aimer256s/m4stack/api.h | 1 + crypto_sign/aimer256s/m4stack/field.c | 1 + crypto_sign/aimer256s/m4stack/field.h | 1 + crypto_sign/aimer256s/m4stack/hash.c | 1 + crypto_sign/aimer256s/m4stack/hash.h | 1 + crypto_sign/aimer256s/m4stack/params.h | 28 + crypto_sign/aimer256s/m4stack/sign.c | 654 ++++++++++++++++++ crypto_sign/aimer256s/m4stack/sign.h | 1 + crypto_sign/aimer256s/m4stack/tree.c | 1 + crypto_sign/aimer256s/m4stack/tree.h | 1 + 156 files changed, 15255 insertions(+) create mode 100644 crypto_sign/aimer128f/m4speed/__asm_field.S create mode 100644 crypto_sign/aimer128f/m4speed/aim2.c create mode 100644 crypto_sign/aimer128f/m4speed/aim2.h create mode 100644 crypto_sign/aimer128f/m4speed/api.h create mode 100644 crypto_sign/aimer128f/m4speed/field.c create mode 100644 crypto_sign/aimer128f/m4speed/field.h create mode 100644 crypto_sign/aimer128f/m4speed/hash.c create mode 100644 crypto_sign/aimer128f/m4speed/hash.h create mode 100644 crypto_sign/aimer128f/m4speed/params.h create mode 100644 crypto_sign/aimer128f/m4speed/sign.c create mode 100644 crypto_sign/aimer128f/m4speed/sign.h create mode 100644 crypto_sign/aimer128f/m4speed/tree.c create mode 100644 crypto_sign/aimer128f/m4speed/tree.h create mode 120000 crypto_sign/aimer128f/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer128f/m4stack/aim2.c create mode 120000 crypto_sign/aimer128f/m4stack/aim2.h create mode 120000 crypto_sign/aimer128f/m4stack/api.h create mode 120000 crypto_sign/aimer128f/m4stack/field.c create mode 120000 crypto_sign/aimer128f/m4stack/field.h create mode 120000 crypto_sign/aimer128f/m4stack/hash.c create mode 120000 crypto_sign/aimer128f/m4stack/hash.h create mode 100644 crypto_sign/aimer128f/m4stack/params.h create mode 100644 crypto_sign/aimer128f/m4stack/sign.c create mode 100644 crypto_sign/aimer128f/m4stack/sign.h create mode 100644 crypto_sign/aimer128f/m4stack/tree.c create mode 100644 crypto_sign/aimer128f/m4stack/tree.h create mode 120000 crypto_sign/aimer128s/m4speed/__asm_field.S create mode 120000 crypto_sign/aimer128s/m4speed/aim2.c create mode 120000 crypto_sign/aimer128s/m4speed/aim2.h create mode 100644 crypto_sign/aimer128s/m4speed/api.h create mode 120000 crypto_sign/aimer128s/m4speed/field.c create mode 120000 crypto_sign/aimer128s/m4speed/field.h create mode 100644 crypto_sign/aimer128s/m4speed/hash.c create mode 100644 crypto_sign/aimer128s/m4speed/hash.h create mode 100644 crypto_sign/aimer128s/m4speed/params.h create mode 100644 crypto_sign/aimer128s/m4speed/sign.c create mode 100644 crypto_sign/aimer128s/m4speed/sign.h create mode 100644 crypto_sign/aimer128s/m4speed/tree.c create mode 100644 crypto_sign/aimer128s/m4speed/tree.h create mode 120000 crypto_sign/aimer128s/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer128s/m4stack/aim2.c create mode 120000 crypto_sign/aimer128s/m4stack/aim2.h create mode 120000 crypto_sign/aimer128s/m4stack/api.h create mode 120000 crypto_sign/aimer128s/m4stack/field.c create mode 120000 crypto_sign/aimer128s/m4stack/field.h create mode 120000 crypto_sign/aimer128s/m4stack/hash.c create mode 120000 crypto_sign/aimer128s/m4stack/hash.h create mode 100644 crypto_sign/aimer128s/m4stack/params.h create mode 100644 crypto_sign/aimer128s/m4stack/sign.c create mode 120000 crypto_sign/aimer128s/m4stack/sign.h create mode 120000 crypto_sign/aimer128s/m4stack/tree.c create mode 120000 crypto_sign/aimer128s/m4stack/tree.h create mode 100644 crypto_sign/aimer192f/m4speed/__asm_field.S create mode 100644 crypto_sign/aimer192f/m4speed/aim2.c create mode 100644 crypto_sign/aimer192f/m4speed/aim2.h create mode 100644 crypto_sign/aimer192f/m4speed/api.h create mode 100644 crypto_sign/aimer192f/m4speed/field.c create mode 100644 crypto_sign/aimer192f/m4speed/field.h create mode 100644 crypto_sign/aimer192f/m4speed/hash.c create mode 100644 crypto_sign/aimer192f/m4speed/hash.h create mode 100644 crypto_sign/aimer192f/m4speed/params.h create mode 100644 crypto_sign/aimer192f/m4speed/sign.c create mode 120000 crypto_sign/aimer192f/m4speed/sign.h create mode 120000 crypto_sign/aimer192f/m4speed/tree.c create mode 120000 crypto_sign/aimer192f/m4speed/tree.h create mode 120000 crypto_sign/aimer192f/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer192f/m4stack/aim2.c create mode 120000 crypto_sign/aimer192f/m4stack/aim2.h create mode 120000 crypto_sign/aimer192f/m4stack/api.h create mode 120000 crypto_sign/aimer192f/m4stack/field.c create mode 120000 crypto_sign/aimer192f/m4stack/field.h create mode 120000 crypto_sign/aimer192f/m4stack/hash.c create mode 120000 crypto_sign/aimer192f/m4stack/hash.h create mode 100644 crypto_sign/aimer192f/m4stack/params.h create mode 100644 crypto_sign/aimer192f/m4stack/sign.c create mode 120000 crypto_sign/aimer192f/m4stack/sign.h create mode 120000 crypto_sign/aimer192f/m4stack/tree.c create mode 120000 crypto_sign/aimer192f/m4stack/tree.h create mode 120000 crypto_sign/aimer192s/m4speed/__asm_field.S create mode 120000 crypto_sign/aimer192s/m4speed/aim2.c create mode 120000 crypto_sign/aimer192s/m4speed/aim2.h create mode 100644 crypto_sign/aimer192s/m4speed/api.h create mode 120000 crypto_sign/aimer192s/m4speed/field.c create mode 120000 crypto_sign/aimer192s/m4speed/field.h create mode 100644 crypto_sign/aimer192s/m4speed/hash.c create mode 100644 crypto_sign/aimer192s/m4speed/hash.h create mode 100644 crypto_sign/aimer192s/m4speed/params.h create mode 100644 crypto_sign/aimer192s/m4speed/sign.c create mode 120000 crypto_sign/aimer192s/m4speed/sign.h create mode 120000 crypto_sign/aimer192s/m4speed/tree.c create mode 120000 crypto_sign/aimer192s/m4speed/tree.h create mode 120000 crypto_sign/aimer192s/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer192s/m4stack/aim2.c create mode 120000 crypto_sign/aimer192s/m4stack/aim2.h create mode 120000 crypto_sign/aimer192s/m4stack/api.h create mode 120000 crypto_sign/aimer192s/m4stack/field.c create mode 120000 crypto_sign/aimer192s/m4stack/field.h create mode 120000 crypto_sign/aimer192s/m4stack/hash.c create mode 120000 crypto_sign/aimer192s/m4stack/hash.h create mode 100644 crypto_sign/aimer192s/m4stack/params.h create mode 100644 crypto_sign/aimer192s/m4stack/sign.c create mode 120000 crypto_sign/aimer192s/m4stack/sign.h create mode 120000 crypto_sign/aimer192s/m4stack/tree.c create mode 120000 crypto_sign/aimer192s/m4stack/tree.h create mode 100644 crypto_sign/aimer256f/m4speed/__asm_field.S create mode 100644 crypto_sign/aimer256f/m4speed/aim2.c create mode 100644 crypto_sign/aimer256f/m4speed/aim2.h create mode 100644 crypto_sign/aimer256f/m4speed/api.h create mode 100644 crypto_sign/aimer256f/m4speed/field.c create mode 100644 crypto_sign/aimer256f/m4speed/field.h create mode 120000 crypto_sign/aimer256f/m4speed/hash.c create mode 120000 crypto_sign/aimer256f/m4speed/hash.h create mode 100644 crypto_sign/aimer256f/m4speed/params.h create mode 100644 crypto_sign/aimer256f/m4speed/sign.c create mode 120000 crypto_sign/aimer256f/m4speed/sign.h create mode 120000 crypto_sign/aimer256f/m4speed/tree.c create mode 120000 crypto_sign/aimer256f/m4speed/tree.h create mode 120000 crypto_sign/aimer256f/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer256f/m4stack/aim2.c create mode 120000 crypto_sign/aimer256f/m4stack/aim2.h create mode 120000 crypto_sign/aimer256f/m4stack/api.h create mode 120000 crypto_sign/aimer256f/m4stack/field.c create mode 120000 crypto_sign/aimer256f/m4stack/field.h create mode 120000 crypto_sign/aimer256f/m4stack/hash.c create mode 120000 crypto_sign/aimer256f/m4stack/hash.h create mode 100644 crypto_sign/aimer256f/m4stack/params.h create mode 100644 crypto_sign/aimer256f/m4stack/sign.c create mode 120000 crypto_sign/aimer256f/m4stack/sign.h create mode 120000 crypto_sign/aimer256f/m4stack/tree.c create mode 120000 crypto_sign/aimer256f/m4stack/tree.h create mode 120000 crypto_sign/aimer256s/m4speed/__asm_field.S create mode 120000 crypto_sign/aimer256s/m4speed/aim2.c create mode 120000 crypto_sign/aimer256s/m4speed/aim2.h create mode 100644 crypto_sign/aimer256s/m4speed/api.h create mode 120000 crypto_sign/aimer256s/m4speed/field.c create mode 120000 crypto_sign/aimer256s/m4speed/field.h create mode 120000 crypto_sign/aimer256s/m4speed/hash.c create mode 120000 crypto_sign/aimer256s/m4speed/hash.h create mode 100644 crypto_sign/aimer256s/m4speed/params.h create mode 100644 crypto_sign/aimer256s/m4speed/sign.c create mode 120000 crypto_sign/aimer256s/m4speed/sign.h create mode 120000 crypto_sign/aimer256s/m4speed/tree.c create mode 120000 crypto_sign/aimer256s/m4speed/tree.h create mode 120000 crypto_sign/aimer256s/m4stack/__asm_field.S create mode 120000 crypto_sign/aimer256s/m4stack/aim2.c create mode 120000 crypto_sign/aimer256s/m4stack/aim2.h create mode 120000 crypto_sign/aimer256s/m4stack/api.h create mode 120000 crypto_sign/aimer256s/m4stack/field.c create mode 120000 crypto_sign/aimer256s/m4stack/field.h create mode 120000 crypto_sign/aimer256s/m4stack/hash.c create mode 120000 crypto_sign/aimer256s/m4stack/hash.h create mode 100644 crypto_sign/aimer256s/m4stack/params.h create mode 100644 crypto_sign/aimer256s/m4stack/sign.c create mode 120000 crypto_sign/aimer256s/m4stack/sign.h create mode 120000 crypto_sign/aimer256s/m4stack/tree.c create mode 120000 crypto_sign/aimer256s/m4stack/tree.h diff --git a/crypto_sign/aimer128f/m4speed/__asm_field.S b/crypto_sign/aimer128f/m4speed/__asm_field.S new file mode 100644 index 00000000..05656b37 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/__asm_field.S @@ -0,0 +1,544 @@ +#include "params.h" + +.syntax unified +.cpu cortex-m4 +.thumb + +.text + +.align 2 +.global AIMER_NAMESPACE(GF_to_bytes) +.global AIMER_NAMESPACE(GF_from_bytes) +.global AIMER_NAMESPACE(GF_copy) +.type AIMER_NAMESPACE(GF_to_bytes), %function +.type AIMER_NAMESPACE(GF_from_bytes), %function +.type AIMER_NAMESPACE(GF_copy), %function +AIMER_NAMESPACE(GF_to_bytes): +AIMER_NAMESPACE(GF_from_bytes): +AIMER_NAMESPACE(GF_copy): + out_p .req R0 + in_p .req R1 + + .equ width, 4 + + ldr.w R2, [in_p, #0 * width] + ldr.w R3, [in_p, #1 * width] + str.w R2, [out_p, #0 * width] + str.w R3, [out_p, #1 * width] + + ldr.w R2, [in_p, #2 * width] + ldr.w R3, [in_p, #3 * width] + str.w R2, [out_p, #2 * width] + str.w R3, [out_p, #3 * width] + + bx lr + + .unreq in_p + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_set0) +.type AIMER_NAMESPACE(GF_set0), %function +AIMER_NAMESPACE(GF_set0): + out_p .req R0 + + .equ width, 4 + + mov.w R2, #0 + str.w R2, [out_p, #0 * width] + str.w R2, [out_p, #1 * width] + str.w R2, [out_p, #2 * width] + str.w R2, [out_p, #3 * width] + + bx lr + + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_add) +.type AIMER_NAMESPACE(GF_add), %function +AIMER_NAMESPACE(GF_add): + out_p .req R0 + in0_p .req R1 + in1_p .req R2 + + .equ width, 4 + + ldr.w R3, [in0_p, #0 * width] + ldr.w R12, [in1_p, #0 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #0 * width] + + ldr.w R3, [in0_p, #1 * width] + ldr.w R12, [in1_p, #1 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #1 * width] + + ldr.w R3, [in0_p, #2 * width] + ldr.w R12, [in1_p, #2 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #2 * width] + + ldr.w R3, [in0_p, #3 * width] + ldr.w R12, [in1_p, #3 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #3 * width] + + bx lr + + .unreq out_p + .unreq in0_p + .unreq in1_p + +.macro or_shift_and in_a, con_a, off_a + orr.w \in_a, \in_a, \in_a, lsl #\off_a + and.w \in_a, \in_a, \con_a +.endm + +.align 2 +.global AIMER_NAMESPACE(GF_sqr_s) +.type AIMER_NAMESPACE(GF_sqr_s), %function +AIMER_NAMESPACE(GF_sqr_s): + out_p .req R0 + in_p .req R1 + + in0 .req R2 + in1 .req R3 + in2 .req R4 + in3 .req R5 + in4 .req R6 + in5 .req R7 + in6 .req R8 + in7 .req R9 + + .equ C0, 1431655765 // 0x55555555 + .equ C1, 858993459 // 0x33333333 + .equ C2, 252645135 // 0x0F0F0F0F + .equ C3, 16711935 // 0x00FF00FF + .equ C4, 4294967295 // 0xFFFFFFFF + .equ width, 4 + + push.w {R4-R10, lr} + + ldr.w in0, [in_p, #0 * width] // a[0] + ldr.w in2, [in_p, #1 * width] + ldr.w in4, [in_p, #2 * width] // a[1] + ldr.w in6, [in_p, #3 * width] + + lsr.w in1, in0, #16 + lsr.w in3, in2, #16 + lsr.w in5, in4, #16 + lsr.w in7, in6, #16 + + mov.w R10, C4 + + and.w in0, in0, R10, lsr #16 + and.w in2, in2, R10, lsr #16 + and.w in4, in4, R10, lsr #16 + and.w in6, in6, R10, lsr #16 + + or_shift_and in0, C3, 8 + or_shift_and in1, C3, 8 + or_shift_and in2, C3, 8 + or_shift_and in3, C3, 8 + or_shift_and in4, C3, 8 + or_shift_and in5, C3, 8 + or_shift_and in6, C3, 8 + or_shift_and in7, C3, 8 + + or_shift_and in0, C2, 4 + or_shift_and in1, C2, 4 + or_shift_and in2, C2, 4 + or_shift_and in3, C2, 4 + or_shift_and in4, C2, 4 + or_shift_and in5, C2, 4 + or_shift_and in6, C2, 4 + or_shift_and in7, C2, 4 + + or_shift_and in0, C1, 2 + or_shift_and in1, C1, 2 + or_shift_and in2, C1, 2 + or_shift_and in3, C1, 2 + or_shift_and in4, C1, 2 + or_shift_and in5, C1, 2 + or_shift_and in6, C1, 2 + or_shift_and in7, C1, 2 + + or_shift_and in0, C0, 1 + or_shift_and in1, C0, 1 + or_shift_and in2, C0, 1 + or_shift_and in3, C0, 1 + or_shift_and in4, C0, 1 + or_shift_and in5, C0, 1 + or_shift_and in6, C0, 1 + or_shift_and in7, C0, 1 + + // t = temp[2] ^ ((temp[3] >> 57) ^ (temp[3] >> 62) ^ (temp[3] >> 63)); + eor.w in4, in4, in7, lsr #25 + eor.w in4, in4, in7, lsr #30 + eor.w in4, in4, in7, lsr #31 + + // c[1] = temp[1] ^ temp[3]; + eor.w in2, in2, in6 + eor.w in3, in3, in7 + + // c[1] ^= (temp[3] << 7) | (t >> 57); + // c[1] ^= (temp[3] << 2) | (t >> 62); + // c[1] ^= (temp[3] << 1) | (t >> 63); + eor.w in2, in2, in5, lsr #25 + eor.w in2, in2, in5, lsr #30 + eor.w in2, in2, in5, lsr #31 + + eor.w in2, in2, in6, lsl #7 + eor.w in2, in2, in6, lsl #2 + eor.w in2, in2, in6, lsl #1 + + eor.w in3, in3, in6, lsr #25 + eor.w in3, in3, in6, lsr #30 + eor.w in3, in3, in6, lsr #31 + + eor.w in3, in3, in7, lsl #7 + eor.w in3, in3, in7, lsl #2 + eor.w in3, in3, in7, lsl #1 + + // c[0] = temp[0] ^ t; + eor.w in0, in0, in4 + eor.w in1, in1, in5 + + // c[0] ^= (t << 7); + // c[0] ^= (t << 2); + // c[0] ^= (t << 1); + eor.w in0, in0, in4, lsl #7 + eor.w in0, in0, in4, lsl #2 + eor.w in0, in0, in4, lsl #1 + + eor.w in1, in1, in4, lsr #25 + eor.w in1, in1, in4, lsr #30 + eor.w in1, in1, in4, lsr #31 + + eor.w in1, in1, in5, lsl #7 + eor.w in1, in1, in5, lsl #2 + eor.w in1, in1, in5, lsl #1 + + str.w in0, [out_p, #0 * width] + str.w in1, [out_p, #1 * width] + str.w in2, [out_p, #2 * width] + str.w in3, [out_p, #3 * width] + + pop.w {R4-R10, pc} + + // unlink register name + .unreq in_p + .unreq out_p + +.macro lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + ldr \out1_0, [\sp1, #0] + ldr \in0_2, [\sp1, #4] + + ldr \in0_0, [\sp0, #0] + ldr \in0_1, [\sp0, #4] + eor \in0_1, \in0_1, \out1_0 +.endm + +.macro lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + lsr \in0_3, \in0_2, #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + lsl \in0_3, \in0_3, #4 + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + orr \in0_3, \in0_3, \in0_2, lsr #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + lsl \in0_3, \in0_3, #4 + and \sp1, \mask, \b0_1, lsl #\offset + orr \in0_3, \in0_3, \in0_2, lsr #28 + and \sp0, \mask, \b0_0, lsl #\offset + + lsl \in0_2, \in0_2, #4 + add \sp1, \sp1, sp + orr \in0_2, \in0_2, \in0_1, lsr #28 + add \sp0, \sp0, sp + + lsl \in0_1, \in0_1, #4 + ldmia \sp1, {\out1_0-\out1_1} + orr \in0_1, \in0_1, \in0_0, lsr #28 + ldmia \sp0, {\out0_0-\out0_1} + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + and \mask, \one, \r0_ret, lsr #\offset + sub \mask, \zero, \mask + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.macro last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + sub \mask, \zero, \r0_ret, lsr #\offset + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.global AIMER_NAMESPACE(poly64_mul) +.type AIMER_NAMESPACE(poly64_mul), %function +AIMER_NAMESPACE(poly64_mul): + t0_0 .req R0 + t0_1 .req R1 + t1_0 .req R2 + t1_1 .req R3 + t2_0 .req R4 + t2_1 .req R5 + t3_0 .req R6 + t3_1 .req R7 + t4_0 .req R8 + t4_1 .req R9 + t5_0 .req R10 + t5_1 .req R11 + + r1_copy .req R12 + t_base .req R14 + + sp0 .req R12 + sp1 .req R14 + + b0_0 .req R0 + b0_1 .req R1 + + in0_0 .req R2 + in0_1 .req R3 + in0_2 .req R4 + in0_3 .req R5 + + out0_0 .req R6 + out0_1 .req R7 + out1_0 .req R8 + out1_1 .req R9 + + mask .req R10 + + zero .req R6 + one .req R7 + + r0_ret .req R8 + + mask0_0 .req R9 + mask0_1 .req R11 + mask0_2 .req R12 + + push {R4-R11, lr} + push {R2-R3} + + ldr t1_0, [R0, #0] + ldr t1_1, [R0, #4] + push {t1_1} + + sub sp, #128 // allocating space in the stack + // 8 bytes * 16 = 128 bytes + mov t_base, sp + mov r1_copy, R1 + + mov t0_0, #0 + mov t0_1, #0 + + and t1_1, #0x1FFFFFFF + + lsl t2_1, t1_1, #1 + orr t2_1, t2_1, t1_0, lsr #31 + lsl t2_0, t1_0, #1 + + eor t3_0, t1_0, t2_0 + eor t3_1, t1_1, t2_1 + + lsl t4_1, t2_1, #1 + orr t4_1, t4_1, t2_0, lsr #31 + lsl t4_0, t2_0, #1 + + eor t5_0, t1_0, t4_0 + eor t5_1, t1_1, t4_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t0_0, t2_0, t4_0 + eor t0_1, t2_1, t4_1 + + lsl t2_1, t4_1, #1 + orr t2_1, t2_1, t4_0, lsr #31 + lsl t2_0, t4_0, #1 + + eor t5_0, t2_0, t3_0 + eor t5_1, t2_1, t3_1 + + eor t3_0, t2_0, t1_0 + eor t3_1, t2_1, t1_1 + + eor t4_0, t4_0, t0_0 + eor t4_1, t4_1, t0_1 + + eor t4_0, t4_0, t2_0 + eor t4_1, t4_1, t2_1 + + eor t1_0, t1_0, t0_0 + eor t1_1, t1_1, t0_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t1_0, t5_0, t0_0 + eor t1_1, t5_1, t0_1 + + eor t2_0, t2_0, t0_0 + eor t2_1, t2_1, t0_1 + + eor t3_0, t3_0, t0_0 + eor t3_1, t3_1, t0_1 + + eor t0_0, t4_0, t0_0 + eor t0_1, t4_1, t0_1 + + stmia t_base, {t0_0-t3_1} // 4 bytes X 8 elements = 32 bytes + + ldmia r1_copy, {b0_0-b0_1} + mov mask, #0x00000078 + + lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 25 + lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 21 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 17 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 13 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 9 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 5 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 1 + lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 3 + + mov zero, #0 + mov one, #1 + ldr r0_ret, [sp, #128] + + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 29 + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 30 + last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 31 + + ldr R0, [sp, #132] + ldr R1, [sp, #136] + add sp, #140 // restoring stack + + str in0_0, [R1, #0] + str in0_1, [R1, #4] + + str in0_2, [R0, #0] + str in0_3, [R0, #4] + + pop {R4-R11, pc} + + // unlink register name + .unreq t0_0 + .unreq t0_1 + .unreq t1_0 + .unreq t1_1 + .unreq t2_0 + .unreq t2_1 + .unreq t3_0 + .unreq t3_1 + .unreq t4_0 + .unreq t4_1 + .unreq t5_0 + .unreq t5_1 + + .unreq r1_copy + .unreq t_base + + .unreq sp0 + .unreq sp1 + + .unreq b0_0 + .unreq b0_1 + + .unreq in0_0 + .unreq in0_1 + .unreq in0_2 + .unreq in0_3 + + .unreq out0_0 + .unreq out0_1 + .unreq out1_0 + .unreq out1_1 + + .unreq mask + + .unreq zero + .unreq one + + .unreq r0_ret + + .unreq mask0_0 + .unreq mask0_1 + .unreq mask0_2 diff --git a/crypto_sign/aimer128f/m4speed/aim2.c b/crypto_sign/aimer128f/m4speed/aim2.c new file mode 100644 index 00000000..7cb00352 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/aim2.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: MIT + +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +// inverse Mersenne S-box with e1 = 49 +// (2 ^ 49 - 1) ^ (-1) mod (2 ^ 128 - 1) = 0xb6b6d6d6dadb5b5b6b6b6d6dadadb5b5 +// b6b6d6d 6 d a d b5 b5 b6 b6b6d6d a d a d b5 b5 +void GF_exp_invmer_e_1(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}, t2 = {0,}; + GF table_5 = {0,}, table_6 = {0,}; + GF table_a = {0,}, table_b = {0,}, table_d = {0,}; + + // t1 = in ^ 4 + GF_sqr_s(table_d, in); + GF_sqr_s(t1, table_d); + + // table_5 = in ^ 5 + GF_mul_s(table_5, t1, in); + // table_6 = in ^ 6 + GF_mul_s(table_6, table_5, in); + // table_a = in ^ 10 = (in ^ 5) ^ 2 + GF_sqr_s(table_a, table_5); + // table_b = in ^ 11 + GF_mul_s(table_b, table_a, in); + // table_d = in ^ 13 + GF_mul_s(table_d, table_b, table_d); + + // table_b = in ^ (0xb6), table_5 = in ^ (0xb5) + GF_sqr_s(t1, table_b); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_b, t1, table_6); + GF_mul_s(table_5, t1, table_5); + + // t1 = in ^ (0xb6b6) + GF_sqr_s(t1, table_b); + for (i = 1; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6b6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6b6d 6) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t2 = in ^ (0xb6b6d6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t2, t1, table_d); + + // t1 = in ^ (0xb6b6d6d 6) + GF_sqr_s(t1, t2); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xb6b6d6d6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6b6d6d6d a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6b6d6d6da d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6b6d6d6dad b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6b6d6d6dadb5 b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6b6d6d6dadb5b5 b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6 b6b6d6d) + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6d a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6da d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6dad a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6dada d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6dadad b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6b6d6d6dadb5b5b6b6b6d6dadadb5 b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, table_5); +} + +// inverse Mersenne S-box with e2 = 91 +// (2 ^ 91 - 1) ^ (-1) mod (2 ^ 128 - 1) = 0xb6db5b6dadb6dadb6d6db6d6db6b6db5 +// b6d b5 b6d a d b6d a d b6d 6 d b6d 6 d b6 b6d b5 +void GF_exp_invmer_e_2(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}, t2 = {0,}, t3 = {0,}; + GF table_5 = {0,}, table_6 = {0,}; + GF table_a = {0,}, table_b = {0,}, table_d = {0,}; + + // t1 = in ^ 4 + GF_sqr_s(table_d, in); + GF_sqr_s(t1, table_d); + + // table_5 = in ^ 5 + GF_mul_s(table_5, t1, in); + // table_6 = in ^ 6 + GF_mul_s(table_6, table_5, in); + // table_a = in ^ 10 = (in ^ 5) ^ 2 + GF_sqr_s(table_a, table_5); + // table_b = in ^ 11 + GF_mul_s(table_b, table_a, in); + // table_d = in ^ 13 + GF_mul_s(table_d, table_b, table_d); + + // t3 = in ^ (0xb6), table_b = in ^ (0xb5) + GF_sqr_s(t1, table_b); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_b, t1, table_5); + GF_mul_s(t3, t1, table_6); + + // t2 = in ^ (0xb6 d) + GF_sqr_s(t1, t3); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t2, t1, table_d); + + // t1 = in ^ (0xb6d b5) + GF_sqr_s(t1, t2); + for (i = 1; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6db5 b6d) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xb6db5b6d a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6db5b6da d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6db5b6dad b6d) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xb6db5b6dadb6d a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6db5b6dadb6da d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6db5b6dadb6dad b6d) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d 6) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6d b6d) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6db6d 6) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6db6d6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6db6d6d b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t3); + + // t1 = in ^ (0xb6db5b6dadb6dadb6d6db6d6db6 b6d) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // out = in ^ (0xb6db5b6dadb6dadb6d6db6d6db6b6d b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, table_b); +} + +// Mersenne exponentiation with e_star = 3 +void GF_exp_mer_e_star(GF out, const GF in) +{ + GF t1 = {0,}; + + // t1 = a ^ (2 ^ 2 - 1) + GF_sqr_s(t1, in); + GF_mul_s(t1, t1, in); + + // out = a ^ (2 ^ 3 - 1) + GF_sqr_s(t1, t1); + GF_mul_s(out, t1, in); +} + +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + uint8_t buf[AIM2_NUM_BYTES_FIELD]; + uint64_t ormask, lmask, umask; + hash_instance ctx; + GF temp = {0,}; + + // initialize hash + hash_init(&ctx); + hash_update(&ctx, iv, AIM2_IV_SIZE); + hash_final(&ctx); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t row = 0; row < AIM2_NUM_BITS_FIELD; row++) + { + hash_squeeze(&ctx, buf, AIM2_NUM_BYTES_FIELD); + GF_from_bytes(temp, buf); + + ormask = ((uint64_t)1) << (row % 64); + lmask = ((uint64_t)-1) << (row % 64); + umask = ~lmask; + + size_t inter = row / 64; + size_t col_word; + for (col_word = 0; col_word < inter; col_word++) + { + // L is zero, U is full + matrix_L[num][row][col_word] = 0; + matrix_U[num][row][col_word] = temp[col_word]; + } + matrix_L[num][row][inter] = (temp[inter] & lmask) | ormask; + matrix_U[num][row][inter] = (temp[inter] & umask) | ormask; + for (col_word = inter + 1; col_word < AIM2_NUM_WORDS_FIELD; col_word++) + { + // L is full, U is zero + matrix_L[num][row][col_word] = temp[col_word]; + matrix_U[num][row][col_word] = 0; + } + } + } + + hash_squeeze(&ctx, (uint8_t *)vector_b, AIM2_NUM_BYTES_FIELD); + hash_ctx_release(&ctx); +} + +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t i = 0; i < AIM2_NUM_BITS_FIELD; i++) + { + GF_transposed_matmul(matrix_A[num][i], matrix_U[num][i], + (const GF *)matrix_L[num]); + } + } +} + +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + + GF state[AIM2_NUM_INPUT_SBOX]; + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, pt); + + // generate random matrix + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + // linear component: constant addition + GF_add(state[0], pt_GF, aim2_constants[0]); + GF_add(state[1], pt_GF, aim2_constants[1]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(state[0], state[0]); + GF_exp_invmer_e_2(state[1], state[1]); + + // linear component: affine layer + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_U[0]); + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_L[0]); + + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_U[1]); + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_L[1]); + + GF_add(state[0], state[0], state[1]); + GF_add(state[0], state[0], vector_b); + + // non-linear component: Mersenne S-box + GF_exp_mer_e_star(state[0], state[0]); + + // linear component: feed-forward + GF_add(ct_GF, state[0], pt_GF); + + GF_to_bytes(ct, ct_GF); +} + +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt) +{ + // linear component: constant addition + GF_add(sbox_outputs[0], pt, aim2_constants[0]); + GF_add(sbox_outputs[1], pt, aim2_constants[1]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(sbox_outputs[0], sbox_outputs[0]); + GF_exp_invmer_e_2(sbox_outputs[1], sbox_outputs[1]); +} diff --git a/crypto_sign/aimer128f/m4speed/aim2.h b/crypto_sign/aimer128f/m4speed/aim2.h new file mode 100644 index 00000000..5564fc71 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/aim2.h @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: MIT + +#ifndef AIM2_H +#define AIM2_H + +#include "field.h" +#include "params.h" +#include + +static const GF aim2_constants[AIM2_NUM_INPUT_SBOX] = +{ + {0x13198a2e03707344, 0x243f6a8885a308d3}, + {0x082efa98ec4e6c89, 0xa4093822299f31d0}, +}; + +static const GF aim2_e1_power_matrix[AIM2_NUM_BITS_FIELD] = +{ + {0x0000000000000001, 0x0000000000000000}, + {0xb87c1159421de6c0, 0xfbcf8c1e442c8cf5}, + {0x687634c0bd8f66a6, 0x4d328e5ae8b1bde5}, + {0x742a6036d93c2057, 0x08974511b147a2fe}, + {0xc8b21bf16608e4db, 0x4d758c29eeb484f7}, + {0x0b5c6d5c43980a3c, 0x82739c986dfbdb20}, + {0x0ace7f98da3711b9, 0x34f149a76cf782b0}, + {0x321995ec53ea9914, 0xc2ff5007f8a98c83}, + {0x939b53119c4b7496, 0x097da6d2e8f7686d}, + {0x5fb6dd3ca90cff95, 0x10f77bb9e7748ed3}, + {0x55194932141d0937, 0xc253f8ea7ac0779a}, + {0xb2a4b4591251916b, 0xdfef8e3e1b142c07}, + {0x14df24dfc33e1f4f, 0x931f7bdb443197a1}, + {0xbd4cbe8b919dbb07, 0x24128da6bf057bc8}, + {0x1be6a922a8d0d7d4, 0xb7330162b6115e90}, + {0xb6d9e6635ec916aa, 0x930f20cea1c668e0}, + {0xccbb31a458da0423, 0x60488351c7403436}, + {0xef86b4dbc4263e4d, 0x9237f55823767eae}, + {0xe2a0e301bed0748a, 0x967e64f599297f3c}, + {0x2fde9314f05105e5, 0x58f5315e0e29e358}, + {0xc9e5b15be18b7596, 0xa305f4f11aaa8ad2}, + {0xa592cb3563071925, 0x31b050cca997ed24}, + {0xa55f9e7374b10af1, 0x5904c31aaebea1ed}, + {0xcf6921d88d12bbf2, 0xea5142776b77d368}, + {0x28779ef24c9ddcb5, 0x448bfd74cc624506}, + {0x0d2caf1924759d9a, 0xc66ef14828e98e80}, + {0x312a49ac8d3790db, 0x5121956dac40960a}, + {0x311230a0f0166f37, 0x41cdda4642d1e45a}, + {0x152cd68f8d980779, 0x50accd8f44cc6a3b}, + {0x0e6342e6e178a202, 0xaf2e59b6e13fec01}, + {0xcdfaea274cfff823, 0x008f7a68483d8f8a}, + {0x80183f4571309485, 0xdece92499f9521ba}, + {0xaba321469362905f, 0x3c5814a4c792b3be}, + {0x7e8680766e1d3ffc, 0x7585a167f0b843b8}, + {0x4e81e572c5dbf79a, 0x114bd1d466ef8787}, + {0x3a7e0a403a1da600, 0x014747267c0b38f9}, + {0x23116c4dd539e293, 0x196284a6305e23d7}, + {0xf0a02f00d5a45c0f, 0xae9980fc3aa3cd2e}, + {0x7eae2c6dae8286e9, 0xd2be72a1da8addbc}, + {0xbb8689cb630a9e23, 0x2d1eb9e86163e7f4}, + {0xf0febfb8f6e46561, 0x8eda5ccd665a3ac2}, + {0x370a6880719f8be9, 0x83fe14fe68c33df0}, + {0xe9634dd58474116f, 0xdfb51a0ca76c9c82}, + {0x9c40da32ca69fe52, 0xcecdf64c8559eef4}, + {0xe29f358edce8d40e, 0x9256190cf3cfb1fa}, + {0xb5431f672597e9cd, 0xc69025ae5a99210a}, + {0x0f00e0c670d40d95, 0xdf81e3ce7617b0a1}, + {0x699332d099ea38d7, 0xc24d5671c235f28e}, + {0x89ea2f4529a74b45, 0x7c11f6654369b65d}, + {0xeaa8470e44915e89, 0x049b62170967135b}, + {0x39fb9877aadc951b, 0xba3743d76fda5083}, + {0xe2da8722532e6fbb, 0xdef2a5ff6e028aba}, + {0xb5e975340c6c76a1, 0xf28418e25fbc0144}, + {0x035ab9363f6882be, 0xab56f227d4a26a26}, + {0x273536b8b02dd5f1, 0x75af981a11d43e64}, + {0x846e480a8bc44fa9, 0x507a048207335fa1}, + {0x3808d8fa4fcba922, 0xf632f1c9c802ab76}, + {0x34ecb7872eda1962, 0x2dcfedd3c12f73be}, + {0xf884a540c1b411ea, 0xf77d23a1c6600553}, + {0x0e106a0239843e3c, 0x7d5ef83763344eed}, + {0x4192e743be4ae7d9, 0x5070be659c9249dd}, + {0x6588c07b62dd03ba, 0x09d7b6469e953856}, + {0x790b4af55db42c92, 0x5c859acd40414177}, + {0xedda860c739ca8f7, 0xd728f7e92e3e7940}, + {0xfbcf513b18b860f7, 0xf6fd92c58b52c44d}, + {0x4f1571762119854e, 0x04286d00eb347197}, + {0x3f777b9977ed2aa6, 0xf68288c09c8d73d4}, + {0x538b16a3bd887a20, 0x86437c4cb491c94b}, + {0x3656d64f9fdf8baf, 0x97db137363bf2a7e}, + {0x0582fbdad31a1e6c, 0x213b4a759760ffe0}, + {0xc7f42208feff0a47, 0x05cb6fb77aad0666}, + {0x8f59c644fd5259d4, 0xd3740dabc91a5ecd}, + {0xca19d9ef4ab67cee, 0xa2486f3cdc03c63f}, + {0x8a1f14a7c3d2f88f, 0x71b6e4a0b3d4a2a0}, + {0xe9ee9aa288652690, 0xa28d2266c47e02b2}, + {0x759c7eee1a3eead3, 0x689aa81596670031}, + {0x50a9a3f15e0032ae, 0x206b34f2ed6fc8ff}, + {0x630774b85c40302e, 0xf7f5952347d531a6}, + {0x78886ef4e794267b, 0x7072ec9b3a2ddd8f}, + {0x754c7bf46deec1a2, 0xb360d5ec03ebf053}, + {0x337080ceace4b67a, 0xbe8541809bccdc7d}, + {0x8c243c5d486009a0, 0x87fc6f3fbe554f61}, + {0x58e8f3ccf2596f26, 0xc7a500e89b1b40a6}, + {0x516a6cbee9e76420, 0xe719cb9a5a49f8ed}, + {0x96f150816f90c216, 0x484947f2b48d7882}, + {0xdefb92978dfa0053, 0x58823337d6c0a641}, + {0x98bbc22dd2d3262b, 0xdad5891c70205c95}, + {0xbf1d06e5edc7d9ba, 0xea3e0a86c4241c1e}, + {0x78e2cf480abc18ef, 0x1110bc39a35669cf}, + {0xc188299c1375e7b2, 0x8eb4cf8cb0851480}, + {0xd0ec275048c667d2, 0xff5c57071581e3b1}, + {0x955c8d54a50fdd52, 0xcf79008ac79991d3}, + {0xf46cdcd85b7289c9, 0x1c5fc0acfab2cbb2}, + {0x676f48ac3ed3c825, 0x862183d1a9042f4d}, + {0xf35fc7982c7daee6, 0xa655183af862baae}, + {0x5335bbcaf8b9f37b, 0x963ed04a2a0b3eaa}, + {0x76d009714121cb10, 0x82f1d3e8253374ee}, + {0x50198339f3198270, 0xee023bd013e359f5}, + {0x315d27ea94c7941a, 0x5c1520117e098dbf}, + {0x96ccc513ba987df7, 0x7d84bbe2e504ff94}, + {0x03464584b630d2b7, 0x7d9fc4a633f228f4}, + {0x7e39cbb756cac943, 0x45a5498048f1a474}, + {0x56a90669f7aa29c6, 0x4883787b94c90425}, + {0x9a262b27cb8de6e9, 0x6495beb53f905401}, + {0xdc5866e0159b2920, 0x6c2c9c31b3faab04}, + {0x82f93c693fec7b5f, 0x1926807fb1c2bdd5}, + {0x3a06ca560fda4251, 0xff56ec036c5f13d6}, + {0xcf96fe4ae095a1c3, 0xaea98fd960fd6b9d}, + {0xc2ae3b23e1b73447, 0xe7c1f21b63d4e19c}, + {0x660f92196e62044c, 0xa61e4689ac8893c0}, + {0x4aacc983cc5d9cfe, 0xb71adc881811c258}, + {0xb01938e5f92ea2e0, 0x3d4b38fea83810f8}, + {0x8195527abb10f039, 0x242e99777aeec42a}, + {0x077a36f6536baf7f, 0x928620c22f148a6d}, + {0xb4d16665e8f965a6, 0x300ecf50c00b75a7}, + {0x53d4fbf144350d5c, 0x50967628985e6eaf}, + {0xea67291009feb48e, 0x74a182255aa9ccae}, + {0xe67c52e63c97fb3a, 0xbe1b4991d245fa61}, + {0x6bd8d3685ed38551, 0xc26bdd871e8691e5}, + {0x267c4e3df39e0a7e, 0x2408058c7b3e3c09}, + {0x2bc55550057b4b4e, 0xe70baa2724b374d3}, + {0x0e2984947284c4dd, 0x4f4e64ba26bfee68}, + {0x78891ea4bacdb828, 0x357f7d8801646f08}, + {0x220a9cb569d1ee6b, 0x8e6c9653552802fa}, + {0x6159359f74dda4d7, 0xcbd0c89374b1cc2e}, + {0x8dd5a4c4fe55c89f, 0xeeca37f94d3f69bd}, + {0x22abf1f68e0f314a, 0x69b86caf61d48d15}, + {0xab26c59f1090455d, 0x1a49957d9798f177}, +}; + +static const GF aim2_e2_power_matrix[AIM2_NUM_BITS_FIELD] = +{ + {0x0000000000000001, 0x0000000000000000}, + {0xf50e0632f2a35f5b, 0x386db41096f62a8a}, + {0x1843656b2ea8f397, 0xefdb454053648225}, + {0xfc670d9cf3feeb63, 0x7582326d84c7a1de}, + {0xf1c52011971b40b3, 0x864204566cee644d}, + {0x5d8e354c13ae648b, 0x192b28f22b444709}, + {0x9d5cef9c88eb0d9f, 0xb686d60b99470446}, + {0xc91fa3a9b726fd99, 0xcf7a6d254a105b09}, + {0x048e86e374780c55, 0x9f65220d0c78fc67}, + {0xafa9c90017000acc, 0x83a4540ded360993}, + {0x3e563c2c6efb6102, 0xb7147f0d38fa394e}, + {0x858e694ad98264cb, 0x184d72cdc205efdb}, + {0x260f2eae08292a50, 0x101cdb156939622a}, + {0x4a9a43781e99484d, 0x8b9b7c41b6c639f6}, + {0x16c9831c810a7459, 0xcb60c983013050be}, + {0x96d02af1b8d2cba8, 0xb37b4c2c6ea27c34}, + {0x3caadfab02ea679d, 0x6c3124a15e087d32}, + {0xf0892e59955b87ae, 0xaab1aa69ba6853d8}, + {0x8420916c212205ac, 0x86ed9039af31291c}, + {0x0610fd444421f178, 0xa6b004a839e31b64}, + {0xaebf5d9bae4e4ac1, 0x54bf9e6ec57b2d65}, + {0x28bce750ebcba70e, 0x4ce04f578ca77d4d}, + {0xe35d48d89312441e, 0xe6d91969fd74895a}, + {0xcca901ef7fabb1c5, 0x117d2c0c4032a05b}, + {0x4d05be0c6a5a2edc, 0x8314aecc100fcba9}, + {0x7c685f4133a51825, 0x9acd72f51105c28b}, + {0x5011fb2faa2c215a, 0xf33e2515d2bd65e4}, + {0xcec542879e66d1d0, 0xb35dca22a0c3ce97}, + {0x40849b4ce23375b2, 0x92453c68d163c3cb}, + {0x807af8ab827e3617, 0x9aa0b258c13e1db7}, + {0x02cf8f1292f7c659, 0x188599535df660bb}, + {0x675c7dfe865c4b21, 0x60e7e01162356b69}, + {0xdca8758ed620dd7b, 0x40e2dfc1450698ca}, + {0xd4785af596fd0c85, 0x194dcdf10572a8d6}, + {0x39c75c8db5a743fd, 0xaaff1be5fb825c25}, + {0x76f287eaaf80a26e, 0x6d5c3d924e633b50}, + {0xf3289f813d56fa87, 0x8a5781160603ae34}, + {0x023097d7bf57b560, 0x5c09da41ceda1dab}, + {0xaa7caa9af1506059, 0xd65b5a005d02edd2}, + {0x837d13e5bec17d5c, 0x96732ad7e569d594}, + {0xfca9d80d257930ce, 0xbb07355f7df706c0}, + {0x7e719f925352363e, 0x61f17c3d17da7386}, + {0xbdd686a4862a5d5b, 0x5ddbe9580f36ecca}, + {0xcd8440580a8cb347, 0x8b395b802547e6d8}, + {0x4338e255f15fc0d9, 0xf2400716b60d1c2c}, + {0xc0a4a5181cf7a401, 0x208e7b27a3d4e578}, + {0x6557dd7a9909844a, 0xd7dd867435b17ded}, + {0xe7214501f52038cd, 0xf73bfe485cf7fdd0}, + {0x93443a46972cbc70, 0xd2ca8f42b2d199e0}, + {0xbea25cda0a9de799, 0x51886f07950aef32}, + {0x82824ccfb37df72d, 0x71a58d7df86233f6}, + {0x0ab442c2423ac6e3, 0x5d989eeb2df819bb}, + {0x717b766d60dda065, 0x3899b1af41b28b8b}, + {0x2fffad98c8e94310, 0x9ff893980c381280}, + {0x9d7da6a6ca8c0d82, 0x09c78e0f83da5e2a}, + {0x26b7e85d55753566, 0x48b0fee439062128}, + {0x63896bb7a7a3c638, 0x551438e5f3ff5db9}, + {0x080d9af5ef2e5865, 0x048eccc1b914ae50}, + {0xf081a5f8ab004099, 0x24ffc9670c5492ac}, + {0x7e4178c2bf375b5a, 0xa641e4982d1c8638}, + {0x9f1874733c37691a, 0xa6e59883261af497}, + {0x90068f05a814992d, 0x8f340c2ecb9a2bd2}, + {0x2e0a82ad5f144c70, 0x783eb790b951d2d9}, + {0xbf58c52a82e24af6, 0x190f49c97cd133af}, + {0x29e30e4d37b882a1, 0x217bea750913f0db}, + {0xfe2287c403984038, 0x870bd9dd397e696e}, + {0x49e9bc6efdb97d7d, 0xf75f4c5e88587e96}, + {0xa6223b70299d2836, 0xf27661ea227ab61b}, + {0x4d6b8601ceb750cf, 0xfab6503eb520e48d}, + {0xcaf2dd4a73f67c6c, 0x93f3baaf44fed4e0}, + {0x1ff32e99fc57e662, 0x502b8bb6f2031150}, + {0x1d8b5656e3d694dc, 0xb31de0d77f80372b}, + {0x0f3d13aca2eac302, 0xb6d1f98a81d2cd6d}, + {0x840d8615c90887b8, 0x1d44fc5efe63c574}, + {0xded005c9eb05ef63, 0xdeb4246e55c121bb}, + {0x3409b8d1c43c2415, 0x700c0d1dc307fe8d}, + {0x8b361337911e3002, 0x7920c1039098414c}, + {0xa5dddabdd1beecf5, 0x146aaf12b0d6da5e}, + {0xe1a91d6f2a874e47, 0x0d63fcc83ef069d1}, + {0x0ffd9177c1f3ebb2, 0x9a0cadce706c0cc0}, + {0xc60d34aa0f45f13d, 0x2d0b4ea8c2bfdc70}, + {0x83e36503d6399610, 0x6014c0c7cba2d2f2}, + {0x9cc705d2ecaeca0e, 0x79f83e8c83e7f333}, + {0x58c7035772444ccc, 0x789c6687005b995e}, + {0x6b3d950394c886a1, 0x9b4f4564cd5b92d0}, + {0x872c7f29b6dae6ca, 0xd2a320a97a0d0be9}, + {0x14bb3a90e34016b2, 0xb308fa5fc47ad142}, + {0xc6b31a14ce574546, 0xd7f758f96323f56e}, + {0x046d3862feb271a0, 0x391175405eef9c5e}, + {0xf7654c3e98aff433, 0x92b8d607c0180e5e}, + {0xdfe26a4ee0edcbcf, 0x4c21afb68c481788}, + {0xb9175aa38699a7fa, 0xa26d3569fb705b0a}, + {0xd2955bcc820c812c, 0x29d30f039b37f636}, + {0x37d8c59743ebdc8d, 0x19289d7baab847bc}, + {0x8b8a25c0075e7200, 0x75fcbc7110b551c9}, + {0x8ab2318dd48eb686, 0xca8ee9edf4a5a1e0}, + {0x182033f6233cad5f, 0x743083edee67622b}, + {0xc82b0364e7db3d93, 0x3cec89a9bc59587d}, + {0x4fb362a6d33cdc65, 0xb2f2a5ce567b5b8e}, + {0x90df4043911d6152, 0xfe9e1ef68cc145b2}, + {0x4fcf7b4fcca5200b, 0xaba094d2f96d9249}, + {0x5ac887c31fc3fd76, 0x1845172174cf2944}, + {0x25180f84f6702866, 0xde5223f17c83df5d}, + {0x2863a5b3ae30cdea, 0x610fc2ae8f7cfc74}, + {0x64a4086ca77af644, 0xafe073214eb0e372}, + {0xbdc97dadac10ab50, 0x97cf31c3dfa3a7ad}, + {0x79f2ee819538d167, 0x68555fb401eb2780}, + {0x72e2b904d5c7a7ed, 0x482326aa3e165b1c}, + {0x92f65484dcff7fd8, 0x603faf9bafb86f1e}, + {0x210e7817fff07876, 0xabdf6d8a0dd6d8a5}, + {0xab561f7f19942dec, 0x55f71e3e54c7b523}, + {0x8e7140a742fb2245, 0x34a49c54b5ad70ec}, + {0x6da544268e007b3f, 0xebf2cf33aeaee1c9}, + {0x010679622fe3753e, 0x40228d2a0d402ed0}, + {0x2e128b07e6e4e311, 0x0811ebd4d8dde5b5}, + {0x126cb02cee9ad020, 0x398e5321decfb79c}, + {0x6dfdff51553fb5ff, 0x415b4003d55c33ab}, + {0xd3b7fedc1cd8ab6e, 0x49dc7b6033f0ae60}, + {0x7062ab84db2bbaed, 0xc33060adb11136c6}, + {0xae149ced6b9cc3d3, 0xef2f29a2ebe433ce}, + {0x133ca1e237105dc6, 0x9712a59673f1d79c}, + {0xfcf98569ab4ec844, 0x6a40dd9e8d49194e}, + {0xd73a65ce7e33212a, 0xaa29936469e73794}, + {0x961009e50707fe21, 0x657c63ec063d9f23}, + {0x6b1af6be25650671, 0xce96b0cb11ce0372}, + {0xc7312488beda3b54, 0x9ee42f2347f50335}, + {0x829d638189fca23f, 0xe3123a63017f9509}, + {0xbb40cef8e0e85cea, 0xd8b3a76799622f49}, +}; + +#define GF_exp_invmer_e_1 AIMER_NAMESPACE(GF_exp_invmer_e_1) +void GF_exp_invmer_e_1(GF out, const GF in); +#define GF_exp_invmer_e_2 AIMER_NAMESPACE(GF_exp_invmer_e_2) +void GF_exp_invmer_e_2(GF out, const GF in); +#define GF_exp_mer_e_star AIMER_NAMESPACE(GF_exp_mer_e_star) +void GF_exp_mer_e_star(GF out, const GF in); + +#define generate_matrices_L_and_U AIMER_NAMESPACE(generate_matrices_L_and_U) +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define generate_matrix_LU AIMER_NAMESPACE(generate_matrix_LU) +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define aim2_sbox_outputs AIMER_NAMESPACE(aim2_sbox_outputs) +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt); + +#define aim2 AIMER_NAMESPACE(aim2) +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]); + +#endif // AIM2_H diff --git a/crypto_sign/aimer128f/m4speed/api.h b/crypto_sign/aimer128f/m4speed/api.h new file mode 100644 index 00000000..50b6558d --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 32 +#define CRYPTO_SECRETKEYBYTES 48 +#define CRYPTO_BYTES 5888 +#define CRYPTO_ALGNAME "aimer128f" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer128f/m4speed/field.c b/crypto_sign/aimer128f/m4speed/field.c new file mode 100644 index 00000000..1e12b447 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/field.c @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: MIT + +#include "field.h" +#include +#include + +#define mask_64 0x00000000ffffffff +#define mask_final 0x000000000000ffff + +#define mask0_64 0x000000ff000000ff +#define mask0 0x000000ff + +#define mask1_64 0x000f000f000f000f +#define mask1 0x000f000f + +#define mask2_64 0x0303030303030303 +#define mask2 0x03030303 + +#define mask3_64 0x1111111111111111 +#define mask3 0x11111111 + +#define zero_padding(x0, mask1, mask2, mask3) \ + x0 = (x0 | (x0 << 12)) & mask1; \ + x0 = (x0 | (x0 << 6 )) & mask2; \ + x0 = (x0 | (x0 << 3 )) & mask3; + +#define inv_zero_padding(x0, mask0, mask1, mask2, mask_final) \ + x0 = (x0 | (x0 >> 3 )) & mask2; \ + x0 = (x0 | (x0 >> 6 )) & mask1; \ + x0 = (x0 | (x0 >> 12)) & mask0; \ + x0 = (x0 | (x0 >> 24)) & mask_final; + +void GF_mul(GF c, const GF a, const GF b) +{ + uint64_t t[2] = {0,}; + uint64_t temp[4] = {0,}; + uint64_t sub[2] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + + poly64_mul(&a[1], &b[1], &temp[3], &temp[2]); + poly64_mul(&a[0], &b[0], &temp[1], &temp[0]); + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0] ^ temp[0] ^ temp[2]; + temp[2] = t[0] ^ t[1] ^ temp[0] ^ temp[1] ^ temp[3]; + + t[0] = temp[2] ^ ((temp[3] >> 57) ^ (temp[3] >> 62) ^ (temp[3] >> 63)); + + c[1] = temp[1] ^ temp[3]; + c[1] ^= (temp[3] << 7) | (t[0] >> 57); + c[1] ^= (temp[3] << 2) | (t[0] >> 62); + c[1] ^= (temp[3] << 1) | (t[0] >> 63); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_mul_add(GF c, const GF a, const GF b) +{ + uint64_t t[2] = {0,}; + uint64_t temp[4] = {0,}; + uint64_t sub[2] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + + poly64_mul(&a[1], &b[1], &temp[3], &temp[2]); + poly64_mul(&a[0], &b[0], &temp[1], &temp[0]); + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0] ^ temp[0] ^ temp[2]; + temp[2] = t[0] ^ t[1] ^ temp[0] ^ temp[1] ^ temp[3]; + + t[0] = temp[2] ^ ((temp[3] >> 57) ^ (temp[3] >> 62) ^ (temp[3] >> 63)); + + c[1] ^= temp[1] ^ temp[3]; + c[1] ^= (temp[3] << 7) | (t[0] >> 57); + c[1] ^= (temp[3] << 2) | (t[0] >> 62); + c[1] ^= (temp[3] << 1) | (t[0] >> 63); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 8, index >>= 8, b_ptr += 8) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + + mask = -((index >> 4) & 1); + temp_c0 ^= (b_ptr[4][0] & mask); + temp_c1 ^= (b_ptr[4][1] & mask); + + mask = -((index >> 5) & 1); + temp_c0 ^= (b_ptr[5][0] & mask); + temp_c1 ^= (b_ptr[5][1] & mask); + + mask = -((index >> 6) & 1); + temp_c0 ^= (b_ptr[6][0] & mask); + temp_c1 ^= (b_ptr[6][1] & mask); + + mask = -((index >> 7) & 1); + temp_c0 ^= (b_ptr[7][0] & mask); + temp_c1 ^= (b_ptr[7][1] & mask); + } + } + c[0] = temp_c0; + c[1] = temp_c1; +} + +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 8, index >>= 8, b_ptr += 8) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + + mask = -((index >> 4) & 1); + temp_c0 ^= (b_ptr[4][0] & mask); + temp_c1 ^= (b_ptr[4][1] & mask); + + mask = -((index >> 5) & 1); + temp_c0 ^= (b_ptr[5][0] & mask); + temp_c1 ^= (b_ptr[5][1] & mask); + + mask = -((index >> 6) & 1); + temp_c0 ^= (b_ptr[6][0] & mask); + temp_c1 ^= (b_ptr[6][1] & mask); + + mask = -((index >> 7) & 1); + temp_c0 ^= (b_ptr[7][0] & mask); + temp_c1 ^= (b_ptr[7][1] & mask); + } + } + c[0] ^= temp_c0; + c[1] ^= temp_c1; +} + +static void poly64_mul_s(uint64_t *z1, uint64_t *z0, uint64_t x, uint64_t y) +{ + // x_low + uint32_t x4 = x >> 32; + + uint32_t x0 = x & mask_64; + uint32_t x1 = (x0 >> 8) & mask0; + uint32_t x2 = (x0 >> 16) & mask0; + uint32_t x3 = (x0 >> 24) & mask0; + x0 &= mask0; + + // x_high + uint32_t x5 = (x4 >> 8) & mask0; + uint32_t x6 = (x4 >> 16) & mask0; + uint32_t x7 = (x4 >> 24) & mask0; + x4 &= mask0; + + // y_low + uint32_t y4 = y >> 32; + + uint32_t y0 = y & mask_64; + uint32_t y1 = (y0 >> 8) & mask0; + uint32_t y2 = (y0 >> 16) & mask0; + uint32_t y3 = (y0 >> 24) & mask0; + y0 &= mask0; + + // y_high + uint32_t y5 = (y4 >> 8) & mask0; + uint32_t y6 = (y4 >> 16) & mask0; + uint32_t y7 = (y4 >> 24) & mask0; + y4 &= mask0; + + // x padding + zero_padding(x0, mask1, mask2, mask3); + zero_padding(x1, mask1, mask2, mask3); + zero_padding(x2, mask1, mask2, mask3); + zero_padding(x3, mask1, mask2, mask3); + zero_padding(x4, mask1, mask2, mask3); + zero_padding(x5, mask1, mask2, mask3); + zero_padding(x6, mask1, mask2, mask3); + zero_padding(x7, mask1, mask2, mask3); + + // y padding + zero_padding(y0, mask1, mask2, mask3); + zero_padding(y1, mask1, mask2, mask3); + zero_padding(y2, mask1, mask2, mask3); + zero_padding(y3, mask1, mask2, mask3); + zero_padding(y4, mask1, mask2, mask3); + zero_padding(y5, mask1, mask2, mask3); + zero_padding(y6, mask1, mask2, mask3); + zero_padding(y7, mask1, mask2, mask3); + + //x0-3 * y0-3 + uint64_t a0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t a1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + a0 ^= (a1 << 32); + a1 = a1 >> 32; + a1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t a2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + a1 ^= (a2 << 32); + a2 = a2 >> 32; + a2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t a3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + a2 ^= (a3 << 32); + a3 = a3 >> 32; + + a3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + //x4-7 * y4-7 + uint64_t b0 = ((uint64_t)x4 * (uint64_t)y4) & mask3_64; + uint64_t b1 = ((((uint64_t)x4 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y4) & mask3_64)); + b0 ^= (b1 << 32); + b1 = b1 >> 32; + b1 ^= ((((uint64_t)x4 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y4) & mask3_64)); + + uint64_t b2 = ((((uint64_t)x4 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y4) & mask3_64)); + b1 ^= (b2 << 32); + b2 = b2 >> 32; + b2 ^= ((((uint64_t)x5 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y5) & mask3_64)); + + uint64_t b3 = ((((uint64_t)x6 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y6) & mask3_64)); + b2 ^= (b3 << 32); + b3 = b3 >> 32; + + b3 ^= ((uint64_t)x7 * (uint64_t)y7) & mask3_64; + + //middle part + x0 ^= x4; + x1 ^= x5; + x2 ^= x6; + x3 ^= x7; + + y0 ^= y4; + y1 ^= y5; + y2 ^= y6; + y3 ^= y7; + + uint64_t c0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t c1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + c0 ^= (c1 << 32); + c1 = c1 >> 32; + c1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t c2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + c1 ^= (c2 << 32); + c2 = c2 >> 32; + c2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t c3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + c2 ^= (c3 << 32); + c3 = c3 >> 32; + + c3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + c0 = c0 ^ a0 ^ b0; + c1 = c1 ^ a1 ^ b1; + c2 = c2 ^ a2 ^ b2; + c3 = c3 ^ a3 ^ b3; + + a2 ^= c0; + a3 ^= c1; + b0 ^= c2; + b1 ^= c3; + + // result inv_padding + inv_zero_padding(a0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a3, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b3, mask0_64, mask1_64, mask2_64, mask_final); + + *z0 = a0 | (a1 << 16) | (a2 << 32) | (a3 << 48); + *z1 = b0 | (b1 << 16) | (b2 << 32) | (b3 << 48); +} + +void GF_mul_s(GF c, const GF a, const GF b) +{ + uint64_t t[2] = {0,}; + uint64_t temp[4] = {0,}; + + poly64_mul_s(&temp[3], &temp[2], a[1], b[1]); + poly64_mul_s(&temp[1], &temp[0], a[0], b[0]); + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0] ^ temp[0] ^ temp[2]; + temp[2] = t[0] ^ t[1] ^ temp[0] ^ temp[1] ^ temp[3]; + + t[0] = temp[2] ^ ((temp[3] >> 57) ^ (temp[3] >> 62) ^ (temp[3] >> 63)); + + c[1] = temp[1] ^ temp[3]; + c[1] ^= (temp[3] << 7) | (t[0] >> 57); + c[1] ^= (temp[3] << 2) | (t[0] >> 62); + c[1] ^= (temp[3] << 1) | (t[0] >> 63); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_mul_add_s(GF c, const GF a, const GF b) +{ + uint64_t t[2] = {0,}; + uint64_t temp[4] = {0,}; + + poly64_mul_s(&temp[3], &temp[2], a[1], b[1]); + poly64_mul_s(&temp[1], &temp[0], a[0], b[0]); + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0] ^ temp[0] ^ temp[2]; + temp[2] = t[0] ^ t[1] ^ temp[0] ^ temp[1] ^ temp[3]; + + t[0] = temp[2] ^ ((temp[3] >> 57) ^ (temp[3] >> 62) ^ (temp[3] >> 63)); + + c[1] ^= temp[1] ^ temp[3]; + c[1] ^= (temp[3] << 7) | (t[0] >> 57); + c[1] ^= (temp[3] << 2) | (t[0] >> 62); + c[1] ^= (temp[3] << 1) | (t[0] >> 63); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} diff --git a/crypto_sign/aimer128f/m4speed/field.h b/crypto_sign/aimer128f/m4speed/field.h new file mode 100644 index 00000000..e8fd7996 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/field.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +#ifndef FIELD_H +#define FIELD_H + +#include "params.h" +#include +#include + +typedef uint64_t GF[2]; + +#define poly64_mul AIMER_NAMESPACE(poly64_mul) +void poly64_mul(const uint64_t *a, const uint64_t *b, uint64_t *c1, uint64_t *c0); +#define GF_set0 AIMER_NAMESPACE(GF_set0) +void GF_set0(GF a); +#define GF_copy AIMER_NAMESPACE(GF_copy) +void GF_copy(GF out, const GF in); +#define GF_to_bytes AIMER_NAMESPACE(GF_to_bytes) +void GF_to_bytes(uint8_t *out, const GF in); +#define GF_from_bytes AIMER_NAMESPACE(GF_from_bytes) +void GF_from_bytes(GF out, const uint8_t *in); + +#define GF_add AIMER_NAMESPACE(GF_add) +void GF_add(GF c, const GF a, const GF b); +#define GF_mul AIMER_NAMESPACE(GF_mul) +void GF_mul(GF c, const GF a, const GF b); +#define GF_mul_add AIMER_NAMESPACE(GF_mul_add) +void GF_mul_add(GF c, const GF a, const GF b); +#define GF_transposed_matmul AIMER_NAMESPACE(GF_transposed_matmul) +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); +#define GF_transposed_matmul_add AIMER_NAMESPACE(GF_transposed_matmul_add) +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); + +#define GF_mul_s AIMER_NAMESPACE(GF_mul_s) +void GF_mul_s(GF c, const GF a, const GF b); +#define GF_mul_add_s AIMER_NAMESPACE(GF_mul_add_s) +void GF_mul_add_s(GF c, const GF a, const GF b); +#define GF_sqr_s AIMER_NAMESPACE(GF_sqr_s) +void GF_sqr_s(GF c, const GF a); + +#endif // FIELD_H diff --git a/crypto_sign/aimer128f/m4speed/hash.c b/crypto_sign/aimer128f/m4speed/hash.c new file mode 100644 index 00000000..71f3fb67 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/hash.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +#include "hash.h" +#include +#include + +void hash_init(hash_instance *ctx) +{ + shake128_inc_init(ctx); +} + +void hash_init_prefix(hash_instance *ctx, uint8_t prefix) +{ + shake128_inc_init(ctx); + shake128_inc_absorb(ctx, &prefix, sizeof(prefix)); +} + +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len) +{ + shake128_inc_absorb(ctx, data, data_len); +} + +void hash_final(hash_instance *ctx) +{ + shake128_inc_finalize(ctx); +} + +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len) +{ + shake128_inc_squeeze(buffer, buffer_len, ctx); +} + +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src) +{ + shake128_inc_ctx_clone(ctx_dest, ctx_src); +} + +void hash_ctx_release(hash_instance *ctx) +{ + shake128_inc_ctx_release(ctx); +} diff --git a/crypto_sign/aimer128f/m4speed/hash.h b/crypto_sign/aimer128f/m4speed/hash.h new file mode 100644 index 00000000..d6b05065 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/hash.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +#ifndef HASH_H +#define HASH_H + +#include "fips202.h" +#include "params.h" +#include +#include + +static const uint8_t HASH_PREFIX_0 = 0; +static const uint8_t HASH_PREFIX_1 = 1; +static const uint8_t HASH_PREFIX_2 = 2; +static const uint8_t HASH_PREFIX_3 = 3; +static const uint8_t HASH_PREFIX_4 = 4; +static const uint8_t HASH_PREFIX_5 = 5; + +typedef shake128incctx hash_instance; + +#define hash_init AIMER_NAMESPACE(hash_init) +void hash_init(hash_instance *ctx); +#define hash_init_prefix AIMER_NAMESPACE(hash_init_prefix) +void hash_init_prefix(hash_instance *ctx, uint8_t prefix); +#define hash_update AIMER_NAMESPACE(hash_update) +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len); +#define hash_final AIMER_NAMESPACE(hash_final) +void hash_final(hash_instance *ctx); +#define hash_squeeze AIMER_NAMESPACE(hash_squeeze) +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len); +#define hash_ctx_clone AIMER_NAMESPACE(hash_ctx_clone) +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src); +#define hash_ctx_release AIMER_NAMESPACE(hash_ctx_release) +void hash_ctx_release(hash_instance *ctx); + +#endif // HASH_H diff --git a/crypto_sign/aimer128f/m4speed/params.h b/crypto_sign/aimer128f/m4speed/params.h new file mode 100644 index 00000000..8753737e --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer128f_m4speed_##s + +#define SECURITY_BITS 128 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 33 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer128f/m4speed/sign.c b/crypto_sign/aimer128f/m4speed/sign.c new file mode 100644 index 00000000..ce54ea41 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/sign.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE], + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + mult_chk_t mult_chk[AIMER_T][AIMER_N], + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const uint8_t *sk, const uint8_t *m, size_t mlen) +{ + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt + hash_init_prefix(&ctx, HASH_PREFIX_3); + hash_update(&ctx, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, random, SECURITY_BYTES); + hash_final(&ctx); + hash_squeeze(&ctx, sign->salt, AIMER_SALT_SIZE); + + // generate root seeds and expand seed trees + for (size_t rep = 0; rep < AIMER_T; rep++) + { + hash_squeeze(&ctx, nodes[rep][0], AIMER_SEED_SIZE); + } + expand_trees(nodes, sign->salt); + hash_ctx_release(&ctx); + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // initialize adjustment values + tape_t delta, tape; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + commit_and_expand_tape(&tape, commits[rep][party], &ctx_precom, + nodes[rep][party + AIMER_N - 1], rep, party); + hash_update(&ctx, commits[rep][party], AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + GF_set0(mult_chk[rep][party].x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk[rep][party].x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk[rep][party].pt_share, tape.pt_share); + GF_copy(mult_chk[rep][party].x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk[rep][party].x_shares[1], tape.t_shares[1]); + GF_copy(alpha_v_shares[rep][0][party], tape.a_share); + GF_copy(alpha_v_shares[rep][1][party], tape.c_share); + + aim2_mpc(&mult_chk[rep][party], + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_2_and_3(signature_t *sign, + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const mult_chk_t mult_chk[AIMER_T][AIMER_N]) +{ + GF epsilons[AIMER_L + 1]; + + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + GF_set0(alpha); + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // alpha_share = a_share + sum x_share[i] * eps[i] + // v_share = c_share - pt_share * alpha + sum z_share[i] * eps[i] + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[rep][0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].pt_share, alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares[rep], + AIM2_NUM_BYTES_FIELD * 2 * AIMER_N); + } + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + hash_ctx_release(&ctx_e); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + hash_instance ctx; + signature_t *sign = (signature_t *)sig; + + ////////////////////////////////////////////////////////////////////////// + // Phase 1: Committing to the seeds and the execution views of parties. // + ////////////////////////////////////////////////////////////////////////// + + // nodes for seed trees + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + // commitments for seeds + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE]; + + // multiplication check inputs + mult_chk_t mult_chk[AIMER_T][AIMER_N]; + + // multiplication check outputs + GF alpha_v_shares[AIMER_T][2][AIMER_N]; + + // commitments for phase 1 + run_phase_1(sign, commits, nodes, mult_chk, alpha_v_shares, sk, m, mlen); + + ///////////////////////////////////////////////////////////////// + // Phase 2, 3: Challenging and committing to the simulation of // + // the multiplication checking protocol. // + ///////////////////////////////////////////////////////////////// + + // compute the commitment of phase 3 + run_phase_2_and_3(sign, alpha_v_shares, + (const mult_chk_t (*)[AIMER_N])mult_chk); + + ////////////////////////////////////////////////////// + // Phase 4: Challenging views of the MPC protocols. // + ////////////////////////////////////////////////////// + + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + ////////////////////////////////////////////////////// + // Phase 5: Opening the views of the MPC protocols. // + ////////////////////////////////////////////////////// + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes[rep], i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits[rep][i_bar], + AIMER_COMMIT_SIZE); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, + alpha_v_shares[rep][0][i_bar]); + } + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer128f/m4speed/sign.h b/crypto_sign/aimer128f/m4speed/sign.h new file mode 100644 index 00000000..e64c4350 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/sign.h @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT + +#ifndef SIGN_H +#define SIGN_H + +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +typedef struct tape_t +{ + GF pt_share; + GF t_shares[AIMER_L]; + GF a_share; + GF c_share; +} tape_t; + +typedef struct mult_chk_t +{ + GF pt_share; + GF x_shares[AIMER_L + 1]; + GF z_shares[AIMER_L + 1]; +} mult_chk_t; + +typedef struct proof_t +{ + uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE]; + uint8_t missing_commitment[AIMER_COMMIT_SIZE]; + uint8_t delta_pt_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t delta_ts_bytes[AIMER_L][AIM2_NUM_BYTES_FIELD]; + uint8_t delta_c_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t missing_alpha_share_bytes[AIM2_NUM_BYTES_FIELD]; +} proof_t; + +typedef struct signature_t +{ + uint8_t salt[AIMER_SALT_SIZE]; + uint8_t h_1[AIMER_COMMIT_SIZE]; + uint8_t h_2[AIMER_COMMIT_SIZE]; + proof_t proofs[AIMER_T]; +} signature_t; + +#define aim2_mpc AIMER_NAMESPACE(aim2_mpc) +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF); + +#define commit_and_expand_tape AIMER_NAMESPACE(commit_and_expand_tape) +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party); + +#define run_phase_1 AIMER_NAMESPACE(run_phase_1) +void run_phase_1(signature_t *sign, + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE], + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + mult_chk_t mult_chk[AIMER_T][AIMER_N], + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const uint8_t *sk, const uint8_t *m, size_t mlen); + +#define run_phase_2_and_3 AIMER_NAMESPACE(run_phase_2_and_3) +void run_phase_2_and_3(signature_t *sign, + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const mult_chk_t mult_chk[AIMER_T][AIMER_N]); + +#endif // SIGN_H diff --git a/crypto_sign/aimer128f/m4speed/tree.c b/crypto_sign/aimer128f/m4speed/tree.c new file mode 100644 index 00000000..84c23d7f --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/tree.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT + +#include "tree.h" +#include "hash.h" +#include +#include +#include + +// Example of tree for [N = 8] +// x +// d = 0: 1 +// d = 1: 2 3 +// d = 2: 4 5 6 7 +// d = 3: 8 9 10 11 12 13 14 15 + +void expand_trees(uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE]) +{ + size_t rep, index; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx, ctx_; + hash_init_prefix(&ctx_, HASH_PREFIX_4); + hash_update(&ctx_, salt, AIMER_SALT_SIZE); + + for (rep = 0; rep < AIMER_T; rep++) + { + buffer[0] = (uint8_t)(rep); + for (index = 1; index < AIMER_N; index++) + { + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[rep][index - 1], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, &ctx_); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[rep][2 * index - 1], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + } + hash_ctx_release(&ctx_); +} + +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index) +{ + size_t index = cover_index + AIMER_N; + for (size_t depth = 0; depth < AIMER_LOGN; depth++) + { + // index ^ 1 is sibling index + memcpy(reveal_path[depth], nodes[(index ^ 1) - 1], AIMER_SEED_SIZE); + + // go to parent node + index >>= 1; + } +} + +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index) +{ + size_t index, depth, path; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx, ctx_; + hash_init_prefix(&ctx_, HASH_PREFIX_4); + hash_update(&ctx_, salt, AIMER_SALT_SIZE); + + for (depth = 1; depth < AIMER_LOGN; depth++) + { + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); + + for (index = (1U << depth); index < (2U << depth); index++) + { + buffer[0] = (uint8_t)(rep_index); + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[index - 2], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, &ctx_); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[2 * index - 2], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + } + hash_ctx_release(&ctx_); + + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); +} diff --git a/crypto_sign/aimer128f/m4speed/tree.h b/crypto_sign/aimer128f/m4speed/tree.h new file mode 100644 index 00000000..b5a27867 --- /dev/null +++ b/crypto_sign/aimer128f/m4speed/tree.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +#ifndef TREE_H +#define TREE_H + +#include "params.h" +#include +#include + +#define expand_trees AIMER_NAMESPACE(expand_trees) +void expand_trees(uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE]); + +#define reveal_all_but AIMER_NAMESPACE(reveal_all_but) +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index); + +#define reconstruct_tree AIMER_NAMESPACE(reconstruct_tree) +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index); + +#endif // TREE_H diff --git a/crypto_sign/aimer128f/m4stack/__asm_field.S b/crypto_sign/aimer128f/m4stack/__asm_field.S new file mode 120000 index 00000000..308bd9b7 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer128f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/aim2.c b/crypto_sign/aimer128f/m4stack/aim2.c new file mode 120000 index 00000000..7dcc6ae4 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/aim2.h b/crypto_sign/aimer128f/m4stack/aim2.h new file mode 120000 index 00000000..00a5a6e1 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/api.h b/crypto_sign/aimer128f/m4stack/api.h new file mode 120000 index 00000000..065f81c2 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/api.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/field.c b/crypto_sign/aimer128f/m4stack/field.c new file mode 120000 index 00000000..56dcd6bb --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/field.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/field.h b/crypto_sign/aimer128f/m4stack/field.h new file mode 120000 index 00000000..a58150b8 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/field.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/hash.c b/crypto_sign/aimer128f/m4stack/hash.c new file mode 120000 index 00000000..deafd134 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/hash.h b/crypto_sign/aimer128f/m4stack/hash.h new file mode 120000 index 00000000..c150ee5f --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer128f/m4stack/params.h b/crypto_sign/aimer128f/m4stack/params.h new file mode 100644 index 00000000..689e8830 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer128f_m4stack_##s + +#define SECURITY_BITS 128 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 33 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer128f/m4stack/sign.c b/crypto_sign/aimer128f/m4stack/sign.c new file mode 100644 index 00000000..deaea5b7 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/sign.c @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer128f/m4stack/sign.h b/crypto_sign/aimer128f/m4stack/sign.h new file mode 100644 index 00000000..2e2ab61d --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/sign.h @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT + +#ifndef SIGN_H +#define SIGN_H + +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +typedef struct tape_t +{ + GF pt_share; + GF t_shares[AIMER_L]; + GF a_share; + GF c_share; +} tape_t; + +typedef struct mult_chk_t +{ + GF x_shares[AIMER_L + 1]; + GF z_shares[AIMER_L + 1]; +} mult_chk_t; + +typedef struct proof_t +{ + uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE]; + uint8_t missing_commitment[AIMER_COMMIT_SIZE]; + uint8_t delta_pt_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t delta_ts_bytes[AIMER_L][AIM2_NUM_BYTES_FIELD]; + uint8_t delta_c_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t missing_alpha_share_bytes[AIM2_NUM_BYTES_FIELD]; +} proof_t; + +typedef struct signature_t +{ + uint8_t salt[AIMER_SALT_SIZE]; + uint8_t h_1[AIMER_COMMIT_SIZE]; + uint8_t h_2[AIMER_COMMIT_SIZE]; + proof_t proofs[AIMER_T]; +} signature_t; + +#define aim2_mpc AIMER_NAMESPACE(aim2_mpc) +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF); + +#define commit_and_expand_tape AIMER_NAMESPACE(commit_and_expand_tape) +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party); + +#define run_phase_1 AIMER_NAMESPACE(run_phase_1) +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]); + +#define run_phase_1_to_3 AIMER_NAMESPACE(run_phase_1_to_3) +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF); + +#define run_phase_1_to_5 AIMER_NAMESPACE(run_phase_1_to_5) +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b); + +#endif // SIGN_H diff --git a/crypto_sign/aimer128f/m4stack/tree.c b/crypto_sign/aimer128f/m4stack/tree.c new file mode 100644 index 00000000..0585e7fa --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/tree.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT + +#include "tree.h" +#include "hash.h" +#include +#include +#include + +// Example of tree for [N = 8] +// x +// d = 0: 1 +// d = 1: 2 3 +// d = 2: 4 5 6 7 +// d = 3: 8 9 10 11 12 13 14 15 + +void expand_tree(uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + size_t rep_index, + const uint8_t root_seed[AIMER_SEED_SIZE]) +{ + size_t index; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx, ctx_; + hash_init_prefix(&ctx_, HASH_PREFIX_4); + hash_update(&ctx_, salt, AIMER_SALT_SIZE); + + memcpy(nodes[0], root_seed, AIMER_SEED_SIZE); + buffer[0] = (uint8_t)(rep_index); + for (index = 1; index < AIMER_N; index++) + { + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[index - 1], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, &ctx_); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[2 * index - 1], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + hash_ctx_release(&ctx_); +} + +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index) +{ + size_t index = cover_index + AIMER_N; + for (size_t depth = 0; depth < AIMER_LOGN; depth++) + { + // index ^ 1 is sibling index + memcpy(reveal_path[depth], nodes[(index ^ 1) - 1], AIMER_SEED_SIZE); + + // go to parent node + index >>= 1; + } +} + +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index) +{ + size_t index, depth, path; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx, ctx_; + hash_init_prefix(&ctx_, HASH_PREFIX_4); + hash_update(&ctx_, salt, AIMER_SALT_SIZE); + + for (depth = 1; depth < AIMER_LOGN; depth++) + { + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); + + for (index = (1U << depth); index < (2U << depth); index++) + { + buffer[0] = (uint8_t)(rep_index); + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[index - 2], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, &ctx_); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[2 * index - 2], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + } + hash_ctx_release(&ctx_); + + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); +} diff --git a/crypto_sign/aimer128f/m4stack/tree.h b/crypto_sign/aimer128f/m4stack/tree.h new file mode 100644 index 00000000..f1354f19 --- /dev/null +++ b/crypto_sign/aimer128f/m4stack/tree.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef TREE_H +#define TREE_H + +#include "params.h" +#include +#include + +#define expand_tree AIMER_NAMESPACE(expand_tree) +void expand_tree(uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + size_t rep_index, + const uint8_t root_seed[AIMER_SEED_SIZE]); + +#define reveal_all_but AIMER_NAMESPACE(reveal_all_but) +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index); + +#define reconstruct_tree AIMER_NAMESPACE(reconstruct_tree) +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index); + +#endif // TREE_H diff --git a/crypto_sign/aimer128s/m4speed/__asm_field.S b/crypto_sign/aimer128s/m4speed/__asm_field.S new file mode 120000 index 00000000..308bd9b7 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/__asm_field.S @@ -0,0 +1 @@ +../../aimer128f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4speed/aim2.c b/crypto_sign/aimer128s/m4speed/aim2.c new file mode 120000 index 00000000..7dcc6ae4 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/aim2.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4speed/aim2.h b/crypto_sign/aimer128s/m4speed/aim2.h new file mode 120000 index 00000000..00a5a6e1 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/aim2.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4speed/api.h b/crypto_sign/aimer128s/m4speed/api.h new file mode 100644 index 00000000..170f69cc --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 32 +#define CRYPTO_SECRETKEYBYTES 48 +#define CRYPTO_BYTES 4160 +#define CRYPTO_ALGNAME "aimer128s" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer128s/m4speed/field.c b/crypto_sign/aimer128s/m4speed/field.c new file mode 120000 index 00000000..56dcd6bb --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/field.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4speed/field.h b/crypto_sign/aimer128s/m4speed/field.h new file mode 120000 index 00000000..a58150b8 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/field.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4speed/hash.c b/crypto_sign/aimer128s/m4speed/hash.c new file mode 100644 index 00000000..443de84b --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/hash.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +#include "hash.h" +#include "keccakf1600.h" +#include +#include + +static void shake128_inc_skip_squeeze(shake128incctx *state, size_t outlen) +{ + size_t i; + + for (i = 0; i < outlen && i < state->ctx[25]; i++) + { + continue; + } + outlen -= i; + state->ctx[25] -= i; + + while (outlen > 0) + { + KeccakF1600_StatePermute(state->ctx); + + for (i = 0; i < outlen && i < SHAKE128_RATE; i++) + { + continue; + } + outlen -= i; + state->ctx[25] = SHAKE128_RATE - i; + } +} + +void hash_init(hash_instance *ctx) +{ + shake128_inc_init(ctx); +} + +void hash_init_prefix(hash_instance *ctx, uint8_t prefix) +{ + shake128_inc_init(ctx); + shake128_inc_absorb(ctx, &prefix, sizeof(prefix)); +} + +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len) +{ + shake128_inc_absorb(ctx, data, data_len); +} + +void hash_final(hash_instance *ctx) +{ + shake128_inc_finalize(ctx); +} + +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len) +{ + shake128_inc_squeeze(buffer, buffer_len, ctx); +} + +void hash_skip_squeeze(hash_instance *ctx, size_t buffer_len) +{ + shake128_inc_skip_squeeze(ctx, buffer_len); +} + +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src) +{ + shake128_inc_ctx_clone(ctx_dest, ctx_src); +} + +void hash_ctx_release(hash_instance *ctx) +{ + shake128_inc_ctx_release(ctx); +} diff --git a/crypto_sign/aimer128s/m4speed/hash.h b/crypto_sign/aimer128s/m4speed/hash.h new file mode 100644 index 00000000..dbac6717 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/hash.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT + +#ifndef HASH_H +#define HASH_H + +#include "fips202.h" +#include "params.h" +#include +#include + +static const uint8_t HASH_PREFIX_0 = 0; +static const uint8_t HASH_PREFIX_1 = 1; +static const uint8_t HASH_PREFIX_2 = 2; +static const uint8_t HASH_PREFIX_3 = 3; +static const uint8_t HASH_PREFIX_4 = 4; +static const uint8_t HASH_PREFIX_5 = 5; + +typedef shake128incctx hash_instance; + +#define hash_init AIMER_NAMESPACE(hash_init) +void hash_init(hash_instance *ctx); +#define hash_init_prefix AIMER_NAMESPACE(hash_init_prefix) +void hash_init_prefix(hash_instance *ctx, uint8_t prefix); +#define hash_update AIMER_NAMESPACE(hash_update) +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len); +#define hash_final AIMER_NAMESPACE(hash_final) +void hash_final(hash_instance *ctx); +#define hash_squeeze AIMER_NAMESPACE(hash_squeeze) +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len); +#define hash_skip_squeeze AIMER_NAMESPACE(hash_skip_squeeze) +void hash_skip_squeeze(hash_instance *ctx, size_t buffer_len); +#define hash_ctx_clone AIMER_NAMESPACE(hash_ctx_clone) +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src); +#define hash_ctx_release AIMER_NAMESPACE(hash_ctx_release) +void hash_ctx_release(hash_instance *ctx); + +#endif // HASH_H diff --git a/crypto_sign/aimer128s/m4speed/params.h b/crypto_sign/aimer128s/m4speed/params.h new file mode 100644 index 00000000..91a31ba7 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/params.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer128s_m4speed_##s + +#define SECURITY_BITS 128 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 17 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#define PRE_TREE_IDX 256 + +#endif // PARAMS_H diff --git a/crypto_sign/aimer128s/m4speed/sign.c b/crypto_sign/aimer128s/m4speed/sign.c new file mode 100644 index 00000000..a4992979 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/sign.c @@ -0,0 +1,662 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void commit_and_expand_tape_phase_3(tape_t *tape, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_skip_squeeze(&ctx, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape_phase_3(&tape, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE] = {0,}; + + hash_instance ctx_tree; + hash_init_prefix(&ctx_tree, HASH_PREFIX_4); + hash_update(&ctx_tree, sign->salt, AIMER_SALT_SIZE); + + pre_expand_trees(pre_nodes, &ctx_tree, root_seeds); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_3(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_5(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + + hash_ctx_release(&ctx_tree); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature( + sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, + size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify( + signature, CRYPTO_BYTES, + message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer128s/m4speed/sign.h b/crypto_sign/aimer128s/m4speed/sign.h new file mode 100644 index 00000000..0c168ee0 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/sign.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT + +#ifndef SIGN_H +#define SIGN_H + +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +typedef struct tape_t +{ + GF pt_share; + GF t_shares[AIMER_L]; + GF a_share; + GF c_share; +} tape_t; + +typedef struct mult_chk_t +{ + GF x_shares[AIMER_L + 1]; + GF z_shares[AIMER_L + 1]; +} mult_chk_t; + +typedef struct proof_t +{ + uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE]; + uint8_t missing_commitment[AIMER_COMMIT_SIZE]; + uint8_t delta_pt_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t delta_ts_bytes[AIMER_L][AIM2_NUM_BYTES_FIELD]; + uint8_t delta_c_bytes[AIM2_NUM_BYTES_FIELD]; + uint8_t missing_alpha_share_bytes[AIM2_NUM_BYTES_FIELD]; +} proof_t; + +typedef struct signature_t +{ + uint8_t salt[AIMER_SALT_SIZE]; + uint8_t h_1[AIMER_COMMIT_SIZE]; + uint8_t h_2[AIMER_COMMIT_SIZE]; + proof_t proofs[AIMER_T]; +} signature_t; + +#define aim2_mpc AIMER_NAMESPACE(aim2_mpc) +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF); + +#define commit_and_expand_tape AIMER_NAMESPACE(commit_and_expand_tape) +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party); + +#define commit_and_expand_tape_phase_3 AIMER_NAMESPACE(commit_and_expand_tape_phase_3) +void commit_and_expand_tape_phase_3(tape_t *tape, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party); + +#define run_phase_1 AIMER_NAMESPACE(run_phase_1) +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]); + +#define run_phase_1_to_3 AIMER_NAMESPACE(run_phase_1_to_3) +void run_phase_1_to_3(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]); + +#define run_phase_1_to_5 AIMER_NAMESPACE(run_phase_1_to_5) +void run_phase_1_to_5(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]); + +#endif // SIGN_H diff --git a/crypto_sign/aimer128s/m4speed/tree.c b/crypto_sign/aimer128s/m4speed/tree.c new file mode 100644 index 00000000..3f4fa554 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/tree.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT + +#include "tree.h" +#include "hash.h" +#include +#include +#include + +// Example of tree for [N = 8] +// x +// d = 0: 1 +// d = 1: 2 3 +// d = 2: 4 5 6 7 +// d = 3: 8 9 10 11 12 13 14 15 + +void pre_expand_trees(uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE], + const hash_instance *ctx_tree, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + size_t rep_index, node_index; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx; + + for (rep_index = 0; rep_index < AIMER_T; rep_index++) + { + memcpy(pre_nodes[rep_index][0], root_seeds[rep_index], AIMER_SEED_SIZE); + buffer[0] = (uint8_t)(rep_index); + for (node_index = 1; node_index < PRE_TREE_IDX; node_index++) + { + buffer[1] = (uint8_t)(node_index); + memcpy(buffer + 2, pre_nodes[rep_index][node_index - 1], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_tree); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, pre_nodes[rep_index][2 * node_index - 1], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + } +} + +void expand_tree(uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + const hash_instance *ctx_tree, + size_t rep_index) +{ + size_t index; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx; + + buffer[0] = (uint8_t)(rep_index); + for (index = PRE_TREE_IDX; index < AIMER_N; index++) + { + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[index - 1], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_tree); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[2 * index - 1], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } +} + +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index) +{ + size_t index = cover_index + AIMER_N; + for (size_t depth = 0; depth < AIMER_LOGN; depth++) + { + // index ^ 1 is sibling index + memcpy(reveal_path[depth], nodes[(index ^ 1) - 1], AIMER_SEED_SIZE); + + // go to parent node + index >>= 1; + } +} + +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index) +{ + size_t index, depth, path; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + hash_instance ctx, ctx_; + hash_init_prefix(&ctx_, HASH_PREFIX_4); + hash_update(&ctx_, salt, AIMER_SALT_SIZE); + + for (depth = 1; depth < AIMER_LOGN; depth++) + { + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); + + for (index = (1U << depth); index < (2U << depth); index++) + { + buffer[0] = (uint8_t)(rep_index); + buffer[1] = (uint8_t)(index); + memcpy(buffer + 2, nodes[index - 2], AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, &ctx_); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, nodes[2 * index - 2], AIMER_SEED_SIZE << 1); + hash_ctx_release(&ctx); + } + } + hash_ctx_release(&ctx_); + + path = ((cover_index + AIMER_N) >> (AIMER_LOGN - depth)) ^ 1; + memcpy(nodes[path - 2], reveal_path[AIMER_LOGN - depth], AIMER_SEED_SIZE); +} diff --git a/crypto_sign/aimer128s/m4speed/tree.h b/crypto_sign/aimer128s/m4speed/tree.h new file mode 100644 index 00000000..364c85f7 --- /dev/null +++ b/crypto_sign/aimer128s/m4speed/tree.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT + +#ifndef TREE_H +#define TREE_H + +#include "params.h" +#include "hash.h" +#include +#include + +#define pre_expand_trees AIMER_NAMESPACE(pre_expand_trees) +void pre_expand_trees(uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE], + const hash_instance *ctx_tree, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]); + +#define expand_tree AIMER_NAMESPACE(expand_tree) +void expand_tree(uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + const hash_instance *ctx_tree, + size_t rep_index); + +#define reveal_all_but AIMER_NAMESPACE(reveal_all_but) +void reveal_all_but(uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + const uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE], + size_t cover_index); + +#define reconstruct_tree AIMER_NAMESPACE(reconstruct_tree) +void reconstruct_tree(uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE], + const uint8_t salt[AIMER_SALT_SIZE], + const uint8_t reveal_path[AIMER_LOGN][AIMER_SEED_SIZE], + size_t rep_index, + size_t cover_index); + +#endif // TREE_H diff --git a/crypto_sign/aimer128s/m4stack/__asm_field.S b/crypto_sign/aimer128s/m4stack/__asm_field.S new file mode 120000 index 00000000..308bd9b7 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer128f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/aim2.c b/crypto_sign/aimer128s/m4stack/aim2.c new file mode 120000 index 00000000..7dcc6ae4 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/aim2.h b/crypto_sign/aimer128s/m4stack/aim2.h new file mode 120000 index 00000000..00a5a6e1 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/api.h b/crypto_sign/aimer128s/m4stack/api.h new file mode 120000 index 00000000..a6f9c1df --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/api.h @@ -0,0 +1 @@ +../../aimer128s/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/field.c b/crypto_sign/aimer128s/m4stack/field.c new file mode 120000 index 00000000..56dcd6bb --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/field.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/field.h b/crypto_sign/aimer128s/m4stack/field.h new file mode 120000 index 00000000..a58150b8 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/field.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/hash.c b/crypto_sign/aimer128s/m4stack/hash.c new file mode 120000 index 00000000..deafd134 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/hash.h b/crypto_sign/aimer128s/m4stack/hash.h new file mode 120000 index 00000000..c150ee5f --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/params.h b/crypto_sign/aimer128s/m4stack/params.h new file mode 100644 index 00000000..8f03a035 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer128s_m4stack_##s + +#define SECURITY_BITS 128 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 17 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer128s/m4stack/sign.c b/crypto_sign/aimer128s/m4stack/sign.c new file mode 100644 index 00000000..deaea5b7 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/sign.c @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer128s/m4stack/sign.h b/crypto_sign/aimer128s/m4stack/sign.h new file mode 120000 index 00000000..c46aabad --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/tree.c b/crypto_sign/aimer128s/m4stack/tree.c new file mode 120000 index 00000000..09dffdf6 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer128s/m4stack/tree.h b/crypto_sign/aimer128s/m4stack/tree.h new file mode 120000 index 00000000..53fc8d73 --- /dev/null +++ b/crypto_sign/aimer128s/m4stack/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4speed/__asm_field.S b/crypto_sign/aimer192f/m4speed/__asm_field.S new file mode 100644 index 00000000..26575c28 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/__asm_field.S @@ -0,0 +1,617 @@ +#include "params.h" + +.syntax unified +.cpu cortex-m4 +.thumb + +.text + +.align 2 +.global AIMER_NAMESPACE(GF_to_bytes) +.global AIMER_NAMESPACE(GF_from_bytes) +.global AIMER_NAMESPACE(GF_copy) +.type AIMER_NAMESPACE(GF_to_bytes), %function +.type AIMER_NAMESPACE(GF_from_bytes), %function +.type AIMER_NAMESPACE(GF_copy), %function +AIMER_NAMESPACE(GF_to_bytes): +AIMER_NAMESPACE(GF_from_bytes): +AIMER_NAMESPACE(GF_copy): + out_p .req R0 + in_p .req R1 + + .equ width, 4 + + ldr.w R2, [in_p, #0 * width] + ldr.w R3, [in_p, #1 * width] + str.w R2, [out_p, #0 * width] + str.w R3, [out_p, #1 * width] + + ldr.w R2, [in_p, #2 * width] + ldr.w R3, [in_p, #3 * width] + str.w R2, [out_p, #2 * width] + str.w R3, [out_p, #3 * width] + + ldr.w R2, [in_p, #4 * width] + ldr.w R3, [in_p, #5 * width] + str.w R2, [out_p, #4 * width] + str.w R3, [out_p, #5 * width] + + bx lr + + .unreq in_p + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_set0) +.type AIMER_NAMESPACE(GF_set0), %function +AIMER_NAMESPACE(GF_set0): + out_p .req R0 + + .equ width, 4 + + mov.w R2, #0 + str.w R2, [out_p, #0 * width] + str.w R2, [out_p, #1 * width] + str.w R2, [out_p, #2 * width] + str.w R2, [out_p, #3 * width] + str.w R2, [out_p, #4 * width] + str.w R2, [out_p, #5 * width] + + bx lr + + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_add) +.type AIMER_NAMESPACE(GF_add), %function +AIMER_NAMESPACE(GF_add): + out_p .req R0 + in0_p .req R1 + in1_p .req R2 + + .equ width, 4 + + ldr.w R3, [in0_p, #0 * width] + ldr.w R12, [in1_p, #0 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #0 * width] + + ldr.w R3, [in0_p, #1 * width] + ldr.w R12, [in1_p, #1 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #1 * width] + + ldr.w R3, [in0_p, #2 * width] + ldr.w R12, [in1_p, #2 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #2 * width] + + ldr.w R3, [in0_p, #3 * width] + ldr.w R12, [in1_p, #3 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #3 * width] + + ldr.w R3, [in0_p, #4 * width] + ldr.w R12, [in1_p, #4 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #4 * width] + + ldr.w R3, [in0_p, #5 * width] + ldr.w R12, [in1_p, #5 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #5 * width] + + bx lr + + .unreq out_p + .unreq in0_p + .unreq in1_p + +.macro or_shift_and in_a, con_a, off_a + orr.w \in_a, \in_a, \in_a, lsl #\off_a + and.w \in_a, \in_a, \con_a +.endm + +.align 2 +.global AIMER_NAMESPACE(GF_sqr_s) +.type AIMER_NAMESPACE(GF_sqr_s), %function +AIMER_NAMESPACE(GF_sqr_s): + out_p .req R0 + in_p .req R1 + + in0 .req R2 + in1 .req R3 + in2 .req R4 + in3 .req R5 + in4 .req R6 + in5 .req R7 + in6 .req R8 + in7 .req R9 + + .equ C0, 1431655765 // 0x55555555 + .equ C1, 858993459 // 0x33333333 + .equ C2, 252645135 // 0x0F0F0F0F + .equ C3, 16711935 // 0x00FF00FF + .equ C4, 4294967295 // 0xFFFFFFFF + .equ width, 4 + + push.w {R4-R10, lr} + + ldr.w in0, [in_p, #2 * width] // a[1] + ldr.w in2, [in_p, #3 * width] + ldr.w in4, [in_p, #4 * width] // a[2] + ldr.w in6, [in_p, #5 * width] + + lsr.w in1, in0, #16 + lsr.w in3, in2, #16 + lsr.w in5, in4, #16 + lsr.w in7, in6, #16 + + mov.w R10, C4 + + and.w in0, in0, R10, lsr #16 + and.w in2, in2, R10, lsr #16 + and.w in4, in4, R10, lsr #16 + and.w in6, in6, R10, lsr #16 + + or_shift_and in0, C3, 8 + or_shift_and in1, C3, 8 + or_shift_and in2, C3, 8 + or_shift_and in3, C3, 8 + or_shift_and in4, C3, 8 + or_shift_and in5, C3, 8 + or_shift_and in6, C3, 8 + or_shift_and in7, C3, 8 + + or_shift_and in0, C2, 4 + or_shift_and in1, C2, 4 + or_shift_and in2, C2, 4 + or_shift_and in3, C2, 4 + or_shift_and in4, C2, 4 + or_shift_and in5, C2, 4 + or_shift_and in6, C2, 4 + or_shift_and in7, C2, 4 + + or_shift_and in0, C1, 2 + or_shift_and in1, C1, 2 + or_shift_and in2, C1, 2 + or_shift_and in3, C1, 2 + or_shift_and in4, C1, 2 + or_shift_and in5, C1, 2 + or_shift_and in6, C1, 2 + or_shift_and in7, C1, 2 + + or_shift_and in0, C0, 1 + or_shift_and in1, C0, 1 + or_shift_and in2, C0, 1 + or_shift_and in3, C0, 1 + or_shift_and in4, C0, 1 + or_shift_and in5, C0, 1 + or_shift_and in6, C0, 1 + or_shift_and in7, C0, 1 + + // t = temp[3] ^ ((temp[5] >> 57) ^ (temp[5] >> 62) ^ (temp[5] >> 63)); + eor.w in2, in2, in7, lsr #25 + eor.w in2, in2, in7, lsr #30 + eor.w in2, in2, in7, lsr #31 + + // c[2] = temp[2] ^ temp[5]; + eor.w in0, in0, in6 + eor.w in1, in1, in7 + + // c[2] ^= (temp[5] << 7) | ((temp[4] >> 57); + // c[2] ^= (temp[5] << 2) | ((temp[4] >> 62); + // c[2] ^= (temp[5] << 1) | ((temp[4] >> 63); + eor.w in0, in0, in5, lsr #25 + eor.w in0, in0, in5, lsr #30 + eor.w in0, in0, in5, lsr #31 + + eor.w in0, in0, in6, lsl #7 + eor.w in0, in0, in6, lsl #2 + eor.w in0, in0, in6, lsl #1 + + eor.w in1, in1, in6, lsr #25 + eor.w in1, in1, in6, lsr #30 + eor.w in1, in1, in6, lsr #31 + + eor.w in1, in1, in7, lsl #7 + eor.w in1, in1, in7, lsl #2 + eor.w in1, in1, in7, lsl #1 + + str.w in0, [out_p, #4 * width] + str.w in1, [out_p, #5 * width] + + ldr.w in0, [in_p, #0 * width] // a[0] + ldr.w in6, [in_p, #1 * width] + + lsr.w in1, in0, #16 + lsr.w in7, in6, #16 + + and.w in0, in0, R10, lsr #16 + and.w in6, in6, R10, lsr #16 + + or_shift_and in0, C3, 8 + or_shift_and in1, C3, 8 + or_shift_and in6, C3, 8 + or_shift_and in7, C3, 8 + + or_shift_and in0, C2, 4 + or_shift_and in1, C2, 4 + or_shift_and in6, C2, 4 + or_shift_and in7, C2, 4 + + or_shift_and in0, C1, 2 + or_shift_and in1, C1, 2 + or_shift_and in6, C1, 2 + or_shift_and in7, C1, 2 + + or_shift_and in0, C0, 1 + or_shift_and in1, C0, 1 + or_shift_and in6, C0, 1 + or_shift_and in7, C0, 1 + + // c[1] = temp[1] ^ temp[4]; + eor.w in6, in6, in4 + eor.w in7, in7, in5 + + // c[1] ^= (temp[4] << 7) | (t >> 57); + // c[1] ^= (temp[4] << 2) | (t >> 62); + // c[1] ^= (temp[4] << 1) | (t >> 63); + eor.w in6, in6, in3, lsr #25 + eor.w in6, in6, in3, lsr #30 + eor.w in6, in6, in3, lsr #31 + + eor.w in6, in6, in4, lsl #7 + eor.w in6, in6, in4, lsl #2 + eor.w in6, in6, in4, lsl #1 + + eor.w in7, in7, in4, lsr #25 + eor.w in7, in7, in4, lsr #30 + eor.w in7, in7, in4, lsr #31 + + eor.w in7, in7, in5, lsl #7 + eor.w in7, in7, in5, lsl #2 + eor.w in7, in7, in5, lsl #1 + + str.w in6, [out_p, #2 * width] + str.w in7, [out_p, #3 * width] + + // c[0] = temp[0] ^ t; + eor.w in0, in0, in2 + eor.w in1, in1, in3 + + // c[0] ^= (t << 7); + // c[0] ^= (t << 2); + // c[0] ^= (t << 1); + eor.w in0, in0, in2, lsl #7 + eor.w in0, in0, in2, lsl #2 + eor.w in0, in0, in2, lsl #1 + + eor.w in1, in1, in2, lsr #25 + eor.w in1, in1, in2, lsr #30 + eor.w in1, in1, in2, lsr #31 + + eor.w in1, in1, in3, lsl #7 + eor.w in1, in1, in3, lsl #2 + eor.w in1, in1, in3, lsl #1 + + str.w in0, [out_p, #0 * width] + str.w in1, [out_p, #1 * width] + + pop.w {R4-R10, pc} + + // unlink register name + .unreq in_p + .unreq out_p + +.macro lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + ldr \out1_0, [\sp1, #0] + ldr \in0_2, [\sp1, #4] + + ldr \in0_0, [\sp0, #0] + ldr \in0_1, [\sp0, #4] + eor \in0_1, \in0_1, \out1_0 +.endm + +.macro lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + lsr \in0_3, \in0_2, #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + lsl \in0_3, \in0_3, #4 + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + orr \in0_3, \in0_3, \in0_2, lsr #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + lsl \in0_3, \in0_3, #4 + and \sp1, \mask, \b0_1, lsl #\offset + orr \in0_3, \in0_3, \in0_2, lsr #28 + and \sp0, \mask, \b0_0, lsl #\offset + + lsl \in0_2, \in0_2, #4 + add \sp1, \sp1, sp + orr \in0_2, \in0_2, \in0_1, lsr #28 + add \sp0, \sp0, sp + + lsl \in0_1, \in0_1, #4 + ldmia \sp1, {\out1_0-\out1_1} + orr \in0_1, \in0_1, \in0_0, lsr #28 + ldmia \sp0, {\out0_0-\out0_1} + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + and \mask, \one, \r0_ret, lsr #\offset + sub \mask, \zero, \mask + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.macro last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + sub \mask, \zero, \r0_ret, lsr #\offset + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.global AIMER_NAMESPACE(poly64_mul) +.type AIMER_NAMESPACE(poly64_mul), %function +AIMER_NAMESPACE(poly64_mul): + t0_0 .req R0 + t0_1 .req R1 + t1_0 .req R2 + t1_1 .req R3 + t2_0 .req R4 + t2_1 .req R5 + t3_0 .req R6 + t3_1 .req R7 + t4_0 .req R8 + t4_1 .req R9 + t5_0 .req R10 + t5_1 .req R11 + + r1_copy .req R12 + t_base .req R14 + + sp0 .req R12 + sp1 .req R14 + + b0_0 .req R0 + b0_1 .req R1 + + in0_0 .req R2 + in0_1 .req R3 + in0_2 .req R4 + in0_3 .req R5 + + out0_0 .req R6 + out0_1 .req R7 + out1_0 .req R8 + out1_1 .req R9 + + mask .req R10 + + zero .req R6 + one .req R7 + + r0_ret .req R8 + + mask0_0 .req R9 + mask0_1 .req R11 + mask0_2 .req R12 + + push {R4-R11, lr} + push {R2-R3} + + ldr t1_0, [R0, #0] + ldr t1_1, [R0, #4] + push {t1_1} + + sub sp, #128 // allocating space in the stack + // 8 bytes * 16 = 128 bytes + mov t_base, sp + mov r1_copy, R1 + + mov t0_0, #0 + mov t0_1, #0 + + and t1_1, #0x1FFFFFFF + + lsl t2_1, t1_1, #1 + orr t2_1, t2_1, t1_0, lsr #31 + lsl t2_0, t1_0, #1 + + eor t3_0, t1_0, t2_0 + eor t3_1, t1_1, t2_1 + + lsl t4_1, t2_1, #1 + orr t4_1, t4_1, t2_0, lsr #31 + lsl t4_0, t2_0, #1 + + eor t5_0, t1_0, t4_0 + eor t5_1, t1_1, t4_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t0_0, t2_0, t4_0 + eor t0_1, t2_1, t4_1 + + lsl t2_1, t4_1, #1 + orr t2_1, t2_1, t4_0, lsr #31 + lsl t2_0, t4_0, #1 + + eor t5_0, t2_0, t3_0 + eor t5_1, t2_1, t3_1 + + eor t3_0, t2_0, t1_0 + eor t3_1, t2_1, t1_1 + + eor t4_0, t4_0, t0_0 + eor t4_1, t4_1, t0_1 + + eor t4_0, t4_0, t2_0 + eor t4_1, t4_1, t2_1 + + eor t1_0, t1_0, t0_0 + eor t1_1, t1_1, t0_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t1_0, t5_0, t0_0 + eor t1_1, t5_1, t0_1 + + eor t2_0, t2_0, t0_0 + eor t2_1, t2_1, t0_1 + + eor t3_0, t3_0, t0_0 + eor t3_1, t3_1, t0_1 + + eor t0_0, t4_0, t0_0 + eor t0_1, t4_1, t0_1 + + stmia t_base, {t0_0-t3_1} // 4 bytes X 8 elements = 32 bytes + + ldmia r1_copy, {b0_0-b0_1} + mov mask, #0x00000078 + + lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 25 + lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 21 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 17 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 13 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 9 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 5 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 1 + lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 3 + + mov zero, #0 + mov one, #1 + ldr r0_ret, [sp, #128] + + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 29 + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 30 + last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 31 + + ldr R0, [sp, #132] + ldr R1, [sp, #136] + add sp, #140 // restoring stack + + str in0_0, [R1, #0] + str in0_1, [R1, #4] + + str in0_2, [R0, #0] + str in0_3, [R0, #4] + + pop {R4-R11, pc} + + // unlink register name + .unreq t0_0 + .unreq t0_1 + .unreq t1_0 + .unreq t1_1 + .unreq t2_0 + .unreq t2_1 + .unreq t3_0 + .unreq t3_1 + .unreq t4_0 + .unreq t4_1 + .unreq t5_0 + .unreq t5_1 + + .unreq r1_copy + .unreq t_base + + .unreq sp0 + .unreq sp1 + + .unreq b0_0 + .unreq b0_1 + + .unreq in0_0 + .unreq in0_1 + .unreq in0_2 + .unreq in0_3 + + .unreq out0_0 + .unreq out0_1 + .unreq out1_0 + .unreq out1_1 + + .unreq mask + + .unreq zero + .unreq one + + .unreq r0_ret + + .unreq mask0_0 + .unreq mask0_1 + .unreq mask0_2 diff --git a/crypto_sign/aimer192f/m4speed/aim2.c b/crypto_sign/aimer192f/m4speed/aim2.c new file mode 100644 index 00000000..b5dbbc85 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/aim2.c @@ -0,0 +1,491 @@ +// SPDX-License-Identifier: MIT + +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +// inverse Mersenne S-box with e1 = 17 +// (2 ^ 17 - 1) ^ (-1) mod (2 ^ 192 - 1) +// = 0xad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6ad6b56b5ab5ad5 +// ad6b56b5ab5ad5 ad6 ad6b56b5ab5ad5 ad6 ad6b56b5ab5ad5 +void GF_exp_invmer_e_1(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}, t2 = {0,}; + GF table_5 = {0,}, table_6 = {0,}; + GF table_a = {0,}, table_b = {0,}, table_d = {0,}; + + // t1 = in ^ 4 + GF_sqr_s(table_d, in); + GF_sqr_s(t1, table_d); + + // table_5 = in ^ 5 + GF_mul_s(table_5, t1, in); + // table_6 = in ^ 6 + GF_mul_s(table_6, table_5, in); + // table_a = in ^ 10 = (in ^ 5) ^ 2 + GF_sqr_s(table_a, table_5); + // table_b = in ^ 11 + GF_mul_s(table_b, table_a, in); + // table_d = in ^ 13 + GF_mul_s(table_d, table_b, table_d); + + // t1 = in ^ (0xad) + GF_sqr_s(t1, table_a); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t2 = in ^ (0xad 6), table_d = in ^ (0xad5) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t2, t1, table_6); + GF_mul_s(table_d, t1, table_5); + + // t1 = in ^ (0xad6 b) + GF_sqr_s(t1, t2); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xad6b 5) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xad6b5 6) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xad6b56 b) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xad6b56b 5) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xad6b56b5 a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xad6b56b5a b) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xad6b56b5ab 5) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_5); + + // table_d = in ^ (0xad6b56b5ab5 ad5) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(table_d, t1, table_d); + + // t1 = n ^ (0xad6b56b5ab5ad5 ad6) + GF_sqr_s(t1, table_d); + for (i = 1; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xad6b56b5ab5ad5ad6 ad6b56b5ab5ad5) + for (i = 0; i < 56; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xad6b56b5ab5ad5ad6ad6b56b5ab5ad5 ad6) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xad6b56b5ab5ad5ad6ad6b56b5ab5ad5ad6 ad6b56b5ab5ad5) + for (i = 0; i < 56; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, table_d); +} + +// inverse Mersenne S-box with e2 = 47 +// (2 ^ 47 - 1) ^ (-1) mod (2 ^ 192 - 1) +// = 0xddddddddddddbbbbbbbbbbbb777777777776eeeeeeeeeeed +// dddd dddd dddd bb bb bb bb bb bb 77 77 77 77 77 76 ee ee ee ee ee ed +void GF_exp_invmer_e_2(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}, t2 = {0,}; + GF table_6 = {0,}, table_7 = {0,}; + GF table_b = {0,}, table_d = {0,}, table_e = {0,}; + + // t1 = in ^ 3 + GF_sqr_s(table_d, in); + GF_mul_s(t1, table_d, in); + + // table_6 = (in ^ 3) ^ 2 + GF_sqr_s(table_6, t1); + // table_7 = in ^ 7 + GF_mul_s(table_7, table_6, in); + // table_b = in ^ 11 + GF_sqr_s(table_b, table_d); + GF_mul_s(table_b, table_b, table_7); + // table_d = in ^ 13 + GF_mul_s(table_d, table_6, table_7); + // table_e = in ^ 14 + GF_sqr_s(table_e, table_7); + + // table_b = in ^ (0xbb) + GF_sqr_s(t1, table_b); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_b, t1, table_b); + + // table_7 = in ^ (0x77), table_6 = in ^ (0x76) + GF_sqr_s(t1, table_7); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_6, t1, table_6); + GF_mul_s(table_7, t1, table_7); + + // t2 = in ^ (0xdd) + GF_sqr_s(t1, table_d); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t2, t1, table_d); + + // table_e = in ^ (0xee), table_d = in ^ (0xed) + GF_sqr_s(t1, table_e); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_d, t1, table_d); + GF_mul_s(table_e, t1, table_e); + + // t2 = in ^ (0xdd dd) + GF_sqr_s(t1, t2); + for (i = 1; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t2, t1, t2); + + // t1 = in ^ (0xdddd dddd) + GF_sqr_s(t1, t2); + for (i = 1; i < 16; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xdddddddd dddd) + for (i = 0; i < 16; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t1 = in ^ (0xdddddddddddd bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbb bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbbbb bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbbbbbb bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbbbbbbbb bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbb bb) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb 77) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb77 77) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb7777 77) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777 77) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb77777777 77) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb7777777777 76) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776 ee) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_e); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776ee ee) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_e); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776eeee ee) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_e); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776eeeeee ee) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_e); + + // t1 = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776eeeeeeee ee) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_e); + + // out = in ^ (0xddddddddddddbbbbbbbbbbbb777777777776eeeeeeeeee ed) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, table_d); +} + +// Mersenne exponentiation with e_star = 5 +void GF_exp_mer_e_star(GF out, const GF in) +{ + GF t1 = {0,}; + GF t2 = {0,}; + + // t2 = a ^ (2 ^ 2 - 1) + GF_sqr_s(t1, in); + GF_mul_s(t2, t1, in); + + // t1 = a ^ (2 ^ 3 - 1) + GF_sqr_s(t1, t2); + GF_mul_s(t1, t1, in); + + // out = a ^ (2 ^ 5 - 1) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(out, t1, t2); +} + +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + uint8_t buf[AIM2_NUM_BYTES_FIELD]; + uint64_t ormask, lmask, umask; + hash_instance ctx; + GF temp = {0,}; + + // initialize hash + hash_init(&ctx); + hash_update(&ctx, iv, AIM2_IV_SIZE); + hash_final(&ctx); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t row = 0; row < AIM2_NUM_BITS_FIELD; row++) + { + hash_squeeze(&ctx, buf, AIM2_NUM_BYTES_FIELD); + GF_from_bytes(temp, buf); + + ormask = ((uint64_t)1) << (row % 64); + lmask = ((uint64_t)-1) << (row % 64); + umask = ~lmask; + + size_t inter = row / 64; + size_t col_word; + for (col_word = 0; col_word < inter; col_word++) + { + // L is zero, U is full + matrix_L[num][row][col_word] = 0; + matrix_U[num][row][col_word] = temp[col_word]; + } + matrix_L[num][row][inter] = (temp[inter] & lmask) | ormask; + matrix_U[num][row][inter] = (temp[inter] & umask) | ormask; + for (col_word = inter + 1; col_word < AIM2_NUM_WORDS_FIELD; col_word++) + { + // L is full, U is zero + matrix_L[num][row][col_word] = temp[col_word]; + matrix_U[num][row][col_word] = 0; + } + } + } + + hash_squeeze(&ctx, (uint8_t *)vector_b, AIM2_NUM_BYTES_FIELD); + hash_ctx_release(&ctx); +} + +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t i = 0; i < AIM2_NUM_BITS_FIELD; i++) + { + GF_transposed_matmul(matrix_A[num][i], matrix_U[num][i], + (const GF *)matrix_L[num]); + } + } +} + +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + + GF state[AIM2_NUM_INPUT_SBOX]; + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, pt); + + // generate random matrix + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + // linear component: constant addition + GF_add(state[0], pt_GF, aim2_constants[0]); + GF_add(state[1], pt_GF, aim2_constants[1]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(state[0], state[0]); + GF_exp_invmer_e_2(state[1], state[1]); + + // linear component: affine layer + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_U[0]); + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_L[0]); + + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_U[1]); + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_L[1]); + + GF_add(state[0], state[0], state[1]); + GF_add(state[0], state[0], vector_b); + + // non-linear component: Mersenne S-box + GF_exp_mer_e_star(state[0], state[0]); + + // linear component: feed-forward + GF_add(ct_GF, state[0], pt_GF); + + GF_to_bytes(ct, ct_GF); +} + +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt) +{ + // linear component: constant addition + GF_add(sbox_outputs[0], pt, aim2_constants[0]); + GF_add(sbox_outputs[1], pt, aim2_constants[1]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(sbox_outputs[0], sbox_outputs[0]); + GF_exp_invmer_e_2(sbox_outputs[1], sbox_outputs[1]); +} diff --git a/crypto_sign/aimer192f/m4speed/aim2.h b/crypto_sign/aimer192f/m4speed/aim2.h new file mode 100644 index 00000000..b30d4cb9 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/aim2.h @@ -0,0 +1,435 @@ +// SPDX-License-Identifier: MIT + +#ifndef AIM2_H +#define AIM2_H + +#include "field.h" +#include "params.h" +#include + +static const GF aim2_constants[AIM2_NUM_INPUT_SBOX] = +{ + {0xc0ac29b7c97c50dd, 0xbe5466cf34e90c6c, 0x452821e638d01377}, + {0xd1310ba698dfb5ac, 0x9216d5d98979fb1b, 0x3f84d5b5b5470917} +}; + +static const GF aim2_e1_power_matrix[AIM2_NUM_BITS_FIELD] = +{ + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, + {0x24187d60404121f6, 0x994d0c36800d12c1, 0x00911dd52a0924f1}, + {0x764f49362db3c478, 0x3bcc2005010a3fa6, 0x402147d6af1a6ff4}, + {0x1c0878591079091d, 0x9b08ffde1c878f59, 0x8ff70000000021c2}, + {0xbc23dcb74c10198f, 0xe23fb48357412666, 0x70031ccb7f97795b}, + {0xffa72d9a27550570, 0xc7dab56f7d5ade7c, 0x78cd4c6283845a4b}, + {0x655b34aa00430d9a, 0x0150004209eea37c, 0xea5061fe40551141}, + {0x291b4f90d5814c36, 0xcda4bfb158be9a9b, 0x0d4558cc51c4127c}, + {0xbe4eb108521087f8, 0x855a49e49b1f9165, 0xfa15129aaa8d8745}, + {0xef60386cb35ccf9a, 0x5115765ff710f9f9, 0x205677891921e135}, + {0xbed705ee53ec571d, 0x97ef8c6dd0851236, 0xdfb8887b08ee7b6d}, + {0x6731ce99be825c5a, 0x78665e68455482e1, 0x8b867f2046054b3e}, + {0x008fe70500592609, 0x6419eeb2829f34c3, 0x8f95a35e28a915f4}, + {0x4dd556b654d54730, 0x07e8d738dc4b2c41, 0x6de823272f319c70}, + {0xc805945260585e93, 0xf3efb93595438399, 0x387f3dab97add8fd}, + {0x8825784a2bb54db6, 0x8d1d21f68a9fed14, 0xd72c5de2e4375500}, + {0xd9fbd5d41179e461, 0xbaa9f9428fe27896, 0x49998ea2c43c70ee}, + {0xba1e061ac9218b6b, 0x93a1c1ea0a23984a, 0x145015f4bca9f514}, + {0xb2829eadb1319c61, 0xf21008aca9c587af, 0x491dfc66b48bb406}, + {0xdc192cc5729969e6, 0x19aeec2c6a3facb8, 0xeaf05f73c034e88f}, + {0x5cc5d35af8af5039, 0x64bfd6b3c8401142, 0x4d083af0e0cecd4f}, + {0xbcb663181c16e418, 0x9d73d6e08b40b1cf, 0xe6a19d2ea608b779}, + {0x8f9e2660cdf64ce3, 0x6e790dfe030df1e7, 0xf36bdb76802d4809}, + {0x24e27b21fdd534eb, 0x9b2abc8327bb58a6, 0xa60607784f3d2a8a}, + {0x6470b72d839b493a, 0x3de3bd12dbc9236b, 0xab0e0e81db838cab}, + {0x9fa25765dfa0dc0c, 0xa4866af77f3c1d39, 0xa22985fd177fb75e}, + {0x1bd0dcf82dfcbaf6, 0x2778cab77faeae14, 0x144c9d871ac906e8}, + {0xab206aa0299e585a, 0x1f2a1c115b2b24e7, 0xd683dc1df4f0e8e4}, + {0x3db096486b11d3fc, 0x1d88f50f57fb1318, 0xfbdbd02cf211be3b}, + {0x83c0ed680040dbeb, 0x01d5321e9c73822a, 0x5c78f9da86ddc253}, + {0xed72eb240cfd7027, 0xe43295f2eab71065, 0x7dad74ed8a4daf27}, + {0x593448e3f55865bc, 0x3dbc22ef1d415b62, 0xff617d36a6e04fd7}, + {0x79fee82d5e5f6225, 0xe933e7ffba3ad69f, 0x11333262fecf9f21}, + {0xaccf982f89364968, 0x961868954276eacd, 0x3903286905b4951a}, + {0x15f9d8aff0e99b99, 0x37d7fc3823e38e15, 0x8f3cf305ce9c3317}, + {0x5f1db90ec8ff178c, 0xef61eb5b69c0cf16, 0xd6d4428841ba2406}, + {0x6c1d820160b3e589, 0x1655a37c12244e16, 0x1506fe0d42af221a}, + {0x776220241d5f52f8, 0xbbd873a1a32d77fc, 0x2967ed932de2646d}, + {0xb360b6c691f374f5, 0xe152921a89b1bb3a, 0x9bb32e5d9871acf2}, + {0xbbae8029d2f0211d, 0xdfa58ed49cdc469a, 0x298aa1fd3b5fee94}, + {0x311334572c4f58e2, 0xbd79cb94c83a4a65, 0x097731c2b9f63b2f}, + {0x202f161d6f618d78, 0xb30f00f7d63d2b1c, 0xba3ba40cb586c147}, + {0x6f6de8a66957b811, 0x933c64f745e4cb26, 0xe60acca62b3467da}, + {0x2d52d8e03eadc408, 0x020b8ada8b0cbcfb, 0x97e520c15d31d866}, + {0x17f79f53394c41f8, 0x8057746b55d4354d, 0x29944f234150b558}, + {0xd48d6f8d466f4fb7, 0xe62aa6c05e099abf, 0xe72196d812cdf8ff}, + {0x31086eee778187b7, 0x5f39e6312ab8e7fc, 0xd2794f291ba18edc}, + {0x8bb7a2d05d52dd01, 0x898fee2a72a51691, 0xaf83c32d4f112cdf}, + {0xf219effd62769131, 0x006ad7baac86fb08, 0xae1e7bed2f88d4eb}, + {0x085e604007b4850e, 0x74969c7dc17959a0, 0x70af70f460fd6854}, + {0x85048e661ea730d2, 0xccb4840c40f6c89e, 0xcb4b3836c98d0776}, + {0xac7fadd0308807de, 0x93e5399425e1f409, 0x6cebcde031477957}, + {0x12b09fb9d6bb04ff, 0xa5b0c0475b17d882, 0x9a2d1dc52a42cbfb}, + {0x2a89655cb1fec3db, 0xb8a64412d508abdf, 0x3998b588ed04feab}, + {0xa8687e88bff0829c, 0x671e2f2b99afe070, 0x2c08c6f71aa0fa09}, + {0xe1ce5c820d6be145, 0x7c9485f929d3a113, 0x35a20e96293d131a}, + {0xba53e0ea72f26b2a, 0x2c4dc2a431baa81b, 0x19674137360734db}, + {0xde4269315e846bfb, 0x9ed583db0c4ca349, 0x315852fa0660ab68}, + {0x00ae2ff5c859fcd1, 0x8a404e1ee645e1db, 0x9feadfee4a6a10b9}, + {0x098454c0f608253b, 0xbf09d16ec3b96f79, 0xe63451db95697baf}, + {0xa422cc6c5adc283f, 0xb7854c10a36c12d0, 0x9650b028e25b9107}, + {0x8da1b75903dd2aa8, 0xef8f3a20c77f4c10, 0x11e6a8d176631e6f}, + {0xe70563f20a26d72a, 0xc706a9184b4269ec, 0x01707c8cd370854b}, + {0x4c497f712f722710, 0x40d97c17a9f96a81, 0x61ac088c7242b19b}, + {0x9c1188e5b2c4043a, 0x15c4ce5e386918fd, 0xc2c19cddc8022f62}, + {0x334dd52624b37647, 0x0ecfeb52b8db6b3a, 0x7cb0cc6a541d915f}, + {0x0d2da3de5da05ab9, 0x4c8403040eb7a0a8, 0xaa43178d698e1d16}, + {0x94dd24ac7d70454e, 0x19c81eacd2305f1d, 0xab7995a48e6230a2}, + {0xc4c2698143f7ebe6, 0x9a9c3bf3c8dbc9bc, 0xef2ce69e69cf09cf}, + {0xe4d55e8362bd6084, 0x4bd67382e024dfd0, 0x821aed870355bf63}, + {0xd76139f98e468054, 0x61f1798f51310a13, 0x29046f782268e0dc}, + {0xd415fc0d991dd093, 0x40c961038916982c, 0x50c6b0ef248e059b}, + {0x9964bad18a8082f1, 0x666ff6785e18a4dd, 0x8ef30e5710f8282b}, + {0xb414e2f6230594fe, 0x1bc6a73e670570f9, 0x58556965657d0723}, + {0x7923079ff8bc88c9, 0x2009ba12607a4104, 0x79486291900310c9}, + {0xbee4fd3a8ba864ef, 0x5df270cc7b675b45, 0x8fe410ae3a6416b4}, + {0xed8ea038500ce1aa, 0x23cfffa4b08f7923, 0x24391c9872e1db52}, + {0xea11414bd1ee6f54, 0x57a5ebe50ea4869b, 0x18f580aebbed4614}, + {0x4d0c81d6ef843f2f, 0xfd169854c78d4b18, 0x7c36b2afccb84371}, + {0x0c639f2dc76998e0, 0xdc8e28abec0a421f, 0xfba0c0a5251cd144}, + {0x766dda3b823a1b74, 0x7f6d206bbd49261d, 0x710de4ad8beaa62e}, + {0x7abd0b3c484d3910, 0x58abd14b6ee2e49b, 0x78652fe31e4d6d19}, + {0x4dce3f2a407a25c2, 0x57d6ce10b19b7b99, 0x29cabd29d03528c3}, + {0xf03c709f8b55bbc2, 0x10f449ee0641e483, 0xf60bd442dfd1a803}, + {0x51d8a3af211b35bb, 0x2b0c872b328250e9, 0xb67d77e5c9d6d27a}, + {0x9a731c8f091b2c24, 0x04cf41a716e1e225, 0x9b354a2d84899ec9}, + {0x0748672bb3e504fb, 0xda648aaa478a326c, 0x0d85a4a55979e5ca}, + {0xbb732bb90d147586, 0x446c43c25a19dc66, 0x18523f7f708eff36}, + {0xc549edb1f37b1b15, 0x719aa23612aac7e4, 0x2c771e685e380ec2}, + {0xe2b6b4207ad6a4b6, 0xf7cc2a116c9527ba, 0xdf6e5d55b2406221}, + {0xb67a2baac610e044, 0xd425d94d1ebe4051, 0xb7bd1ce70c015395}, + {0x64ff5ff72d64a1b1, 0xdaca2b8812d90ae6, 0x79a022efcc594eaf}, + {0xc93cfa6de67bcacd, 0xa179dce6ffd14aec, 0x31528f0f0f3c6817}, + {0x3ec18f7af7342039, 0xf8d7aa856a662ed9, 0x097b848460df8308}, + {0xf037fa04d6ff2eb4, 0x1b6ec290719d4d0a, 0xe20e86a3b38d743e}, + {0x8aea64bccc94d424, 0x2cc260f4f6b65bad, 0x355d31f6d901a260}, + {0x140e5ae17cc96cb4, 0x620ee0a86b0eda0a, 0xb3fcecb29d358575}, + {0x5ec85d1f29af07e2, 0xd6c8834f22331d6a, 0xcef37a820396e162}, + {0xe344085d2eabc755, 0x6c6b136959c8ef7a, 0xbb22e260fa6a677a}, + {0x7a64bfaa585ae30a, 0xe317efc967bbe220, 0x9a9780dfb02d4b7e}, + {0x98c71744cd706ceb, 0xd177e9274ab5f551, 0x8353064dea82d011}, + {0xff04c178eec23d3e, 0x2f460919349f2d47, 0x78fe5c7e69a969f2}, + {0x40b0e4b5ba731b12, 0xdfdf6fb48e1eacca, 0x418adb73cc0cac43}, + {0x07e5547b971dc85a, 0x9bb127d9e57350ef, 0xdb9801dd4d74063c}, + {0x85c01e6cb0183fd9, 0x3ed03735d2254d39, 0x759b3422ff5ef8f1}, + {0x6d72fa4b71c48c98, 0x3a991af37f04f9e1, 0xb32059432a68082f}, + {0x3fe283302875d557, 0x8173481a149eee28, 0xeb7766a31793b0be}, + {0x7acae2d67f591873, 0xb326c3aa2ed4173a, 0x1946cb0d5f62d04d}, + {0x23bef9ae772d7f05, 0xe0bfc86b1d88610d, 0x74f165bcee4734eb}, + {0x1d4726ce666680c3, 0x2ce0e6d607113532, 0xffc5de80c34f2df4}, + {0xc2c05b149cdd1b58, 0x6944e26394cbe4d2, 0x97958f196f8c4c6b}, + {0x270456c0b2e40aa0, 0x55d5c764d7670e84, 0x717d55b1ebf4aac6}, + {0x20bc0c1aa67ad034, 0xd4281becc759401d, 0xa34c23a734c590ac}, + {0x5847ae572b03bf5c, 0xfcac4377aa016371, 0xc37160769e1a862d}, + {0x7dd17fc6d6f74010, 0x5b327c27eb1048e0, 0x9bdfc698b132189d}, + {0xab7a432b47cdddcb, 0xa929bbd83ccbd1f9, 0x4d454da5089a34f2}, + {0xb39461490efcedca, 0x53d60b8883762f77, 0x38149fe44801d6e1}, + {0x7c94c03395823033, 0xdeeb603aad8b99f6, 0x6135272e4190f922}, + {0x253f212e339c57b8, 0x4fbc0d5dd968a708, 0xf66bd639e3fb013b}, + {0x6607bb8d9f1426d8, 0x0b9156b2a938e184, 0x1d6f7d7b46319a77}, + {0x408e99af5df09232, 0xea04d07e17d71e98, 0x0961e3735a066ceb}, + {0x0ac48cb89fc1d495, 0xe5ed5004fadbdcb6, 0xb371ec4e641dbdfd}, + {0x870fba78bc9a5840, 0xa1372a9ae9b35641, 0xd7b9b31aedb9368d}, + {0x9ec8171425817f91, 0x46d3a766e6d0c217, 0x6d410a83cdfd91e4}, + {0xbaaf0e5bac52a284, 0x6184eb30dcfa0676, 0x10c8fb0ed6d0bdc9}, + {0xac8814d3e0fe8707, 0x86d0ff1167e53b8a, 0x10e6600f84bbd4e6}, + {0x747c0349c6a589dd, 0xf944627e4ef37152, 0x28e5a0f135a5a9bb}, + {0x382e5c28e3026945, 0xee877613758af703, 0x2d922be5a1610e7f}, + {0xcadae8499bb4cdb7, 0xd090031f77613a0d, 0xb775a4e76fd94b4f}, + {0xd09a761e6898eced, 0x5669242c2f84d5da, 0x3d97c6bded80996e}, + {0x2f95de059a47e03f, 0xfa75be47169ed83f, 0x87d30a6c8dff4a90}, + {0xf8588b0cb7a0c692, 0xd246208d9f6dc4fb, 0xe36d575d6c2485c0}, + {0x48c08c7013df5c58, 0x4d37effdea32dc30, 0xff80378ec9caad7d}, + {0xf9e43db917658f34, 0xb76c0ff79e41f707, 0x8e4935c0b5c08083}, + {0xb33f84c0bc9ef48d, 0xaab63f4f9f339a4c, 0xae55cf665e81d500}, + {0x15e234561c4632f1, 0xe084e7a57d035829, 0xbaa1511cb0ed12a0}, + {0x74f83ba7ec3568de, 0x1d7ecb2f352fdb0b, 0xd76964def60c29f6}, + {0xd1c2b81f2e13a757, 0xf84d5af929439b5d, 0xc34a2d0878b81e8d}, + {0x47767837fdba926b, 0x5683aec561752e96, 0x961ca0e7d4439beb}, + {0x7d73c95d078b625f, 0x6e621c6b3817a9f1, 0xd300b482fda5d226}, + {0x2cf83b998a66fb35, 0x4f0359eaa9684bfb, 0x2c460d7b4765cbc7}, + {0xa5c0e6cf67395406, 0xb659d3e82276235d, 0x2c5c851229561369}, + {0x3168901c3d8747a6, 0x4541eabd5d866402, 0xb768bb5b1a6b8379}, + {0xb5fa4b6cdc308417, 0x8100841dbbeb59e8, 0x4db5eb632adc8553}, + {0x2622070061628fa6, 0xc66a1ed278866e50, 0xfad328db6fb4acba}, + {0x6734cb1adfc5db87, 0xd7f8cfed34d7e713, 0x259e5c52bef9b101}, + {0xa077ba5e97f9e1c0, 0x21edc3275eed4b8f, 0xc2ddffec584d31bc}, + {0xe8074b1519eb9faa, 0xa35f39294a8283ed, 0xffbfa9f0fdcce212}, + {0x49406434389cd06b, 0x5241069e873cd010, 0xde4f448e7e3c47b6}, + {0x8cb6dafda57a1b04, 0xb80b06fb012be0f6, 0x6c1f61ef626c5ee2}, + {0x9e596d56ff39dd82, 0xfd823060d81e563c, 0xfe45b0659666e7bf}, + {0x713e642578abac3b, 0x1e13b3773dddffd6, 0xf7ebe45d0b4ed62e}, + {0x0fb29b505409913a, 0xbd66ecfa5053f05e, 0x5172fa12bbd062cf}, + {0x7a8cd2f2af8db5c7, 0xf1c96d88f03f2f0c, 0xfaa8376f49a0abd5}, + {0xacc980889b25b5e7, 0x2c34843e6a6d9f3d, 0xa6bf67c68037b6ca}, + {0xaff8095311a13c10, 0x1d4a259b84ca7804, 0x3cbb9d0b61f7ff43}, + {0x5662cd5d639dfe13, 0x89c27a983290bab8, 0x92a7d11e497af642}, + {0x4157aad5c3c645ca, 0xf51297f3f77a30f2, 0x83c9dda7804ac4d8}, + {0x4e84ffef7ca3be0a, 0x14a7ba9c76da7c08, 0x5c28dc6da027d5a0}, + {0xb0964b96303be4e5, 0x4615a98b7f22a76d, 0xf222f844d2b37df9}, + {0x802540711d4f5f7d, 0xf6649bae872a32e3, 0xaed6395da047f447}, + {0x2f0953d8ce80f600, 0xdcf66d5eaf05752f, 0x209193bacdf14ef8}, + {0xc6a3ef2332ce576d, 0xb9e01c6c4572a31f, 0xde9e30f16310efde}, + {0xba02b8398971d6e6, 0xd1bab81c9c5221d6, 0x1c9c2d1f1b7f3f2b}, + {0xedc228019fbdd60a, 0x2753c3a138bcb6d7, 0x786fd2ba67707c2f}, + {0x448e2cb6c1407cbf, 0xf7b738377f0cfb97, 0x4c9212bdc0657e9c}, + {0xc76e32691429c2f9, 0x490232f4e8c043ce, 0x217833736b683230}, + {0xd1499dc75ffd2a9c, 0xd4b5f702de32b776, 0xd6dfbb898f67a374}, + {0x3b5a28d4cff86b77, 0x806f6c0571138c8b, 0x54628239f0c0f09f}, + {0xb8d45dd4a900ea0a, 0x2a9169078690c168, 0xb3657df1647fbd66}, + {0x08189a6674f4c29c, 0x8915f4636dd5d112, 0x654dc7fe07da3107}, + {0x5250e18c883794b0, 0x8828b68987cd0d9a, 0x300a18a7c772270d}, + {0x51d33040e3efaa99, 0xd658da2cb0cb97b0, 0x39038890d157c0af}, + {0x68f5a5cd07a32b53, 0x46b4f5ec1368cf94, 0xf2e0d23f40742f45}, + {0x782b44a867a3f208, 0xae64fe82046cd425, 0xb78cf45fe171d435}, + {0xde012b438c92c4d6, 0x4733810dca874273, 0x206a03d102c15302}, + {0xbea371badf5b9173, 0x8cbfaa817fd4f717, 0x34bea5affcb319d8}, + {0x1a26c2090378d01a, 0xf3d15fc5c66a7f39, 0x4de762da9a07d052}, + {0x3486c8a67bccd6cc, 0x0d10351e2b0e18ac, 0x087106b5da2aba90}, + {0xbd5c398105759654, 0x932e7ce0d2415118, 0xff7a9395dd694851}, + {0x6f6615de424f584e, 0x6ca415cbf1ff0b9a, 0x509c3763be9bb7ea}, + {0xe45a5c178e450e25, 0x48cc200c65039546, 0x2c2d872741a6e8d2}, + {0x10a487ce7b7ba1f7, 0x8da8831a4adaa217, 0xcb608d431e73d316}, + {0x480667a3a33a0923, 0x3a6fc63a03c45c96, 0xebed952f29ad80c0}, + {0x8899df2b4edff733, 0x7b68b7ea18849999, 0xcedaa43cfb6f7f7b}, + {0x356eff5782ed987f, 0xca6aab13ed43b0ce, 0x9dd8a4a5288bc18a}, + {0x5ffc38d8fbfdcdb6, 0x697d4c0b82ce34af, 0x3509dc6ecc05993b}, + {0x83905969be9090dd, 0x2125eb5bbd23d5da, 0x64224c3dfae48ffe}, + {0xf54512d0b6691741, 0x0cbaec28b636b0bc, 0xbb1d6adcda1edefc}, + {0x89ea6a9a58cddfdb, 0x845d179babdb73f7, 0xcf74a641c412cff5}, + {0x65c9f3063d3b266e, 0x560354e0ca062952, 0xc6eb9b218ae96514}, + {0x8e8c7412b3689e52, 0x99b2ec666a8a4e48, 0x5b4477de15147c03}, +}; + +static const GF aim2_e2_power_matrix[AIM2_NUM_BITS_FIELD] = +{ + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, + {0x75575b2a01927c2b, 0xe38f9eab8f685827, 0x782b0bd5192bca87}, + {0xaebbaa0e79dffe28, 0xb3542e6782b8ce84, 0x8a972b1b32323be2}, + {0x62cbd1af5c77da14, 0x3bbc6119877bbc1d, 0x8b6d73bce65ed541}, + {0x4cd2ae2762f272cc, 0xdd4adc5bfc34ae6b, 0xa3f908a96f0fe449}, + {0x60cfbdb9b6447e24, 0x721af8263082c01c, 0x68cb54e6fc7104af}, + {0xa92867af3dc3b730, 0xb2608cc06efe34d0, 0xa3445078ace873ca}, + {0xeedad86c96afe677, 0x52afb525bd42562f, 0x38cf8ddb97dc96e5}, + {0x0a3b06f10bbc9562, 0x577b7a04e02c557b, 0x8be00f5765b7e908}, + {0xaa72b3916d207e20, 0x50f0cce86025ffac, 0x09f7f935bbde0a04}, + {0xac08b4e71f96174a, 0x16babbd24d02b260, 0x48e9d357af5ba717}, + {0xe122c9c16beaa8be, 0x07043902949cfad6, 0xf78fd47b58608577}, + {0x5c473c24ac8ca469, 0xb1da898afda7d7aa, 0xcac72d2cf21a9be3}, + {0x7da00b91479d06e3, 0xc4c76d79d51eb15a, 0xb6c2e5796630269d}, + {0xb42bb35d07e100ec, 0x19964fd51c07b0af, 0xffb88b0ef80a102f}, + {0x60e6beb41a673a07, 0x75bec86a6c06b470, 0x61bb7f05fc39be82}, + {0xfda48d0189cd0c13, 0x649054858d5374c9, 0xb770a8503a32e8a4}, + {0x4a376d825f3006c4, 0x8896eb44124e97aa, 0x70e626bebfff29b5}, + {0xe37a2f298ccf89c0, 0x3c3609a866d94979, 0x356c25d15f10d784}, + {0x458ca204a347e41a, 0x59568e0a4da4e181, 0xab475a7c61d9014c}, + {0x8c1a39eb79672160, 0xb373d43893fbd9fe, 0x41ba8d6a7097e9c8}, + {0x7c01434b5f8e1448, 0x662bd055a2512d4f, 0x652c31c38e992dbc}, + {0x1eae5c36fe075219, 0x82cb682598bcb1ea, 0x60daaa526a3e9947}, + {0xf7ab17ab10f03bdf, 0x1e124b56f71a4c37, 0x75df607068cfdcff}, + {0x1ffe54ada576e3c2, 0x384cb4e86120aaa8, 0xc6a4fefc642071df}, + {0x1ae57be1013b7efb, 0x28d36534e13a369d, 0x75612cd220210f77}, + {0xa84cfbb045298f2b, 0x733fdf0216082f1f, 0x0054b363e1fcdb09}, + {0x8745e66041e62570, 0x980a16636c09d9b2, 0x51695306d0539b47}, + {0xa67319655b027ef6, 0x4fd02799c207267a, 0x01587af4a65b6fd2}, + {0x8d991698735bcc88, 0xf14dbd2b19f99a78, 0x6947a3b95199d2f4}, + {0xe2906490948e4aff, 0x16b2ee7035d98706, 0x78f47845853b1ddc}, + {0x58d9cdc2dd693cd9, 0x7e9c240b1b252019, 0x5cbd3d458a53ca24}, + {0x24101759ff01d89b, 0xed8fdd27cdb2d47b, 0x11b0fa26e8d8a743}, + {0x9da3e8ee96db2f59, 0x68285801543b4ac8, 0x618cc8ad53d51b65}, + {0xf0b448478f472d56, 0x6044053c293513d2, 0xea2fb63a575a34cb}, + {0x56bd7f9b430ca7de, 0xf883dbb4c18d2e0b, 0x6c8030ef1a38c730}, + {0xf2e2c1396125acce, 0x882e926d399fcc33, 0x87e914f3049f22ce}, + {0x7ec0b0443f81915d, 0x4573c52a818a44f3, 0xafc01f5cc8120f6b}, + {0x924aed58bfbc33f1, 0x7cbf5617448b59a8, 0xef023ef380d782bb}, + {0xed78ebbcc2543624, 0x4fbdf96f5a481d8a, 0x7dea022c85973850}, + {0x4cd0fda73b73aaf8, 0xab714c84882fc5a6, 0x31a12db8b87c1a82}, + {0x4f55b122e52b04af, 0x2b6abc206fcdea22, 0xeecc6a28e10f3cd9}, + {0x773b7f263618ea81, 0xfedd6644251162ff, 0x20f124b39fffa2ef}, + {0xc86672d34c7f9c99, 0xa1a9bedd91ba54ab, 0xe3164453cdbc1680}, + {0x976193445cc61080, 0x4e8af4d9771f7fde, 0x2d6951afbad5a152}, + {0xac8104ed45afc3e0, 0x2daa407aee0854a8, 0x93bf8a5f6332934b}, + {0xadacd0145616a90f, 0x18fcdf471f8e446e, 0xb6cb1d657c5aee1f}, + {0x39f4888a9f625046, 0x714ced776be006aa, 0x301aab64f4c07bac}, + {0xfed94c87075ec99b, 0x6527495efabe5878, 0xae4ed05b44c346fa}, + {0xe8089970ab84a9ad, 0xfa8ef420f612f142, 0x3033e1b424799c03}, + {0x3de830d471a1c303, 0x1d4648963e64b5e8, 0xb7fc69c1308d744f}, + {0xf917cc81a21178a2, 0xf51c71d20d3dde0f, 0xc755e70d903eca43}, + {0xf988b4435c7e0659, 0xe8ec12c9411e644d, 0x011cff135dc46fe5}, + {0x45eb42b4bc82e615, 0xbb1ea1d87fa2dcc8, 0xbbf258cddfcc5a4e}, + {0x76c177c889777fa3, 0x771de5ab30476eca, 0xe3dd4d0ea4da4f41}, + {0x62d43190a74afaab, 0x8c72e6cc25a0906d, 0x6560641e35c269c1}, + {0x4a473706039e3353, 0x9270c15446432105, 0x508bd6dfcce33617}, + {0x58e979ef836cb200, 0x64a108a5f68530dc, 0xeeb5a210610292b9}, + {0x3e8a485122657a2d, 0xb7f7272f3423621b, 0x4c0e2f899ffc6f0f}, + {0xb03f26ebad2101f3, 0x2bf27f00ccb827ad, 0xf2c32d1c9db42e29}, + {0xcc5f196397e2bb63, 0x9cf1f95bba0e5fb0, 0xcffa723b8add78c2}, + {0x5198cabd81774aa6, 0x79e142bd7c3981f1, 0xcfb65a6d42815d8a}, + {0x91dc7af311207622, 0xf294a4f3c38f447e, 0xdfd67624b63f7997}, + {0xfb2f51ed0b5b44c1, 0x6eeb2b229427682c, 0xfad555a3f1680200}, + {0xd043eb034f7557ae, 0x89f917e3d7f663f1, 0xd7f51e2f59ce0302}, + {0xd1738764ddee76f4, 0x28a966bea5ec647e, 0xa322c656d7bc27d1}, + {0x0cd66c8dd29514f0, 0xb4e37bf2f01130a9, 0x7db6ecdc81a7a57f}, + {0xc8cb28a44796dc78, 0x88eb0048501b3765, 0x8ff3fbd6d703c26d}, + {0x2c5d68650ca4b6f5, 0xa8e391ce83198344, 0x8b9f3219506be9d0}, + {0x911906127a1ba855, 0x30d5215961ac95e7, 0x71827dfac7504342}, + {0x1ae4c2e2506d0712, 0xb5caffb8afbcda6e, 0x159080539f7f876e}, + {0x86571676f6228cdb, 0x3a51f0bfed40380f, 0x5dec5a0cee962a54}, + {0xf5c3339c01460504, 0x5d55382d4e349ecc, 0xcf81cc12df0b2c9e}, + {0x89a775997037437a, 0xc86002223b57f27f, 0xfe795feb841f08ef}, + {0x7da8a9b3f9f43fe4, 0x8494d51c6e215f43, 0xb703f044bc338b9c}, + {0xf73c2c9d450a092f, 0xce0ae97084884a01, 0x9a647f6d5f970839}, + {0x87c63573f869cdbb, 0x812d2d8e966e6911, 0x973b425ba1c66dfa}, + {0x7de5a1e78d630e85, 0x765d7d5a4a6e3cb7, 0x28170eef2a846d99}, + {0x0b0c630c0f59460d, 0x9c8758a9ee8db258, 0xd3589f9c034f75d5}, + {0xe1a6d8e757067309, 0xd18498099be244d9, 0x9b10a894502fc4e1}, + {0xfa14fe8a1dd59c3e, 0x6a9a93b0f1ac862a, 0xdbe4d8d065053ef7}, + {0x5c94965ff0a8e28e, 0xc2a32a0d57f1faa2, 0x24dc5effe1fa9e37}, + {0x6b404bba72a24d04, 0xbcd23a38f7981241, 0x93d0c9eb1b9a39ef}, + {0xa53a198b9e74e59c, 0x17cb3bc05f9608d1, 0x21bcc23eb5e75655}, + {0x05911f7d3220397f, 0x7915054dcb628314, 0x183a2a8400570cef}, + {0x2a420bf34788186c, 0x8c83a2945ee3027b, 0x606a65c37a8f2fe3}, + {0xccf4e83131d54a27, 0xc95466a498499126, 0xef9ac8206968b1f7}, + {0xe457b2ff12256f1e, 0x57fd60a454e5f68d, 0xf3388bb1de5dd1c2}, + {0x4addb3e322595749, 0x39e02bd59d8ae504, 0x20284c1ae2f1a65c}, + {0x9fbb5574795cac4d, 0x9fedac975974c8bb, 0xd307ecf05fd4fd22}, + {0x2505bb81200f8cbb, 0x2ac9d93c45830708, 0x11ec704af2c49861}, + {0xfa1702dd351d3b22, 0xbe0dfc13d607f962, 0x82c611b8ccd1e9f2}, + {0xb7ff038d58626bd7, 0x86e990a7d6acad3b, 0x5010d30fbe2d70a9}, + {0xc42bda459ef1afca, 0x83c5891e3eff20a0, 0xdefbb485c364fd5a}, + {0xaada4d9f943df0f1, 0x2618e51a8838b5fe, 0x8f45f0ffff45201f}, + {0xb55e3891213f972c, 0xdb4f56b16dc4e905, 0x30fd462a4cf268fc}, + {0x64e007b7010e8c80, 0x2d0de3d26a1748c3, 0xa2e01ed12648c113}, + {0x5128d2b5c4bac674, 0xb80b46283a340508, 0x1c1f01fe24b17a66}, + {0x4cb8ab976733595f, 0x403aca262ff117b0, 0xce1698b4f9a54376}, + {0x7781e71d8805fdc4, 0x40c3c2110800e7a0, 0xe72e9e63999cc311}, + {0xbb3e3e6501e45c00, 0x9e70bd7de6780a3b, 0x549416aa087fe4c5}, + {0xae1da809d7eed055, 0x06ba5804e029b01c, 0x490555c99e76bd05}, + {0x67f3afbbfeee6547, 0x1243b190c38432b1, 0xbab2fa8df7bf2943}, + {0x6d7197464f15c83c, 0x9283ced1147a6a85, 0x96ba1a0e47d9dd96}, + {0x9cbb90e485218006, 0x8b5ff83a0210b4d9, 0x1086afcf143b95c2}, + {0xa07d026b378f963b, 0x2debd80b456cd3e3, 0xc7792b9bc7f54c4a}, + {0x3d0bec8b88ba06b8, 0x0c13cdfdc4d01e9f, 0x6d256d1087b9c95e}, + {0x9216a33ea47259ff, 0x2bde0cfcb54abe8d, 0xaaef421825f1b47b}, + {0xa1aabb09b181ae0f, 0xc14d44d54e3620cd, 0xabb20e2a4d637bcb}, + {0x2544eba1038d1b04, 0xda1f84aa9bc120c2, 0x41fd7f657a18c45d}, + {0xadaff973f301d8c3, 0x87dae306486ff1a6, 0x60ec280a2570b8ff}, + {0x624994b2704d4c20, 0x532232f1cf209482, 0x861b9c2a5a7d0a43}, + {0x4513aa7db58aea4d, 0x89dfbe8c94798dde, 0xe735f37739441c13}, + {0x2f534ce65fbe5d87, 0xf8fcb2432339f543, 0x8ea957572a77e395}, + {0x2456c8d764e7c1a6, 0x7dc7567c507e2e18, 0xd29b13c5db1cd65a}, + {0x885705a845bb1199, 0xebc702d7e1680421, 0x9aeba22f533cbac9}, + {0x55c435f803ad3742, 0x695442fe576b3a09, 0x5ca02fab230ee023}, + {0x0d446bb06a3cbf8b, 0x5bfc8414d84fff9a, 0x157e3384708408a8}, + {0x7b212d17c02a4054, 0x2b14562733ba6900, 0x7965f7d93122eac0}, + {0x349446294451df24, 0x2b91f57cdcc289f3, 0x829cb5a03cce767d}, + {0x2f8e7fa84f0ad401, 0xb3a50f68cba8a638, 0xde440882f84bfd7a}, + {0xd1ba1db41829f412, 0x9a2c4c23fb8538f7, 0x86ca32d92d99ecb9}, + {0x8a6db99a627b227c, 0x633c81cf8e52a687, 0x8e58542594d7103e}, + {0x4c5a928b8610d6cd, 0x6a38a81e5ec41b61, 0x05ac22b201c86322}, + {0x283c4b53c14f39c0, 0x106fe171df2218c5, 0x4c077d33f17e0107}, + {0x198b4c90bd33552f, 0x5853a4c2f74596db, 0x1018dd6bf21150d4}, + {0x47c29e1c2f495b4c, 0x7ec84995131d545b, 0x49e53beaeb94dae0}, + {0x2678b3f7b548fc9f, 0x63a6b9322f3a574c, 0xef6d85f1091f1aeb}, + {0xf1391f569cd5fe90, 0x876e8ba956de0238, 0x6cd576e3b8ab6222}, + {0x827547465967b775, 0x4197e1290368e412, 0xee63a7ef2156fb67}, + {0x6cb2a919735b34d5, 0x6cc967b756d72395, 0x9a884a65ae74e811}, + {0xbdebcb5fbfafafc0, 0xb7fc62a4c7947030, 0x554c36728822d8b6}, + {0x025fef80c960792a, 0xc0f487dcc0ad8059, 0x9714504680995ad0}, + {0x19ffb11f02502666, 0x482fc0fae8608ad2, 0x781175f6049c62ee}, + {0xf1fece4f515854e7, 0x6dab52f7b6560106, 0xfa0028f50d672954}, + {0x844afcd287c1ddba, 0x47234b529fe3ca41, 0x3ca221c08f88140a}, + {0xfdbbeaaa02badeda, 0xf35a5e21992e2332, 0xa37f6d68d919b65f}, + {0x6d218f603725748a, 0xb6df3c61103e9c3e, 0xbb7ac1cf4c1f4692}, + {0x8e6d3eb058cfc260, 0xfbe2f6497287731a, 0xffa78646830d5ce0}, + {0x8c07c328df449acd, 0x500ba217a7af529f, 0x19ab11b99a1a2a19}, + {0x42de87a6001d7bc4, 0x6d65941a9ae5138b, 0xcb830271914ce1ee}, + {0x25f950eb4e2b9669, 0x0c9f7a2279a16278, 0x86503e9de2e76202}, + {0xedc0f3a86b732556, 0xc7995c7b3ec0ea66, 0x8a4d95b8d19c29ce}, + {0x01b5ab0eca4d3189, 0xed7898b982b519ad, 0x24c5f841a769f11b}, + {0xde3eefe1bad32178, 0x493a735c30942df4, 0x8b5ec5bed8e4d565}, + {0xa974a9d616b752fa, 0x09d37b2ab193ca1c, 0x55b8aaf3af4481ba}, + {0x84ca6915121b1e09, 0x8831e83e34fac643, 0x05e3db5a89049a2f}, + {0x5375a9f4aefd0f44, 0xaf272fd031366078, 0xbbd286c07ed80632}, + {0x9d101a493aa2ebc9, 0x67e3ddfaa73b2b94, 0x45bf06b13a5d6856}, + {0x6469dfeed8b766bc, 0x41a958a8c84553fc, 0xc3665b3f060a6808}, + {0x8bbd23b38d0cff32, 0x891f48bb2592fb3f, 0x24c6243ad065453e}, + {0xf3d1cc12dcb4e302, 0x588dfaa464f518be, 0xfe082e8b4a39cf26}, + {0x95c521746547be8e, 0x9cbbea72400d1df8, 0x0cfdac076655d579}, + {0xa6c4c57375f48495, 0xd63f47b41907a3f7, 0x34e17c2df60668d7}, + {0xa135ca38c26b95c3, 0x2aac9c6b01173258, 0x2d8499bf2ed7c23c}, + {0xba02892976144352, 0x9e4d9906dc2ae94e, 0x6535b5091d0535a4}, + {0x6ec4dba2c6f7e949, 0x02d65b71f7db3f86, 0x61c796b0290e7ff0}, + {0xac044d22d442ff2e, 0x29d00d9db764b6ff, 0x9ec4ff5f21f3216d}, + {0x26b3c84573c53161, 0xa3037316e91bf8bb, 0x251ed327edf11e39}, + {0x2917804d2422970c, 0x16119362ba8934be, 0xafa94e1359c77cce}, + {0x4eac35ec04e84a0b, 0x31b309e5e5d361a5, 0x4171e00956fd334e}, + {0xa02b9fdd9f6b8162, 0xabd8bc110f4e1f52, 0x75578ed77238fedc}, + {0xe73f9ad96bd8686d, 0xbdfc49ed2dba8097, 0x054c4bb989c34404}, + {0xa0d01888aa5b1042, 0x8c33305a0dc075b1, 0x75f81fe0369e7b86}, + {0x679d711aa88faab7, 0xb03f74deaa29c24c, 0x10a7766990689f5a}, + {0x827d13e4d6310b6b, 0xc5a73641d06e47d1, 0xf2f0d06e14e2ab1f}, + {0xcc968649ec63f05e, 0x17cda3a7fc25bfb2, 0x0df1338db25ee18e}, + {0x7d4acd6c3cf8c18b, 0x4bd734fd562d48ad, 0xae50c4f72f542533}, + {0xcf438bf70dbe4c62, 0x0019bcea28ce9270, 0xf687acda7ff8c960}, + {0x5b24783c5318fd09, 0x5623189d31422de8, 0x862fd585eeb3e3f0}, + {0xf98482f8df7d5e16, 0xccb9fb2d3745fbbf, 0x7d5e1bd364daa7d4}, + {0x024849574a40a831, 0x48cae56880d67329, 0xfafa85469a93e6b3}, + {0x944eae6b760bc534, 0x1d1d18f30fec24c3, 0xc64a74b4d0c3181e}, + {0x19c52990a4e62d2d, 0x37b473c7ed759ef9, 0x04080c0ade3df738}, + {0xfcc4062c7876c075, 0x48b4cf0b72aae741, 0x3889eef0b66c1bff}, + {0x49c26471ae06da0b, 0x109da4749a70108b, 0x443b50c74915bd54}, + {0xbe68bd432e672eb8, 0xbe737af593618ab7, 0x5d537d8c0da1a4e7}, + {0xa3ca7393ce4e8d7c, 0x0fcf46d53a057c21, 0x7451a590ca6c1db1}, + {0x79419444b1c149e5, 0x9d577a1e13240b2d, 0x24da1fd0d5db6e4d}, + {0xe8c3caf37ad5170c, 0x423b4593d3f4c834, 0xff039eaad5042ae3}, + {0x3bf5913b5615f7f5, 0x2d24b840238f2c84, 0x97bdc5bfeb1d53b7}, + {0x53538b2293df4606, 0x169029e2d8675ec6, 0x9ab1ac25ee4982a4}, + {0x75bd284d07f591f8, 0xccdd36b98d68786e, 0x9321ba79d2e56eed}, + {0xe63236d17de7e69c, 0x9600d5f5cca5b08a, 0x8ff14c81e5d61843}, + {0xdb079962536683c6, 0x35bb6068eb26bd37, 0xa614c37971ca2e4d}, + {0xab78167ac83c4064, 0xb6a1928d6f89cdd1, 0xc97cc61d01ffe82f}, + {0x83e6edd7a512e8b7, 0xe281601e537bc4ec, 0x19d35d2d57518cde}, + {0xf737f3ddfa7fc9b2, 0x4a8f04a9cb4847be, 0x2946f3355994de91}, + {0x577ca3baf1f7e1ba, 0x446729b10c51ed7c, 0xab637d9c6e3a5554}, + {0x4e31798071664def, 0xec15c968e363630d, 0xd7ce5f867f758e48}, + {0x10525e76bc5a5ed9, 0x1c8a384248ab4398, 0x8f7a522f2e2f3fc5}, + {0xdee25133572d24bf, 0x37203f7f6c2e0e36, 0x89ba27d9b1233156}, +}; + +#define GF_exp_invmer_e_1 AIMER_NAMESPACE(GF_exp_invmer_e_1) +void GF_exp_invmer_e_1(GF out, const GF in); +#define GF_exp_invmer_e_2 AIMER_NAMESPACE(GF_exp_invmer_e_2) +void GF_exp_invmer_e_2(GF out, const GF in); +#define GF_exp_mer_e_star AIMER_NAMESPACE(GF_exp_mer_e_star) +void GF_exp_mer_e_star(GF out, const GF in); + +#define generate_matrices_L_and_U AIMER_NAMESPACE(generate_matrices_L_and_U) +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define generate_matrix_LU AIMER_NAMESPACE(generate_matrix_LU) +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define aim2_sbox_outputs AIMER_NAMESPACE(aim2_sbox_outputs) +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt); + +#define aim2 AIMER_NAMESPACE(aim2) +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]); + +#endif // AIM2_H diff --git a/crypto_sign/aimer192f/m4speed/api.h b/crypto_sign/aimer192f/m4speed/api.h new file mode 100644 index 00000000..dba6ebd7 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 48 +#define CRYPTO_SECRETKEYBYTES 72 +#define CRYPTO_BYTES 13056 +#define CRYPTO_ALGNAME "aimer192f" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer192f/m4speed/field.c b/crypto_sign/aimer192f/m4speed/field.c new file mode 100644 index 00000000..91ee3d55 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/field.c @@ -0,0 +1,482 @@ +// SPDX-License-Identifier: MIT + +#include "field.h" +#include +#include + +#define mask_64 0x00000000ffffffff +#define mask_final 0x000000000000ffff + +#define mask0_64 0x000000ff000000ff +#define mask0 0x000000ff + +#define mask1_64 0x000f000f000f000f +#define mask1 0x000f000f + +#define mask2_64 0x0303030303030303 +#define mask2 0x03030303 + +#define mask3_64 0x1111111111111111 +#define mask3 0x11111111 + +#define zero_padding(x0, mask1, mask2, mask3) \ + x0 = (x0 | (x0 << 12)) & mask1; \ + x0 = (x0 | (x0 << 6 )) & mask2; \ + x0 = (x0 | (x0 << 3 )) & mask3; + +#define inv_zero_padding(x0, mask0, mask1, mask2, mask_final) \ + x0 = (x0 | (x0 >> 3 )) & mask2; \ + x0 = (x0 | (x0 >> 6 )) & mask1; \ + x0 = (x0 | (x0 >> 12)) & mask0; \ + x0 = (x0 | (x0 >> 24)) & mask_final; + +void GF_mul(GF c, const GF a, const GF b) +{ + uint64_t t[3] = {0,}; + uint64_t temp[6] = {0,}; + uint64_t sub[6] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + sub[2] = a[0] ^ a[2]; + sub[3] = b[0] ^ b[2]; + sub[4] = a[1] ^ a[2]; + sub[5] = b[1] ^ b[2]; + + poly64_mul(&a[0], &b[0], &t[0], &temp[0]); + poly64_mul(&a[1], &b[1], &t[2], &t[1]); + t[0] ^= t[1]; + + poly64_mul(&a[2], &b[2], &temp[5], &t[1]); + t[1] ^= t[2]; + + temp[1] = t[0] ^ temp[0]; + temp[2] = t[1] ^ temp[1]; + temp[4] = temp[5] ^ t[1]; + temp[3] = temp[4] ^ t[0]; + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul(&sub[2], &sub[3], &t[1], &t[0]); + temp[2] ^= t[0]; + temp[3] ^= t[1]; + + poly64_mul(&sub[4], &sub[5], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[3] ^ ((temp[5] >> 57) ^ (temp[5] >> 62) ^ (temp[5] >> 63)); + + c[2] = temp[2] ^ temp[5]; + c[2] ^= (temp[5] << 7) | (temp[4] >> 57); + c[2] ^= (temp[5] << 2) | (temp[4] >> 62); + c[2] ^= (temp[5] << 1) | (temp[4] >> 63); + + c[1] = temp[1] ^ temp[4]; + c[1] ^= (temp[4] << 7) | (t[0] >> 57); + c[1] ^= (temp[4] << 2) | (t[0] >> 62); + c[1] ^= (temp[4] << 1) | (t[0] >> 63); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_mul_add(GF c, const GF a, const GF b) +{ + uint64_t t[3] = {0,}; + uint64_t temp[6] = {0,}; + uint64_t sub[6] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + sub[2] = a[0] ^ a[2]; + sub[3] = b[0] ^ b[2]; + sub[4] = a[1] ^ a[2]; + sub[5] = b[1] ^ b[2]; + + poly64_mul(&a[0], &b[0], &t[0], &temp[0]); + poly64_mul(&a[1], &b[1], &t[2], &t[1]); + t[0] ^= t[1]; + + poly64_mul(&a[2], &b[2], &temp[5], &t[1]); + t[1] ^= t[2]; + + temp[1] = t[0] ^ temp[0]; + temp[2] = t[1] ^ temp[1]; + temp[4] = temp[5] ^ t[1]; + temp[3] = temp[4] ^ t[0]; + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul(&sub[2], &sub[3], &t[1], &t[0]); + temp[2] ^= t[0]; + temp[3] ^= t[1]; + + poly64_mul(&sub[4], &sub[5], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[3] ^ ((temp[5] >> 57) ^ (temp[5] >> 62) ^ (temp[5] >> 63)); + + c[2] ^= temp[2] ^ temp[5]; + c[2] ^= (temp[5] << 7) | (temp[4] >> 57); + c[2] ^= (temp[5] << 2) | (temp[4] >> 62); + c[2] ^= (temp[5] << 1) | (temp[4] >> 63); + + c[1] ^= temp[1] ^ temp[4]; + c[1] ^= (temp[4] << 7) | (t[0] >> 57); + c[1] ^= (temp[4] << 2) | (t[0] >> 62); + c[1] ^= (temp[4] << 1) | (t[0] >> 63); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t temp_c2 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 4, index >>= 4, b_ptr += 4) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + temp_c2 ^= (b_ptr[0][2] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + temp_c2 ^= (b_ptr[1][2] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + temp_c2 ^= (b_ptr[2][2] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + temp_c2 ^= (b_ptr[3][2] & mask); + } + } + c[0] = temp_c0; + c[1] = temp_c1; + c[2] = temp_c2; +} + +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t temp_c2 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 4, index >>= 4, b_ptr += 4) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + temp_c2 ^= (b_ptr[0][2] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + temp_c2 ^= (b_ptr[1][2] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + temp_c2 ^= (b_ptr[2][2] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + temp_c2 ^= (b_ptr[3][2] & mask); + } + } + c[0] ^= temp_c0; + c[1] ^= temp_c1; + c[2] ^= temp_c2; +} + +static void poly64_mul_s(uint64_t *z1, uint64_t *z0, uint64_t x, uint64_t y) +{ + // x_low + uint32_t x4 = x >> 32; + + uint32_t x0 = x & mask_64; + uint32_t x1 = (x0 >> 8) & mask0; + uint32_t x2 = (x0 >> 16) & mask0; + uint32_t x3 = (x0 >> 24) & mask0; + x0 &= mask0; + + // x_high + uint32_t x5 = (x4 >> 8) & mask0; + uint32_t x6 = (x4 >> 16) & mask0; + uint32_t x7 = (x4 >> 24) & mask0; + x4 &= mask0; + + // y_low + uint32_t y4 = y >> 32; + + uint32_t y0 = y & mask_64; + uint32_t y1 = (y0 >> 8) & mask0; + uint32_t y2 = (y0 >> 16) & mask0; + uint32_t y3 = (y0 >> 24) & mask0; + y0 &= mask0; + + // y_high + uint32_t y5 = (y4 >> 8) & mask0; + uint32_t y6 = (y4 >> 16) & mask0; + uint32_t y7 = (y4 >> 24) & mask0; + y4 &= mask0; + + // x padding + zero_padding(x0, mask1, mask2, mask3); + zero_padding(x1, mask1, mask2, mask3); + zero_padding(x2, mask1, mask2, mask3); + zero_padding(x3, mask1, mask2, mask3); + zero_padding(x4, mask1, mask2, mask3); + zero_padding(x5, mask1, mask2, mask3); + zero_padding(x6, mask1, mask2, mask3); + zero_padding(x7, mask1, mask2, mask3); + + // y padding + zero_padding(y0, mask1, mask2, mask3); + zero_padding(y1, mask1, mask2, mask3); + zero_padding(y2, mask1, mask2, mask3); + zero_padding(y3, mask1, mask2, mask3); + zero_padding(y4, mask1, mask2, mask3); + zero_padding(y5, mask1, mask2, mask3); + zero_padding(y6, mask1, mask2, mask3); + zero_padding(y7, mask1, mask2, mask3); + + //x0-3 * y0-3 + uint64_t a0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t a1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + a0 ^= (a1 << 32); + a1 = a1 >> 32; + a1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t a2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + a1 ^= (a2 << 32); + a2 = a2 >> 32; + a2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t a3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + a2 ^= (a3 << 32); + a3 = a3 >> 32; + + a3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + //x4-7 * y4-7 + uint64_t b0 = ((uint64_t)x4 * (uint64_t)y4) & mask3_64; + uint64_t b1 = ((((uint64_t)x4 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y4) & mask3_64)); + b0 ^= (b1 << 32); + b1 = b1 >> 32; + b1 ^= ((((uint64_t)x4 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y4) & mask3_64)); + + uint64_t b2 = ((((uint64_t)x4 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y4) & mask3_64)); + b1 ^= (b2 << 32); + b2 = b2 >> 32; + b2 ^= ((((uint64_t)x5 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y5) & mask3_64)); + + uint64_t b3 = ((((uint64_t)x6 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y6) & mask3_64)); + b2 ^= (b3 << 32); + b3 = b3 >> 32; + + b3 ^= ((uint64_t)x7 * (uint64_t)y7) & mask3_64; + + //middle part + x0 ^= x4; + x1 ^= x5; + x2 ^= x6; + x3 ^= x7; + + y0 ^= y4; + y1 ^= y5; + y2 ^= y6; + y3 ^= y7; + + uint64_t c0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t c1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + c0 ^= (c1 << 32); + c1 = c1 >> 32; + c1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t c2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + c1 ^= (c2 << 32); + c2 = c2 >> 32; + c2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t c3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + c2 ^= (c3 << 32); + c3 = c3 >> 32; + + c3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + c0 = c0 ^ a0 ^ b0; + c1 = c1 ^ a1 ^ b1; + c2 = c2 ^ a2 ^ b2; + c3 = c3 ^ a3 ^ b3; + + a2 ^= c0; + a3 ^= c1; + b0 ^= c2; + b1 ^= c3; + + // result inv_padding + inv_zero_padding(a0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a3, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b3, mask0_64, mask1_64, mask2_64, mask_final); + + *z0 = a0 | (a1 << 16) | (a2 << 32) | (a3 << 48); + *z1 = b0 | (b1 << 16) | (b2 << 32) | (b3 << 48); +} + +void GF_mul_s(GF c, const GF a, const GF b) +{ + uint64_t t[3] = {0,}; + uint64_t temp[6] = {0,}; + + poly64_mul_s(&t[0], &temp[0], a[0], b[0]); + poly64_mul_s(&t[2], &t[1], a[1], b[1]); + t[0] ^= t[1]; + + poly64_mul_s(&temp[5], &t[1], a[2], b[2]); + t[1] ^= t[2]; + + temp[1] = t[0] ^ temp[0]; + temp[2] = t[1] ^ temp[1]; + temp[4] = temp[5] ^ t[1]; + temp[3] = temp[4] ^ t[0]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[2]), (b[0] ^ b[2])); + temp[2] ^= t[0]; + temp[3] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[1] ^ a[2]), (b[1] ^ b[2])); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[3] ^ ((temp[5] >> 57) ^ (temp[5] >> 62) ^ (temp[5] >> 63)); + + c[2] = temp[2] ^ temp[5]; + c[2] ^= (temp[5] << 7) | (temp[4] >> 57); + c[2] ^= (temp[5] << 2) | (temp[4] >> 62); + c[2] ^= (temp[5] << 1) | (temp[4] >> 63); + + c[1] = temp[1] ^ temp[4]; + c[1] ^= (temp[4] << 7) | (t[0] >> 57); + c[1] ^= (temp[4] << 2) | (t[0] >> 62); + c[1] ^= (temp[4] << 1) | (t[0] >> 63); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} + +void GF_mul_add_s(GF c, const GF a, const GF b) +{ + uint64_t t[3] = {0,}; + uint64_t temp[6] = {0,}; + + poly64_mul_s(&t[0], &temp[0], a[0], b[0]); + poly64_mul_s(&t[2], &t[1], a[1], b[1]); + t[0] ^= t[1]; + + poly64_mul_s(&temp[5], &t[1], a[2], b[2]); + t[1] ^= t[2]; + + temp[1] = t[0] ^ temp[0]; + temp[2] = t[1] ^ temp[1]; + temp[4] = temp[5] ^ t[1]; + temp[3] = temp[4] ^ t[0]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[2]), (b[0] ^ b[2])); + temp[2] ^= t[0]; + temp[3] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[1] ^ a[2]), (b[1] ^ b[2])); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[3] ^ ((temp[5] >> 57) ^ (temp[5] >> 62) ^ (temp[5] >> 63)); + + c[2] ^= temp[2] ^ temp[5]; + c[2] ^= (temp[5] << 7) | (temp[4] >> 57); + c[2] ^= (temp[5] << 2) | (temp[4] >> 62); + c[2] ^= (temp[5] << 1) | (temp[4] >> 63); + + c[1] ^= temp[1] ^ temp[4]; + c[1] ^= (temp[4] << 7) | (t[0] >> 57); + c[1] ^= (temp[4] << 2) | (t[0] >> 62); + c[1] ^= (temp[4] << 1) | (t[0] >> 63); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 7); + c[0] ^= (t[0] << 2); + c[0] ^= (t[0] << 1); +} diff --git a/crypto_sign/aimer192f/m4speed/field.h b/crypto_sign/aimer192f/m4speed/field.h new file mode 100644 index 00000000..5182adc4 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/field.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +#ifndef FIELD_H +#define FIELD_H + +#include "params.h" +#include +#include + +typedef uint64_t GF[3]; + +#define poly64_mul AIMER_NAMESPACE(poly64_mul) +void poly64_mul(const uint64_t *a, const uint64_t *b, uint64_t *c1, uint64_t *c0); +#define GF_set0 AIMER_NAMESPACE(GF_set0) +void GF_set0(GF a); +#define GF_copy AIMER_NAMESPACE(GF_copy) +void GF_copy(GF out, const GF in); +#define GF_to_bytes AIMER_NAMESPACE(GF_to_bytes) +void GF_to_bytes(uint8_t *out, const GF in); +#define GF_from_bytes AIMER_NAMESPACE(GF_from_bytes) +void GF_from_bytes(GF out, const uint8_t *in); + +#define GF_add AIMER_NAMESPACE(GF_add) +void GF_add(GF c, const GF a, const GF b); +#define GF_mul AIMER_NAMESPACE(GF_mul) +void GF_mul(GF c, const GF a, const GF b); +#define GF_mul_add AIMER_NAMESPACE(GF_mul_add) +void GF_mul_add(GF c, const GF a, const GF b); +#define GF_transposed_matmul AIMER_NAMESPACE(GF_transposed_matmul) +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); +#define GF_transposed_matmul_add AIMER_NAMESPACE(GF_transposed_matmul_add) +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); + +#define GF_mul_s AIMER_NAMESPACE(GF_mul_s) +void GF_mul_s(GF c, const GF a, const GF b); +#define GF_mul_add_s AIMER_NAMESPACE(GF_mul_add_s) +void GF_mul_add_s(GF c, const GF a, const GF b); +#define GF_sqr_s AIMER_NAMESPACE(GF_sqr_s) +void GF_sqr_s(GF c, const GF a); + +#endif // FIELD_H diff --git a/crypto_sign/aimer192f/m4speed/hash.c b/crypto_sign/aimer192f/m4speed/hash.c new file mode 100644 index 00000000..06a6f473 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/hash.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +#include "hash.h" +#include +#include + +void hash_init(hash_instance *ctx) +{ + shake256_inc_init(ctx); +} + +void hash_init_prefix(hash_instance *ctx, uint8_t prefix) +{ + shake256_inc_init(ctx); + shake256_inc_absorb(ctx, &prefix, sizeof(prefix)); +} + +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len) +{ + shake256_inc_absorb(ctx, data, data_len); +} + +void hash_final(hash_instance *ctx) +{ + shake256_inc_finalize(ctx); +} + +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len) +{ + shake256_inc_squeeze(buffer, buffer_len, ctx); +} + +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src) +{ + shake256_inc_ctx_clone(ctx_dest, ctx_src); +} + +void hash_ctx_release(hash_instance *ctx) +{ + shake256_inc_ctx_release(ctx); +} diff --git a/crypto_sign/aimer192f/m4speed/hash.h b/crypto_sign/aimer192f/m4speed/hash.h new file mode 100644 index 00000000..0fb7c8ef --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/hash.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +#ifndef HASH_H +#define HASH_H + +#include "fips202.h" +#include "params.h" +#include +#include + +static const uint8_t HASH_PREFIX_0 = 0; +static const uint8_t HASH_PREFIX_1 = 1; +static const uint8_t HASH_PREFIX_2 = 2; +static const uint8_t HASH_PREFIX_3 = 3; +static const uint8_t HASH_PREFIX_4 = 4; +static const uint8_t HASH_PREFIX_5 = 5; + +typedef shake256incctx hash_instance; + +#define hash_init AIMER_NAMESPACE(hash_init) +void hash_init(hash_instance *ctx); +#define hash_init_prefix AIMER_NAMESPACE(hash_init_prefix) +void hash_init_prefix(hash_instance *ctx, uint8_t prefix); +#define hash_update AIMER_NAMESPACE(hash_update) +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len); +#define hash_final AIMER_NAMESPACE(hash_final) +void hash_final(hash_instance *ctx); +#define hash_squeeze AIMER_NAMESPACE(hash_squeeze) +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len); +#define hash_ctx_clone AIMER_NAMESPACE(hash_ctx_clone) +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src); +#define hash_ctx_release AIMER_NAMESPACE(hash_ctx_release) +void hash_ctx_release(hash_instance *ctx); + +#endif // HASH_H diff --git a/crypto_sign/aimer192f/m4speed/params.h b/crypto_sign/aimer192f/m4speed/params.h new file mode 100644 index 00000000..2415b973 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer192f_m4speed_##s + +#define SECURITY_BITS 192 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 49 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer192f/m4speed/sign.c b/crypto_sign/aimer192f/m4speed/sign.c new file mode 100644 index 00000000..98688f9c --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/sign.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE], + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + mult_chk_t mult_chk[AIMER_T][AIMER_N], + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const uint8_t *sk, const uint8_t *m, size_t mlen) +{ + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt + hash_init_prefix(&ctx, HASH_PREFIX_3); + hash_update(&ctx, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, random, SECURITY_BYTES); + hash_final(&ctx); + hash_squeeze(&ctx, sign->salt, AIMER_SALT_SIZE); + + // generate root seeds and expand seed trees + for (size_t rep = 0; rep < AIMER_T; rep++) + { + hash_squeeze(&ctx, nodes[rep][0], AIMER_SEED_SIZE); + } + expand_trees(nodes, sign->salt); + hash_ctx_release(&ctx); + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // initialize adjustment values + tape_t delta, tape; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + commit_and_expand_tape(&tape, commits[rep][party], &ctx_precom, + nodes[rep][party + AIMER_N - 1], rep, party); + hash_update(&ctx, commits[rep][party], AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + GF_set0(mult_chk[rep][party].x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk[rep][party].x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk[rep][party].pt_share, tape.pt_share); + GF_copy(mult_chk[rep][party].x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk[rep][party].x_shares[1], tape.t_shares[1]); + GF_copy(alpha_v_shares[rep][0][party], tape.a_share); + GF_copy(alpha_v_shares[rep][1][party], tape.c_share); + + aim2_mpc(&mult_chk[rep][party], + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_2_and_3(signature_t *sign, + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const mult_chk_t mult_chk[AIMER_T][AIMER_N]) +{ + GF epsilons[AIMER_L + 1]; + + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + GF_set0(alpha); + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // alpha_share = a_share + sum x_share[i] * eps[i] + // v_share = c_share - pt_share * alpha + sum z_share[i] * eps[i] + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[rep][0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].pt_share, alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares[rep], + AIM2_NUM_BYTES_FIELD * 2 * AIMER_N); + } + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + hash_ctx_release(&ctx_e); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + hash_instance ctx; + signature_t *sign = (signature_t *)sig; + + ////////////////////////////////////////////////////////////////////////// + // Phase 1: Committing to the seeds and the execution views of parties. // + ////////////////////////////////////////////////////////////////////////// + + // nodes for seed trees + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + // commitments for seeds + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE]; + + // multiplication check inputs + mult_chk_t mult_chk[AIMER_T][AIMER_N]; + + // multiplication check outputs + GF alpha_v_shares[AIMER_T][2][AIMER_N]; + + // commitments for phase 1 + run_phase_1(sign, commits, nodes, mult_chk, alpha_v_shares, sk, m, mlen); + + ///////////////////////////////////////////////////////////////// + // Phase 2, 3: Challenging and committing to the simulation of // + // the multiplication checking protocol. // + ///////////////////////////////////////////////////////////////// + + // compute the commitment of phase 3 + run_phase_2_and_3(sign, alpha_v_shares, + (const mult_chk_t (*)[AIMER_N])mult_chk); + + ////////////////////////////////////////////////////// + // Phase 4: Challenging views of the MPC protocols. // + ////////////////////////////////////////////////////// + + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + ////////////////////////////////////////////////////// + // Phase 5: Opening the views of the MPC protocols. // + ////////////////////////////////////////////////////// + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes[rep], i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits[rep][i_bar], + AIMER_COMMIT_SIZE); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, + alpha_v_shares[rep][0][i_bar]); + } + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer192f/m4speed/sign.h b/crypto_sign/aimer192f/m4speed/sign.h new file mode 120000 index 00000000..0cab7ef0 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4speed/tree.c b/crypto_sign/aimer192f/m4speed/tree.c new file mode 120000 index 00000000..0b937a00 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4speed/tree.h b/crypto_sign/aimer192f/m4speed/tree.h new file mode 120000 index 00000000..9ccb9413 --- /dev/null +++ b/crypto_sign/aimer192f/m4speed/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/__asm_field.S b/crypto_sign/aimer192f/m4stack/__asm_field.S new file mode 120000 index 00000000..2c62a39d --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer192f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/aim2.c b/crypto_sign/aimer192f/m4stack/aim2.c new file mode 120000 index 00000000..92590ea9 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/aim2.h b/crypto_sign/aimer192f/m4stack/aim2.h new file mode 120000 index 00000000..c1887817 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/api.h b/crypto_sign/aimer192f/m4stack/api.h new file mode 120000 index 00000000..8d810e6a --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/api.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/field.c b/crypto_sign/aimer192f/m4stack/field.c new file mode 120000 index 00000000..b37ead06 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/field.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/field.h b/crypto_sign/aimer192f/m4stack/field.h new file mode 120000 index 00000000..d54ecff5 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/field.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/hash.c b/crypto_sign/aimer192f/m4stack/hash.c new file mode 120000 index 00000000..e3d8e7dd --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/hash.h b/crypto_sign/aimer192f/m4stack/hash.h new file mode 120000 index 00000000..0e0c3961 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/params.h b/crypto_sign/aimer192f/m4stack/params.h new file mode 100644 index 00000000..d7e67589 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer192f_m4stack_##s + +#define SECURITY_BITS 192 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 49 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer192f/m4stack/sign.c b/crypto_sign/aimer192f/m4stack/sign.c new file mode 100644 index 00000000..905b10f8 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/sign.c @@ -0,0 +1,628 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer192f/m4stack/sign.h b/crypto_sign/aimer192f/m4stack/sign.h new file mode 120000 index 00000000..c46aabad --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/tree.c b/crypto_sign/aimer192f/m4stack/tree.c new file mode 120000 index 00000000..09dffdf6 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer192f/m4stack/tree.h b/crypto_sign/aimer192f/m4stack/tree.h new file mode 120000 index 00000000..53fc8d73 --- /dev/null +++ b/crypto_sign/aimer192f/m4stack/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/__asm_field.S b/crypto_sign/aimer192s/m4speed/__asm_field.S new file mode 120000 index 00000000..2c62a39d --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/__asm_field.S @@ -0,0 +1 @@ +../../aimer192f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/aim2.c b/crypto_sign/aimer192s/m4speed/aim2.c new file mode 120000 index 00000000..92590ea9 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/aim2.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/aim2.h b/crypto_sign/aimer192s/m4speed/aim2.h new file mode 120000 index 00000000..c1887817 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/aim2.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/api.h b/crypto_sign/aimer192s/m4speed/api.h new file mode 100644 index 00000000..c4b90d12 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 48 +#define CRYPTO_SECRETKEYBYTES 72 +#define CRYPTO_BYTES 9120 +#define CRYPTO_ALGNAME "aimer192s" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer192s/m4speed/field.c b/crypto_sign/aimer192s/m4speed/field.c new file mode 120000 index 00000000..b37ead06 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/field.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/field.h b/crypto_sign/aimer192s/m4speed/field.h new file mode 120000 index 00000000..d54ecff5 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/field.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/hash.c b/crypto_sign/aimer192s/m4speed/hash.c new file mode 100644 index 00000000..005b51d1 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/hash.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +#include "hash.h" +#include "keccakf1600.h" +#include +#include + +static void shake256_inc_skip_squeeze(shake256incctx *state, size_t outlen) +{ + size_t i; + + for (i = 0; i < outlen && i < state->ctx[25]; i++) + { + continue; + } + outlen -= i; + state->ctx[25] -= i; + + while (outlen > 0) + { + KeccakF1600_StatePermute(state->ctx); + + for (i = 0; i < outlen && i < SHAKE256_RATE; i++) + { + continue; + } + outlen -= i; + state->ctx[25] = SHAKE256_RATE - i; + } +} + +void hash_init(hash_instance *ctx) +{ + shake256_inc_init(ctx); +} + +void hash_init_prefix(hash_instance *ctx, uint8_t prefix) +{ + shake256_inc_init(ctx); + shake256_inc_absorb(ctx, &prefix, sizeof(prefix)); +} + +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len) +{ + shake256_inc_absorb(ctx, data, data_len); +} + +void hash_final(hash_instance *ctx) +{ + shake256_inc_finalize(ctx); +} + +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len) +{ + shake256_inc_squeeze(buffer, buffer_len, ctx); +} + +void hash_skip_squeeze(hash_instance *ctx, size_t buffer_len) +{ + shake256_inc_skip_squeeze(ctx, buffer_len); +} + +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src) +{ + shake256_inc_ctx_clone(ctx_dest, ctx_src); +} + +void hash_ctx_release(hash_instance *ctx) +{ + shake256_inc_ctx_release(ctx); +} diff --git a/crypto_sign/aimer192s/m4speed/hash.h b/crypto_sign/aimer192s/m4speed/hash.h new file mode 100644 index 00000000..8f3450ea --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/hash.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT + +#ifndef HASH_H +#define HASH_H + +#include "fips202.h" +#include "params.h" +#include +#include + +static const uint8_t HASH_PREFIX_0 = 0; +static const uint8_t HASH_PREFIX_1 = 1; +static const uint8_t HASH_PREFIX_2 = 2; +static const uint8_t HASH_PREFIX_3 = 3; +static const uint8_t HASH_PREFIX_4 = 4; +static const uint8_t HASH_PREFIX_5 = 5; + +typedef shake256incctx hash_instance; + +#define hash_init AIMER_NAMESPACE(hash_init) +void hash_init(hash_instance *ctx); +#define hash_init_prefix AIMER_NAMESPACE(hash_init_prefix) +void hash_init_prefix(hash_instance *ctx, uint8_t prefix); +#define hash_update AIMER_NAMESPACE(hash_update) +void hash_update(hash_instance *ctx, const uint8_t *data, size_t data_len); +#define hash_final AIMER_NAMESPACE(hash_final) +void hash_final(hash_instance *ctx); +#define hash_squeeze AIMER_NAMESPACE(hash_squeeze) +void hash_squeeze(hash_instance *ctx, uint8_t *buffer, size_t buffer_len); +#define hash_skip_squeeze AIMER_NAMESPACE(hash_skip_squeeze) +void hash_skip_squeeze(hash_instance *ctx, size_t buffer_len); +#define hash_ctx_clone AIMER_NAMESPACE(hash_ctx_clone) +void hash_ctx_clone(hash_instance *ctx_dest, const hash_instance *ctx_src); +#define hash_ctx_release AIMER_NAMESPACE(hash_ctx_release) +void hash_ctx_release(hash_instance *ctx); + +#endif // HASH_H diff --git a/crypto_sign/aimer192s/m4speed/params.h b/crypto_sign/aimer192s/m4speed/params.h new file mode 100644 index 00000000..209888d7 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/params.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer192s_m4speed_##s + +#define SECURITY_BITS 192 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 25 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#define PRE_TREE_IDX 256 + +#endif // PARAMS_H diff --git a/crypto_sign/aimer192s/m4speed/sign.c b/crypto_sign/aimer192s/m4speed/sign.c new file mode 100644 index 00000000..6a16e2e0 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/sign.c @@ -0,0 +1,664 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void commit_and_expand_tape_phase_3(tape_t *tape, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_skip_squeeze(&ctx, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape_phase_3(&tape, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE] = {0,}; + + hash_instance ctx_tree; + hash_init_prefix(&ctx_tree, HASH_PREFIX_4); + hash_update(&ctx_tree, sign->salt, AIMER_SALT_SIZE); + + pre_expand_trees(pre_nodes, &ctx_tree, root_seeds); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_3(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_5(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + + hash_ctx_release(&ctx_tree); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature( + sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, + size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify( + signature, CRYPTO_BYTES, + message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer192s/m4speed/sign.h b/crypto_sign/aimer192s/m4speed/sign.h new file mode 120000 index 00000000..ad443300 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/sign.h @@ -0,0 +1 @@ +../../aimer128s/m4speed/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/tree.c b/crypto_sign/aimer192s/m4speed/tree.c new file mode 120000 index 00000000..b086c3b3 --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/tree.c @@ -0,0 +1 @@ +../../aimer128s/m4speed/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4speed/tree.h b/crypto_sign/aimer192s/m4speed/tree.h new file mode 120000 index 00000000..f3e5d95b --- /dev/null +++ b/crypto_sign/aimer192s/m4speed/tree.h @@ -0,0 +1 @@ +../../aimer128s/m4speed/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/__asm_field.S b/crypto_sign/aimer192s/m4stack/__asm_field.S new file mode 120000 index 00000000..2c62a39d --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer192f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/aim2.c b/crypto_sign/aimer192s/m4stack/aim2.c new file mode 120000 index 00000000..92590ea9 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/aim2.h b/crypto_sign/aimer192s/m4stack/aim2.h new file mode 120000 index 00000000..c1887817 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/api.h b/crypto_sign/aimer192s/m4stack/api.h new file mode 120000 index 00000000..1545b692 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/api.h @@ -0,0 +1 @@ +../../aimer192s/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/field.c b/crypto_sign/aimer192s/m4stack/field.c new file mode 120000 index 00000000..b37ead06 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/field.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/field.h b/crypto_sign/aimer192s/m4stack/field.h new file mode 120000 index 00000000..d54ecff5 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/field.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/hash.c b/crypto_sign/aimer192s/m4stack/hash.c new file mode 120000 index 00000000..e3d8e7dd --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/hash.h b/crypto_sign/aimer192s/m4stack/hash.h new file mode 120000 index 00000000..0e0c3961 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/params.h b/crypto_sign/aimer192s/m4stack/params.h new file mode 100644 index 00000000..2afef61c --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer192s_m4stack_##s + +#define SECURITY_BITS 192 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 2 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 25 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer192s/m4stack/sign.c b/crypto_sign/aimer192s/m4stack/sign.c new file mode 100644 index 00000000..905b10f8 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/sign.c @@ -0,0 +1,628 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_mul(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], + aim2_e1_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer192s/m4stack/sign.h b/crypto_sign/aimer192s/m4stack/sign.h new file mode 120000 index 00000000..c46aabad --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/tree.c b/crypto_sign/aimer192s/m4stack/tree.c new file mode 120000 index 00000000..09dffdf6 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer192s/m4stack/tree.h b/crypto_sign/aimer192s/m4stack/tree.h new file mode 120000 index 00000000..53fc8d73 --- /dev/null +++ b/crypto_sign/aimer192s/m4stack/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4speed/__asm_field.S b/crypto_sign/aimer256f/m4speed/__asm_field.S new file mode 100644 index 00000000..6181c602 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/__asm_field.S @@ -0,0 +1,695 @@ +#include "params.h" + +.syntax unified +.cpu cortex-m4 +.thumb + +.text + +.align 2 +.global AIMER_NAMESPACE(GF_to_bytes) +.global AIMER_NAMESPACE(GF_from_bytes) +.global AIMER_NAMESPACE(GF_copy) +.type AIMER_NAMESPACE(GF_to_bytes), %function +.type AIMER_NAMESPACE(GF_from_bytes), %function +.type AIMER_NAMESPACE(GF_copy), %function +AIMER_NAMESPACE(GF_to_bytes): +AIMER_NAMESPACE(GF_from_bytes): +AIMER_NAMESPACE(GF_copy): + out_p .req R0 + in_p .req R1 + + .equ width, 4 + + ldr.w R2, [in_p, #0 * width] + ldr.w R3, [in_p, #1 * width] + str.w R2, [out_p, #0 * width] + str.w R3, [out_p, #1 * width] + + ldr.w R2, [in_p, #2 * width] + ldr.w R3, [in_p, #3 * width] + str.w R2, [out_p, #2 * width] + str.w R3, [out_p, #3 * width] + + ldr.w R2, [in_p, #4 * width] + ldr.w R3, [in_p, #5 * width] + str.w R2, [out_p, #4 * width] + str.w R3, [out_p, #5 * width] + + ldr.w R2, [in_p, #6 * width] + ldr.w R3, [in_p, #7 * width] + str.w R2, [out_p, #6 * width] + str.w R3, [out_p, #7 * width] + + bx lr + + .unreq in_p + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_set0) +.type AIMER_NAMESPACE(GF_set0), %function +AIMER_NAMESPACE(GF_set0): + out_p .req R0 + + .equ width, 4 + + mov.w R2, #0 + str.w R2, [out_p, #0 * width] + str.w R2, [out_p, #1 * width] + str.w R2, [out_p, #2 * width] + str.w R2, [out_p, #3 * width] + str.w R2, [out_p, #4 * width] + str.w R2, [out_p, #5 * width] + str.w R2, [out_p, #6 * width] + str.w R2, [out_p, #7 * width] + + bx lr + + .unreq out_p + +.align 2 +.global AIMER_NAMESPACE(GF_add) +.type AIMER_NAMESPACE(GF_add), %function +AIMER_NAMESPACE(GF_add): + out_p .req R0 + in0_p .req R1 + in1_p .req R2 + + .equ width, 4 + + ldr.w R3, [in0_p, #0 * width] + ldr.w R12, [in1_p, #0 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #0 * width] + + ldr.w R3, [in0_p, #1 * width] + ldr.w R12, [in1_p, #1 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #1 * width] + + ldr.w R3, [in0_p, #2 * width] + ldr.w R12, [in1_p, #2 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #2 * width] + + ldr.w R3, [in0_p, #3 * width] + ldr.w R12, [in1_p, #3 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #3 * width] + + ldr.w R3, [in0_p, #4 * width] + ldr.w R12, [in1_p, #4 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #4 * width] + + ldr.w R3, [in0_p, #5 * width] + ldr.w R12, [in1_p, #5 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #5 * width] + + ldr.w R3, [in0_p, #6 * width] + ldr.w R12, [in1_p, #6 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #6 * width] + + ldr.w R3, [in0_p, #7 * width] + ldr.w R12, [in1_p, #7 * width] + eor.w R3, R3, R12 + str.w R3, [out_p, #7 * width] + + bx lr + + .unreq out_p + .unreq in0_p + .unreq in1_p + +.macro or_shift_and in_a, con_a, off_a + orr.w \in_a, \in_a, \in_a, lsl #\off_a + and.w \in_a, \in_a, \con_a +.endm + +.align 2 +.global AIMER_NAMESPACE(GF_sqr_s) +.type AIMER_NAMESPACE(GF_sqr_s), %function +AIMER_NAMESPACE(GF_sqr_s): + out_p .req R0 + in_p .req R1 + + in0 .req R2 + in1 .req R3 + in2 .req R4 + in3 .req R5 + in4 .req R6 + in5 .req R7 + in6 .req R8 + in7 .req R9 + in8 .req R10 + in9 .req R11 + + .equ C0, 1431655765 // 0x55555555 + .equ C1, 858993459 // 0x33333333 + .equ C2, 252645135 // 0x0F0F0F0F + .equ C3, 16711935 // 0x00FF00FF + .equ C4, 4294967295 // 0xFFFFFFFF + .equ width, 4 + + push.w {R4-R12, lr} + + ldr.w in0, [in_p, #4 * width] // a[2] + ldr.w in2, [in_p, #5 * width] + ldr.w in4, [in_p, #6 * width] // a[3] + ldr.w in6, [in_p, #7 * width] + + lsr.w in1, in0, #16 + lsr.w in3, in2, #16 + lsr.w in5, in4, #16 + lsr.w in7, in6, #16 + + mov.w R12, C4 + + and.w in0, in0, R12, lsr #16 + and.w in2, in2, R12, lsr #16 + and.w in4, in4, R12, lsr #16 + and.w in6, in6, R12, lsr #16 + + or_shift_and in0, C3, 8 + or_shift_and in1, C3, 8 + or_shift_and in2, C3, 8 + or_shift_and in3, C3, 8 + or_shift_and in4, C3, 8 + or_shift_and in5, C3, 8 + or_shift_and in6, C3, 8 + or_shift_and in7, C3, 8 + + or_shift_and in0, C2, 4 + or_shift_and in1, C2, 4 + or_shift_and in2, C2, 4 + or_shift_and in3, C2, 4 + or_shift_and in4, C2, 4 + or_shift_and in5, C2, 4 + or_shift_and in6, C2, 4 + or_shift_and in7, C2, 4 + + or_shift_and in0, C1, 2 + or_shift_and in1, C1, 2 + or_shift_and in2, C1, 2 + or_shift_and in3, C1, 2 + or_shift_and in4, C1, 2 + or_shift_and in5, C1, 2 + or_shift_and in6, C1, 2 + or_shift_and in7, C1, 2 + + or_shift_and in0, C0, 1 + or_shift_and in1, C0, 1 + or_shift_and in2, C0, 1 + or_shift_and in3, C0, 1 + or_shift_and in4, C0, 1 + or_shift_and in5, C0, 1 + or_shift_and in6, C0, 1 + or_shift_and in7, C0, 1 + + // t = temp[4] ^ ((temp[7] >> 54) ^ (temp[7] >> 59) ^ (temp[7] >> 62)); + eor.w in0, in0, in7, lsr #22 + eor.w in0, in0, in7, lsr #27 + eor.w in0, in0, in7, lsr #30 + + push.w {in2, in3} // temp[5] + + ldr.w in2, [in_p, #2 * width] // a[1] + ldr.w in8, [in_p, #3 * width] + + lsr.w in3, in2, #16 + lsr.w in9, in8, #16 + + and.w in2, in2, R12, lsr #16 + and.w in8, in8, R12, lsr #16 + + or_shift_and in2, C3, 8 + or_shift_and in3, C3, 8 + or_shift_and in8, C3, 8 + or_shift_and in9, C3, 8 + + or_shift_and in2, C2, 4 + or_shift_and in3, C2, 4 + or_shift_and in8, C2, 4 + or_shift_and in9, C2, 4 + + or_shift_and in2, C1, 2 + or_shift_and in3, C1, 2 + or_shift_and in8, C1, 2 + or_shift_and in9, C1, 2 + + or_shift_and in2, C0, 1 + or_shift_and in3, C0, 1 + or_shift_and in8, C0, 1 + or_shift_and in9, C0, 1 + + // c[3] = temp[3] ^ temp[7]; + eor.w in8, in8, in6 + eor.w in9, in9, in7 + + // c[3] ^= (temp[7] << 10) | (temp[6] >> 54); + // c[3] ^= (temp[7] << 5) | (temp[6] >> 59); + eor.w in8, in8, in5, lsr #22 + eor.w in8, in8, in5, lsr #27 + eor.w in8, in8, in5, lsr #30 + + eor.w in8, in8, in6, lsl #10 + eor.w in8, in8, in6, lsl #5 + eor.w in8, in8, in6, lsl #2 + + eor.w in9, in9, in6, lsr #22 + eor.w in9, in9, in6, lsr #27 + eor.w in9, in9, in6, lsr #30 + + eor.w in9, in9, in7, lsl #10 + eor.w in9, in9, in7, lsl #5 + eor.w in9, in9, in7, lsl #2 + + str.w in8, [out_p, #6 * width] + str.w in9, [out_p, #7 * width] + + // c[2] = temp[2] ^ temp[6]; + eor.w in2, in2, in4 + eor.w in3, in3, in5 + + // c[2] ^= (temp[6] << 10) | (temp[5] >> 54); + // c[2] ^= (temp[6] << 5) | (temp[5] >> 59); + // c[2] ^= (temp[6] << 2) | (temp[5] >> 62); + + pop.w {in6, in7} // temp[5] + + eor.w in2, in2, in7, lsr #22 + eor.w in2, in2, in7, lsr #27 + eor.w in2, in2, in7, lsr #30 + + eor.w in2, in2, in4, lsl #10 + eor.w in2, in2, in4, lsl #5 + eor.w in2, in2, in4, lsl #2 + + eor.w in3, in3, in4, lsr #22 + eor.w in3, in3, in4, lsr #27 + eor.w in3, in3, in4, lsr #30 + + eor.w in3, in3, in5, lsl #10 + eor.w in3, in3, in5, lsl #5 + eor.w in3, in3, in5, lsl #2 + + str.w in2, [out_p, #4 * width] + str.w in3, [out_p, #5 * width] + + ldr.w in2, [in_p, #0 * width] // a[0] + ldr.w in4, [in_p, #1 * width] + + lsr.w in3, in2, #16 + lsr.w in5, in4, #16 + + and.w in2, in2, R12, lsr #16 + and.w in4, in4, R12, lsr #16 + + or_shift_and in2, C3, 8 + or_shift_and in3, C3, 8 + or_shift_and in4, C3, 8 + or_shift_and in5, C3, 8 + + or_shift_and in2, C2, 4 + or_shift_and in3, C2, 4 + or_shift_and in4, C2, 4 + or_shift_and in5, C2, 4 + + or_shift_and in2, C1, 2 + or_shift_and in3, C1, 2 + or_shift_and in4, C1, 2 + or_shift_and in5, C1, 2 + + or_shift_and in2, C0, 1 + or_shift_and in3, C0, 1 + or_shift_and in4, C0, 1 + or_shift_and in5, C0, 1 + + // c[1] = temp[1] ^ temp[5]; + eor.w in4, in4, in6 + eor.w in5, in5, in7 + + // c[1] ^= (temp[5] << 10) | (t >> 54); + // c[1] ^= (temp[5] << 5) | (t >> 59); + // c[1] ^= (temp[5] << 2) | (t >> 62); + eor.w in4, in4, in1, lsr #22 + eor.w in4, in4, in1, lsr #27 + eor.w in4, in4, in1, lsr #30 + + eor.w in4, in4, in6, lsl #10 + eor.w in4, in4, in6, lsl #5 + eor.w in4, in4, in6, lsl #2 + + eor.w in5, in5, in6, lsr #22 + eor.w in5, in5, in6, lsr #27 + eor.w in5, in5, in6, lsr #30 + + eor.w in5, in5, in7, lsl #10 + eor.w in5, in5, in7, lsl #5 + eor.w in5, in5, in7, lsl #2 + + str.w in4, [out_p, #2 * width] + str.w in5, [out_p, #3 * width] + + // c[0] = temp[0] ^ t; + eor.w in2, in2, in0 + eor.w in3, in3, in1 + + // c[0] ^= (t << 10); + // c[0] ^= (t << 5); + // c[0] ^= (t << 2); + eor.w in2, in2, in0, lsl #10 + eor.w in2, in2, in0, lsl #5 + eor.w in2, in2, in0, lsl #2 + + eor.w in3, in3, in0, lsr #22 + eor.w in3, in3, in0, lsr #27 + eor.w in3, in3, in0, lsr #30 + + eor.w in3, in3, in1, lsl #10 + eor.w in3, in3, in1, lsl #5 + eor.w in3, in3, in1, lsl #2 + + str.w in2, [out_p, #0 * width] + str.w in3, [out_p, #1 * width] + + pop.w {R4-R12, pc} + + // unlink register name + .unreq in_p + .unreq out_p + +.macro lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + ldr \out1_0, [\sp1, #0] + ldr \in0_2, [\sp1, #4] + + ldr \in0_0, [\sp0, #0] + ldr \in0_1, [\sp0, #4] + eor \in0_1, \in0_1, \out1_0 +.endm + +.macro lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + lsr \in0_3, \in0_2, #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + and \sp1, \mask, \b0_1, lsr #\offset + and \sp0, \mask, \b0_0, lsr #\offset + lsl \in0_3, \in0_3, #4 + add \sp1, \sp1, sp + add \sp0, \sp0, sp + + orr \in0_3, \in0_3, \in0_2, lsr #28 + ldr \out1_0, [\sp1, #0] + ldr \out1_1, [\sp1, #4] + + lsl \in0_2, \in0_2, #4 + ldr \out0_0, [\sp0, #0] + ldr \out0_1, [\sp0, #4] + + orr \in0_2, \in0_2, \in0_1, lsr #28 + lsl \in0_1, \in0_1, #4 + orr \in0_1, \in0_1, \in0_0, lsr #28 + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, offset + lsl \in0_3, \in0_3, #4 + and \sp1, \mask, \b0_1, lsl #\offset + orr \in0_3, \in0_3, \in0_2, lsr #28 + and \sp0, \mask, \b0_0, lsl #\offset + + lsl \in0_2, \in0_2, #4 + add \sp1, \sp1, sp + orr \in0_2, \in0_2, \in0_1, lsr #28 + add \sp0, \sp0, sp + + lsl \in0_1, \in0_1, #4 + ldmia \sp1, {\out1_0-\out1_1} + orr \in0_1, \in0_1, \in0_0, lsr #28 + ldmia \sp0, {\out0_0-\out0_1} + lsl \in0_0, \in0_0, #4 + + eor \in0_1, \in0_1, \out1_0 + eor \in0_2, \in0_2, \out1_1 + eor \in0_0, \in0_0, \out0_0 + eor \in0_1, \in0_1, \out0_1 +.endm + +.macro last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + and \mask, \one, \r0_ret, lsr #\offset + sub \mask, \zero, \mask + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.macro last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, offset + sub \mask, \zero, \r0_ret, lsr #\offset + and \mask0_1, \b0_0, \mask + and \mask0_2, \b0_1, \mask + + lsl \mask0_0, \mask0_1, #\offset + lsr \mask0_1, \mask0_1, #32 - \offset + orr \mask0_1, \mask0_1, \mask0_2, lsl #\offset + lsr \mask0_2, \mask0_2, #32 - \offset + + eor \in0_1, \in0_1, \mask0_0 + eor \in0_2, \in0_2, \mask0_1 + eor \in0_3, \in0_3, \mask0_2 +.endm + +.global AIMER_NAMESPACE(poly64_mul) +.type AIMER_NAMESPACE(poly64_mul), %function +AIMER_NAMESPACE(poly64_mul): + t0_0 .req R0 + t0_1 .req R1 + t1_0 .req R2 + t1_1 .req R3 + t2_0 .req R4 + t2_1 .req R5 + t3_0 .req R6 + t3_1 .req R7 + t4_0 .req R8 + t4_1 .req R9 + t5_0 .req R10 + t5_1 .req R11 + + r1_copy .req R12 + t_base .req R14 + + sp0 .req R12 + sp1 .req R14 + + b0_0 .req R0 + b0_1 .req R1 + + in0_0 .req R2 + in0_1 .req R3 + in0_2 .req R4 + in0_3 .req R5 + + out0_0 .req R6 + out0_1 .req R7 + out1_0 .req R8 + out1_1 .req R9 + + mask .req R10 + + zero .req R6 + one .req R7 + + r0_ret .req R8 + + mask0_0 .req R9 + mask0_1 .req R11 + mask0_2 .req R12 + + push {R4-R11, lr} + push {R2-R3} + + ldr t1_0, [R0, #0] + ldr t1_1, [R0, #4] + push {t1_1} + + sub sp, #128 // allocating space in the stack + // 8 bytes * 16 = 128 bytes + mov t_base, sp + mov r1_copy, R1 + + mov t0_0, #0 + mov t0_1, #0 + + and t1_1, #0x1FFFFFFF + + lsl t2_1, t1_1, #1 + orr t2_1, t2_1, t1_0, lsr #31 + lsl t2_0, t1_0, #1 + + eor t3_0, t1_0, t2_0 + eor t3_1, t1_1, t2_1 + + lsl t4_1, t2_1, #1 + orr t4_1, t4_1, t2_0, lsr #31 + lsl t4_0, t2_0, #1 + + eor t5_0, t1_0, t4_0 + eor t5_1, t1_1, t4_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t0_0, t2_0, t4_0 + eor t0_1, t2_1, t4_1 + + lsl t2_1, t4_1, #1 + orr t2_1, t2_1, t4_0, lsr #31 + lsl t2_0, t4_0, #1 + + eor t5_0, t2_0, t3_0 + eor t5_1, t2_1, t3_1 + + eor t3_0, t2_0, t1_0 + eor t3_1, t2_1, t1_1 + + eor t4_0, t4_0, t0_0 + eor t4_1, t4_1, t0_1 + + eor t4_0, t4_0, t2_0 + eor t4_1, t4_1, t2_1 + + eor t1_0, t1_0, t0_0 + eor t1_1, t1_1, t0_1 + + stmia t_base!, {t0_0-t5_1} // 4 bytes X 12 elements = 48 bytes + + eor t1_0, t5_0, t0_0 + eor t1_1, t5_1, t0_1 + + eor t2_0, t2_0, t0_0 + eor t2_1, t2_1, t0_1 + + eor t3_0, t3_0, t0_0 + eor t3_1, t3_1, t0_1 + + eor t0_0, t4_0, t0_0 + eor t0_1, t4_1, t0_1 + + stmia t_base, {t0_0-t3_1} // 4 bytes X 8 elements = 32 bytes + + ldmia r1_copy, {b0_0-b0_1} + mov mask, #0x00000078 + + lut_access0_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 25 + lut_access0_1_0 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 21 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 17 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 13 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 9 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 5 + lut_access0_1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 1 + lut_access1 sp0, sp1, mask, b0_0, b0_1, out0_0, out0_1, out1_0, out1_1, in0_0, in0_1, in0_2, in0_3, 3 + + mov zero, #0 + mov one, #1 + ldr r0_ret, [sp, #128] + + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 29 + last_mask0 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 30 + last_mask1 mask, one, r0_ret, zero, mask0_0, mask0_1, mask0_2, b0_0, b0_1, in0_1, in0_2, in0_3, 31 + + ldr R0, [sp, #132] + ldr R1, [sp, #136] + add sp, #140 // restoring stack + + str in0_0, [R1, #0] + str in0_1, [R1, #4] + + str in0_2, [R0, #0] + str in0_3, [R0, #4] + + pop {R4-R11, pc} + + // unlink register name + .unreq t0_0 + .unreq t0_1 + .unreq t1_0 + .unreq t1_1 + .unreq t2_0 + .unreq t2_1 + .unreq t3_0 + .unreq t3_1 + .unreq t4_0 + .unreq t4_1 + .unreq t5_0 + .unreq t5_1 + + .unreq r1_copy + .unreq t_base + + .unreq sp0 + .unreq sp1 + + .unreq b0_0 + .unreq b0_1 + + .unreq in0_0 + .unreq in0_1 + .unreq in0_2 + .unreq in0_3 + + .unreq out0_0 + .unreq out0_1 + .unreq out1_0 + .unreq out1_1 + + .unreq mask + + .unreq zero + .unreq one + + .unreq r0_ret + + .unreq mask0_0 + .unreq mask0_1 + .unreq mask0_2 diff --git a/crypto_sign/aimer256f/m4speed/aim2.c b/crypto_sign/aimer256f/m4speed/aim2.c new file mode 100644 index 00000000..74e41922 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/aim2.c @@ -0,0 +1,598 @@ +// SPDX-License-Identifier: MIT + +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include +#include + +// inverse Mersenne S-box with e1 = 11 +// (2 ^ 11 - 1) ^ (-1) mod (2 ^ 256 - 1) +// = 0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5 +// b6d6dadb5 b6 b6d6dadb5 b6 b6d6dadb5 b6 b6d6dadb5 b6 b6d6dadb5 b6 b6d6dadb5 +void GF_exp_invmer_e_1(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}; + GF table_5 = {0,}, table_6 = {0,}; + GF table_a = {0,}, table_b = {0,}, table_d = {0,}; + + // t1 = in ^ 4 + GF_sqr_s(table_d, in); + GF_sqr_s(t1, table_d); + + // table_5 = in ^ 5 + GF_mul_s(table_5, t1, in); + // table_6 = in ^ 6 + GF_mul_s(table_6, table_5, in); + // table_a = in ^ 10 = (in ^ 5) ^ 2 + GF_sqr_s(table_a, table_5); + // table_b = in ^ 11 + GF_mul_s(table_b, table_5, table_6); + // table_d = in ^ 13 + GF_mul_s(table_d, table_b, table_d); + + // table_b = in ^ (0xb6), table_5 = in ^ (0xb5) + GF_sqr_s(t1, table_b); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_5, t1, table_5); + GF_mul_s(table_b, t1, table_6); + + // t1 = in ^ (0xb6 d) + GF_sqr_s(t1, table_b); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6d 6) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // t1 = in ^ (0xb6d6 d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ (0xb6d6d a) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_a); + + // t1 = in ^ (0xb6d6da d) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // table_5 = in ^ (0xb6d6dad b5) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(table_5, t1, table_5); + + // t1 = in ^ (0xb6d6dadb5 b6) + GF_sqr_s(t1, table_5); + for (i = 1; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6d6dadb5b6 b6d6dadb5) + for (i = 0; i < 36; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5 b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6 b6d6dadb5) + for (i = 0; i < 36; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5 b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6 b6d6dadb5) + for (i = 0; i < 36; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5 b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6 b6d6dadb5) + for (i = 0; i < 36; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_5); + + // t1 = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5 b6) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_b); + + // out = in ^ (0xb6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6b6d6dadb5b6 b6d6dadb5) + for (i = 0; i < 36; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, table_5); +} + +// inverse Mersenne S-box with e2 = 141 +// (2 ^ 141 - 1) ^ (-1) mod (2 ^ 256 - 1) +// = 0x2224448889112222444888911222244488911122244448891112224444889111 +// 222444 8889112 222444 8889112 222444 889111 222444 4889111 222444 4889111 +void GF_exp_invmer_e_2(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}, t2 = {0,}, t3 = {0,}, t4 = {0,}, t5 = {0,}; + GF table_9 = {0,}; + + // t2 = in ^ (0x11), table_9 = in ^ 9 + GF_sqr_s(t1, in); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(table_9, t1, in); + GF_sqr_s(t1, t1); + GF_mul_s(t2, t1, in); + + // t3 = in ^ (0x111) + GF_sqr_s(t1, t2); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t3, t1, in); + + // t4 = in ^ (0x222444) + GF_sqr_s(t1, t3); + for (i = 0; i < 10; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t3); + GF_sqr_s(t1, t1); + GF_sqr_s(t4, t1); + + // t1 = in ^ (0x222444 8889) + GF_sqr_s(t1, t4); + for (i = 1; i < 9; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t3); + + for (i = 0; i < 7; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_9); + + // t1 = in ^ (0x2224448889 11) + for (i = 0; i < 8; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + // t5 = in ^ (0x222444888911 2) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, in); + GF_sqr_s(t5, t1); + + // t1 = in ^ (0x2224448889112 2224448889112) + GF_sqr_s(t1, t5); + for (i = 1; i < 52; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t5); + + // t1 = in ^ (0x22244488891122224448889112 222444) + for (i = 0; i < 24; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t4); + + // t1 = in ^ (0x22244488891122224448889112222444 889) + for (i = 0; i < 5; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + for (i = 0; i < 7; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_9); + + // t1 = in ^ (0x22244488891122224448889112222444889 111) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t3); + + // t1 = in ^ (0x22244488891122224448889112222444889111 222444) + for (i = 0; i < 24; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t4); + + // t1 = in ^ (0x22244488891122224448889112222444889111222444 4) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, in); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + + // t1 = in ^ (0x222444888911222244488891122224448891112224444 889) + for (i = 0; i < 5; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + for (i = 0; i < 7; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_9); + + // t1 = in ^ (0x222444888911222244488891122224448891112224444889 111) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t3); + + // t1 = in ^ (0x222444888911222244488891122224448891112224444889111 222444) + for (i = 0; i < 24; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t4); + + // t1 = in ^ (0x222444888911222244488891122224448891112224444889111222444 4) + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, in); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + + // t1 = in ^ (0x2224448889112222444888911222244488911122244448891112224444 889) + for (i = 0; i < 5; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, t2); + + for (i = 0; i < 7; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_9); + + // out = in ^ (0x2224448889112222444888911222244488911122244448891112224444889 111) + for (i = 0; i < 12; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(out, t1, t3); +} + +// inverse Mersenne S-box with e3 = 7 +// (2 ^ 7 - 1) ^ (-1) mod (2 ^ 256 - 1) +// = 0xddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76ed +// ddbb76e ddbb76e ddbb76e ddbb76e ddbb76e ddbb76e ddbb76e ddbb76e ddbb76e d +void GF_exp_invmer_e_3(GF out, const GF in) +{ + size_t i; + GF t1 = {0,}; + GF table_6 = {0,}, table_7 = {0,}, table_b = {0,}, table_d = {0,}; + + // t1 = in ^ 3 + GF_sqr_s(table_d, in); + GF_mul_s(t1, table_d, in); + + // table_6 = in ^ 6 + GF_sqr_s(table_6, t1); + // table_7 = in ^ 7 + GF_mul_s(table_7, table_6, in); + // table_b = in ^ 11 + GF_sqr_s(table_b, table_d); + GF_mul_s(table_b, table_7, table_b); + // table_d = in ^ 13 + GF_mul_s(table_d, table_b, table_d); + + // t1 = in ^ 0xdd + GF_sqr_s(t1, table_d); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_d); + + // t1 = in ^ 0xdd b + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ 0xddb b + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_b); + + // t1 = in ^ 0xddbb 7 + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb7 6 + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_6); + + // table_7 = in ^ 0xddbb76 e + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(t1, t1, table_7); + GF_sqr_s(table_7, t1); + + // t1 = in ^ 0xddbb76e ddbb76e + GF_sqr_s(t1, table_7); + for (i = 1; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76eddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // t1 = in ^ 0xddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76e ddbb76e + for (i = 0; i < 28; i++) + { + GF_sqr_s(t1, t1); + } + GF_mul_s(t1, t1, table_7); + + // out = in ^ 0xddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76e d + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_sqr_s(t1, t1); + GF_mul_s(out, t1, table_d); +} + +// Mersenne exponentiation with e_star = 3 +void GF_exp_mer_e_star(GF out, const GF in) +{ + GF t1 = {0,}; + + // t1 = a ^ (2 ^ 2 - 1) + GF_sqr_s(t1, in); + GF_mul_s(t1, t1, in); + + // out = a ^ (2 ^ 3 - 1) + GF_sqr_s(t1, t1); + GF_mul_s(out, t1, in); +} + +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + uint8_t buf[AIM2_NUM_BYTES_FIELD]; + uint64_t ormask, lmask, umask; + hash_instance ctx; + GF temp = {0,}; + + // initialize hash + hash_init(&ctx); + hash_update(&ctx, iv, AIM2_IV_SIZE); + hash_final(&ctx); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t row = 0; row < AIM2_NUM_BITS_FIELD; row++) + { + hash_squeeze(&ctx, buf, AIM2_NUM_BYTES_FIELD); + GF_from_bytes(temp, buf); + + ormask = ((uint64_t)1) << (row % 64); + lmask = ((uint64_t)-1) << (row % 64); + umask = ~lmask; + + size_t inter = row / 64; + size_t col_word; + for (col_word = 0; col_word < inter; col_word++) + { + // L is zero, U is full + matrix_L[num][row][col_word] = 0; + matrix_U[num][row][col_word] = temp[col_word]; + } + matrix_L[num][row][inter] = (temp[inter] & lmask) | ormask; + matrix_U[num][row][inter] = (temp[inter] & umask) | ormask; + for (col_word = inter + 1; col_word < AIM2_NUM_WORDS_FIELD; col_word++) + { + // L is full, U is zero + matrix_L[num][row][col_word] = temp[col_word]; + matrix_U[num][row][col_word] = 0; + } + } + } + + hash_squeeze(&ctx, (uint8_t *)vector_b, AIM2_NUM_BYTES_FIELD); + hash_ctx_release(&ctx); +} + +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + for (size_t num = 0; num < AIM2_NUM_INPUT_SBOX; num++) + { + for (size_t i = 0; i < AIM2_NUM_BITS_FIELD; i++) + { + GF_transposed_matmul(matrix_A[num][i], matrix_U[num][i], + (const GF *)matrix_L[num]); + } + } +} + +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]) +{ + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + + GF state[AIM2_NUM_INPUT_SBOX]; + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, pt); + + // generate random matrix + generate_matrices_L_and_U(matrix_L, matrix_U, vector_b, iv); + + // linear component: constant addition + GF_add(state[0], pt_GF, aim2_constants[0]); + GF_add(state[1], pt_GF, aim2_constants[1]); + GF_add(state[2], pt_GF, aim2_constants[2]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(state[0], state[0]); + GF_exp_invmer_e_2(state[1], state[1]); + GF_exp_invmer_e_3(state[2], state[2]); + + // linear component: affine layer + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_U[0]); + GF_transposed_matmul(state[0], state[0], (const GF *)matrix_L[0]); + + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_U[1]); + GF_transposed_matmul(state[1], state[1], (const GF *)matrix_L[1]); + + GF_transposed_matmul(state[2], state[2], (const GF *)matrix_U[2]); + GF_transposed_matmul(state[2], state[2], (const GF *)matrix_L[2]); + + GF_add(state[0], state[0], state[1]); + GF_add(state[2], state[2], vector_b); + GF_add(state[0], state[0], state[2]); + + // non-linear component: Mersenne S-box + GF_exp_mer_e_star(state[0], state[0]); + + // linear component: feed-forward + GF_add(ct_GF, state[0], pt_GF); + + GF_to_bytes(ct, ct_GF); +} + +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt) +{ + // linear component: constant addition + GF_add(sbox_outputs[0], pt, aim2_constants[0]); + GF_add(sbox_outputs[1], pt, aim2_constants[1]); + GF_add(sbox_outputs[2], pt, aim2_constants[2]); + + // non-linear component: inverse Mersenne S-box + GF_exp_invmer_e_1(sbox_outputs[0], sbox_outputs[0]); + GF_exp_invmer_e_2(sbox_outputs[1], sbox_outputs[1]); + GF_exp_invmer_e_3(sbox_outputs[2], sbox_outputs[2]); +} diff --git a/crypto_sign/aimer256f/m4speed/aim2.h b/crypto_sign/aimer256f/m4speed/aim2.h new file mode 100644 index 00000000..bdc50429 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/aim2.h @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: MIT + +#ifndef AIM2_H +#define AIM2_H + +#include "field.h" +#include "params.h" +#include + +static const GF aim2_constants[AIM2_NUM_INPUT_SBOX] = +{ + {0x24a19947b3916cf7,0xba7c9045f12c7f99,0xb8e1afed6a267e96,0x2ffd72dbd01adfb7}, + {0x0d95748f728eb658,0xa458fea3f4933d7e,0x636920d871574e69,0x0801f2e2858efc16}, + {0xc5d1b023286085f0,0x9c30d5392af26013,0x7b54a41dc25a59b5,0x718bcd5882154aee} +}; + +static const GF aim2_e2_power_matrix[AIM2_NUM_BITS_FIELD] = +{ + {0x0000000000000001,0x0000000000000000,0x0000000000000000,0x0000000000000000}, + {0x13269d7dcfc555c3,0x6fe13874c42fedfb,0xc69f003d9d5abb9c,0x05636fd04ebf7feb}, + {0x7a273dd9fcec7e15,0x42cd3eb54144ea68,0x5a88aaa3ebaacdff,0x527284e39fae2053}, + {0x56bb9ab537abf542,0x768c3d772850c862,0x0160d91d288fd0e0,0x342e111e0a022022}, + {0xcdb998ce4b3eee2e,0x78984c4dc99c90aa,0x2bb89f84c00275b6,0x75c6a0cc065fd4ac}, + {0x74b2cd2360cb32af,0xbde82f7cf42dd1bf,0x7ceed82d54d965c4,0xf4e9f207aa17f2e9}, + {0x995d5aab614ac6c0,0x1563800b79242f35,0x1d940184c4509090,0xe6558fd024716b90}, + {0x8d0b793b4375cc8a,0xfcf792217776a3ee,0x5da44008043b7450,0xc77adf87407cf838}, + {0x00451596f23df45e,0xd8bcbc0d7ae8534f,0x02c26abe3748db45,0xb37e029dc51a4b41}, + {0x177dbfce6cbc8c0b,0x62cdd72c8cbd2d2a,0x568802d992bd7a2c,0xd0082d2193b6e383}, + {0x221e6872863f45c6,0xbe5a9bce6c00df76,0x98c076efe1cfcc67,0xa75bdc7ab5c142a9}, + {0x088d4e8e27e0b74d,0x71046740fe7e6c5a,0x20123cab6052c1d6,0xa7135d055351c99b}, + {0x46176449341c7657,0x2a7936011468475e,0xc347e166dca96014,0xd79326785eee3555}, + {0xc6b77e5a8b6dcae9,0x6dc641a8e07c54d4,0x37055c3ed77341a8,0xd75eaedd0ec6f1d1}, + {0x5240b9b6f3433443,0x7b7d965745400c05,0x4542be5aec50ec53,0x13e6ac8f2aac12a2}, + {0x66c30b9da469d401,0xcd5dbf02dc359172,0xf16b3e62f8a57e1d,0x362c2bc9345b97ed}, + {0xb2a65d5f7da755e8,0x11df10d6ddd9eb84,0x433468d75cb64470,0xb4a6ffd454c82b2f}, + {0x1c87142145f7c112,0xde2854fa4939dc0b,0x10a503b51b7c7a19,0x174f91701431e1b3}, + {0x60d8fb32b890cec6,0x27d95c11548f693c,0x30fce7ce95e950b3,0x210559008a309578}, + {0x5de49c870dd8fb60,0x1f480e246bb2c961,0xdc5efcb1f4ee90ae,0x165c3f5b62136c5e}, + {0xc17b4bbe4b5780a8,0x690f1102a6decffe,0xa26e146710d9cd7d,0xc7f278fb3f02a99d}, + {0x4fe7916de7e17f1c,0xe9e59586ac0a7185,0x092b72935bc23437,0xa306568e985edbfa}, + {0xc05330df507b35c8,0x944475d0eb5c89f7,0x34a3653b083969a5,0x97e431e62e205633}, + {0x19fe581ef3e9a896,0x720ab1851376eff0,0xda5ca1af445dea40,0xe3899fd1cdc93f2f}, + {0x7a18d867d11567d6,0x14e706af946787cb,0x2ececbd0e726236a,0x66a864e0c387e806}, + {0x0a0a9e1dc2c9d30d,0xa1bd85358585db7a,0x78f90bb68d83e25e,0x2275165a7e496039}, + {0x23f2e1a2057c9892,0xb7f503272b51fa8f,0x0ecf56cbb57a6021,0x77f77f889ecb3e74}, + {0x237633913a45a827,0x3a2c98b4d38d139b,0xbc1dfd5ddab4bb19,0xf2bcbdc105b017fd}, + {0x9a53645fca466120,0x07335188ef82289a,0x9cdd8f1434ddc4c7,0x25afc28ddf0c0ea5}, + {0x0166bda62c3c97ac,0x4821343275a35741,0xa4a1f8ef377f5177,0x3008d4b041fc0802}, + {0xed498663eb9138f0,0xb16289e1ea93949b,0xa2476ced73badf6e,0xb384ce50cdee1d75}, + {0x25430e5e2ea409d8,0xf8909d2164becc11,0x77663884798e456b,0xe11b963640c6a7da}, + {0x2a5ce7930313e789,0x01a1b717dd5e72f3,0x674b4810dda58bf3,0xb348d6cffeee2602}, + {0xe4871c9932b98648,0x90432c7798b61577,0xf803346f3989e611,0x176c5f43490e3127}, + {0x28b7ff52a8d039f5,0x2549d26014bcb371,0x7705b13fd068e5f0,0x22f60aec7063b440}, + {0xa90087e5804b094e,0x17b587e9f7b1334c,0x7e9128a8fd49f502,0x10a15de60dcc1259}, + {0x676fc8232449f7f5,0xa45eba0b86ee4f8d,0x48d0f0583763ed04,0x9430177369350009}, + {0x8bb187487d0ca392,0x8b34c408cf71198e,0x4c5b9033c740f6cb,0x15165d415ea592e5}, + {0xe25b8fc9315d8b10,0x6f067bcaaa5db46f,0xc0d574e6df163bcb,0x76d62e45eeb26cb3}, + {0xc7bb4eaa81af7e21,0xc0c25e2c4da66ca9,0x20a5b7a6ef682683,0xe0c40a42bed8c878}, + {0x340b283a1f67eb72,0x94c68ac57747d7b1,0xaab540d8883c7e78,0x53ffb196e81fbce0}, + {0x03d1fe920cc5c8b6,0x2d058e7c02de80d0,0x349140f34518313d,0x52d8d34dce452897}, + {0x3daf5481e615a4ec,0x1d21ddb2b19865a7,0x28572f8e3caef8c4,0x94f0069367dd5a9c}, + {0xf97efd31544a2432,0x79cc100bcd1c95c5,0x630dd7dbdcda2efa,0xb0c94889efaeabe6}, + {0x1855a973cd69d2ac,0xa249d1e68760fda5,0x9bd185166791f0b0,0x73aad654a16f87d5}, + {0xb64f4c4f69887572,0x0dd0ddfafeaec759,0x9a2b2e01a2dfdf21,0x23e6842e19958e74}, + {0x47126f2ed9d35243,0x2dd26a5dc07d8ab7,0x5f7a0864bae59fef,0x84bd4c2d7eef707e}, + {0xc2b75aa6809fde33,0x4e05ff4138a1458a,0x4283e814ca9b30b5,0x46b1bcf0f62d4313}, + {0x83f0c7c594f6cf9a,0xdb8a4b8e5dfe204e,0x44a803aecd550290,0x96cc8907871fc11e}, + {0x7ca33f7d36e71a53,0x609b8f2296791418,0xd9e9118ba8ddf5e9,0x813002deae63def5}, + {0x5e3805abc5d66c85,0xe95aac205db8a39d,0xfad61d269550a976,0xc0c3e22037926992}, + {0xf3ba3f8e2a564d34,0xfd74426f936299c0,0x23bb54e8112b82e3,0xc5afe8e8365a6000}, + {0xb733edd6855182ef,0x5ecb1ae3728f48e8,0x3b8b1ce5bf96e304,0xf3aba2a7bfac4c59}, + {0x78f2ea71794eaef2,0x59f25ef7fe359b84,0xacfd3e59513654c8,0xd1e24fda7d0c3936}, + {0x288da25da8b17fb3,0xbe107e7feb777a7a,0x166db15573baae6c,0xb5ccbf5cfe3e5135}, + {0x4637849d0285089d,0x4f671ebc0437c2ce,0x188565bc785f8268,0x712dec2cd1ba005e}, + {0xa25a6b6a471a00b1,0x6e1a6a380bb57611,0x3ef50b155eddd23d,0xd3788fef109d4e3b}, + {0x4f403f37eba563c1,0x76a201773cddd009,0x58fba6bec18e06a6,0x11a19d4cbf2a6331}, + {0xe3e6bbb73066a175,0x9748c56fec4b9fa1,0x406aae141855018c,0xa1410c0e735df446}, + {0x5e569e71e70eb719,0xa673071887dd4687,0x07055d8d0a23d785,0x74d498384aee1190}, + {0xa0e8a89b6fb6984d,0x908716f3ce5edf66,0x0a2b9e842b73e729,0xa1b9171e0b83204b}, + {0xbe7532657aadaa20,0x1b66940116e06582,0x7385fd540009963d,0x847a9b51570e7ff8}, + {0xe9395fd61662cbe6,0xb3a286d4b91d1353,0x455b0689d3ff2d83,0xd56078fc7681e787}, + {0x8b470957a3441b8a,0x7df431ebbf7e447b,0x0e0f4fa397edd83c,0xd793865c1388620e}, + {0x7b29927808bfa739,0x96e65ce20d51654b,0xaa8fcec0d3c045c3,0xe5f31c0e239b4fea}, + {0x5525c2a74e77bf9e,0x88cf3be85881afff,0x7c81312941d70c3c,0x23d8a44e23a9c737}, + {0xb869097f96d421f1,0xfc5054b0f253daf5,0x1c241e84b424d6aa,0x32b29f522eb351e7}, + {0x6a466e2ed7c0ad0b,0x5590c446ea6f583b,0x56d2464d3ee4d099,0x068910c7eb32dd95}, + {0x71139d1bc66bb641,0xb3a1027da065feea,0xe04294fcf6174557,0x81dae384498adb46}, + {0xf43ed00c527a209a,0xa5754026d1f22c89,0xc78a8d365f196923,0xf5154817fc84f220}, + {0xae764c7fe7341054,0xffc86134dc4d880f,0x1b6a1e1530d66862,0x250c95737b7b8284}, + {0xbfee6b3c1e46c128,0xa78dc08ba0e7251d,0x3a95f11bcef9d4c7,0x34f2831709c6a420}, + {0xe3a3c1aa9e2407d8,0x4c1a200af1077851,0x8965a32110544d77,0x6354a05036f3f5a7}, + {0xbd108a58fc17d8a6,0x61b0351824a54794,0x499e7fd9fdd626df,0x850217a6be595511}, + {0x53f2510fb68b5c61,0x5b122cfd2501b4ba,0x7fc88679758e8262,0x233472936a675422}, + {0x11965eaffc401c95,0x0af31e003ba1fb12,0x2facfdd6611b7f8b,0xd67eaae060c88abf}, + {0x6fa46680edff5f3f,0x454b6266e25e87cb,0x9addf096cb1df0af,0xa6de67c1da83476b}, + {0xbf6f0cb8a600033a,0xf520f28cc3846c4b,0x008f972a2108bd6a,0x55bbe0da272b6cb0}, + {0x9bf38905d29c13e7,0xc50cd62db6acc3da,0xbb9b791e0d47ac11,0xd54b025508c245d8}, + {0x3a2547ab532ec9ff,0x79495ddf670c8bc8,0xdf4ed2dcee44e1bc,0xc2e52f1fc1f7d4d5}, + {0x4800ee52ee97ecda,0xc9d9b772550e380c,0x98506ba8ea5ec019,0x21ffafa8b46c668f}, + {0x3464a9138085b307,0xf67a192be113e9cc,0xfdd61b66e0e162dc,0xd612aba17d397d2c}, + {0x16207c45e571aabf,0xf2583066040bf4f7,0x4bc24730dc4d62f5,0x608b3d1e61a60b2f}, + {0xc2a6d2c707faaab1,0xc9cfa575f99f891a,0x61ea461507f40f96,0x67104299d7331a82}, + {0xaf1c8fcbed1f1699,0x985767a5dbb95b90,0xd6ae3b3279c96a14,0x275ea501029834e7}, + {0x4e19e32114de1e9c,0x165f71d116e0afb9,0xe968cbf378c1a2f7,0x912182eb2d02ef2d}, + {0x6e4e3c81caceef19,0x85f15b2e37fe2cbe,0x8ae88fcc89bb8687,0xe50b4d7659484c7a}, + {0x80353d06c9930d5c,0x723d1f993acaffad,0x89e273ac935dc5e2,0x51356090a9eecbf9}, + {0xc3bd743bf118e69e,0x78fe213d42306293,0x90638ea842ff3668,0xb0addcda3683625d}, + {0xe26008c6b83cc264,0x74bbbd5777680be8,0xa8892126f9cc485a,0x54899977a5cc34a1}, + {0xd19b2baf7fa0c771,0x39d199b5dfd41569,0x7c3c66294bc7b31d,0x81bb86cd53109ac5}, + {0xe4a790156b11f26a,0xb496c49018830c99,0xf19e574456b9d549,0x867aa70b9bbd4fd0}, + {0xb8ce927c2afbcba9,0x3ae3f9d11d478318,0xebdecea6a113ffd6,0x071def720f45ca33}, + {0xa18c4347c3dba5da,0xc231d50db69b59f6,0x784caea3c01900f9,0x21b179202d1177e0}, + {0x48d839b0e148b37a,0x119910fe9c00220e,0xf6959f7654a471b7,0x138df428ee1ab05e}, + {0x2378b25ea2d743c2,0x52a0660820b6ff4b,0xb20d6835419796a6,0x77d41062fb9a7654}, + {0x1e63666141c834dd,0x534d884045bcdedf,0x07b52ebe10206e92,0x67cb1a5c5d2017bc}, + {0xbd489efa4249447b,0x81b1f830bdd020d0,0xb8db0042e390a71b,0x90b877cf8d8200e6}, + {0xd91a2f7fe76f986d,0x2c6fcd64257849b8,0xcec2c4be6ecbe77b,0x5031f045518f6b98}, + {0x3cc9f99a10cba6b9,0x7df264605ea09f19,0xc6099006fa2f35a0,0xf31aa1999c65f2ed}, + {0x7322250ccd66f2d2,0xa8cf62816a34838c,0xf7bd30878c6d359b,0x450a14aed0d49014}, + {0xf753996b7d7c1d54,0x45e2b366fb683eae,0xcef4cef44af75b4a,0xd1e647d51db49a04}, + {0x257099ec419b94a6,0xd4a8a9f3335fcd10,0xa286788285415010,0x023c9feb9c1e9901}, + {0x229d6fd7eed1531c,0x04cefb6c19ff0062,0x9130be016eed6e29,0xa1a04435eb4cd39d}, + {0xefbd279ed0b045c6,0xe8ec58f13b1a927d,0xbabddf060b172c30,0xa5fd98adc4c9d7f8}, + {0x0f859d44ce18448a,0x07af518284a5a680,0xff7565589bc19136,0x72e50c2e9eaa580a}, + {0x6470f3d6724b5dd7,0x8b0ebb24be876d22,0xfb604e14fd34a2cc,0x213fc1d31fbb7996}, + {0x50e1d4f6f24a3685,0x69348d20cb64f7b6,0xa13da095f7678267,0xb63a6ac7a66c3284}, + {0xb0edaccd9a8698dc,0x73d7ca79b1672272,0xaed4ffd76475e235,0xf36b5b0cbbb22a1b}, + {0x24acd40ab0b10aba,0xafb39e3ea0656a92,0xcfe743611a51fa5a,0xb4f8251f0f0e0d41}, + {0xe8036bb95086dfdf,0x3d5d0332c379fb16,0x3029edc150437ed5,0xf561ce7ace559b0f}, + {0x01047fd87eb154ca,0xce04d75cd86f0d9d,0x33f6d9a762e84d0b,0x52f77f2619632746}, + {0x3fdf7a3e2584aaa7,0xafdff63009b07776,0x24496f671e85ade5,0x35b2e80c0abfdee5}, + {0x4bb3e9185acc78b3,0xe5634557a7f532a4,0xa6a979853e645782,0x97e9a6c3f5ed6068}, + {0x41685f9547d8c651,0x6d4bade8828daeda,0xabe0dcd781a5b523,0x3528952d2a770f19}, + {0xe4e43b26b587ea84,0xf0f3f420178def6d,0xd48cb1f978a8bb2e,0x25de266fb8567a86}, + {0x2906276141285c5c,0x045688d8cac52240,0xa1a62b2fa2474687,0x917244641b004f87}, + {0x73897ebb86a40eb0,0x0df1bc6722ab333e,0xb7815fffa0c79792,0x322111adf2c83d06}, + {0x4dd181aa27fc54fa,0x47b557267a691a35,0x089b8ed1303c2515,0xe60b63596c40b943}, + {0xe574bb3f5e1d3fe5,0x7e5e1dd1aaea6c56,0x443b9d58176d285b,0xa2c066cf80f1c62d}, + {0x9df2b1fe93b4cb69,0x5dc5dcbd7bcd4304,0x4cac45f5c51659e4,0x9039bc7472f02b80}, + {0x81c7d14b2ff6f3d6,0x76b7422e6f000e01,0x23e23fa520ed280b,0x50a4f9ded0d07978}, + {0x154548397391fa38,0xb1ec123aeb772341,0x22f40fd3abeee812,0x0342edcc39a77162}, + {0xa7ef812f5e9d9ba6,0x65de86bcc8071b0d,0x4b9bbe60fe0a1fad,0xf4f8322efc5e2f45}, + {0x21fbeab48a7c1136,0x42736db042991d3e,0xf78c442fd2ed07a6,0x36228053a90abb56}, + {0x6ebfcec360d88021,0x7deeafd7cae1b159,0x6f32c272246a4999,0xb2f984f6c2b488dd}, + {0x76beda6b3d15abc7,0x1bc04ff70ef9d0a9,0x75ec5c46c4854ec0,0x77bd25a817826a51}, + {0xf79c8d9bd7aaf4f0,0xae5add9fd1454f93,0xd9f264167923d698,0x273bf89c8b33a9ec}, + {0x20ba5517532e42a7,0xd9991aaa0bcb040f,0x81ec69b31aea8c89,0x823ee1a07f410f90}, + {0x3e10957041e49998,0x9746fdf5f3deb53d,0xbae6be6d5a7923dd,0xd4aa255a7e60b5f8}, + {0x453e76f50e50f914,0xba084020e530dd32,0x90e9982f02a0b2e3,0xc1bf6d0c93565fd4}, + {0xbb44043183434a96,0xb6839987e4d3fbf5,0x780e11ff154ba921,0x46deb765191c6fad}, + {0xf254860f62ddca11,0x2b40c2147fcc1618,0x9b9df4f2213a87f5,0xf5d9f1982bf72085}, + {0x9ec887ef1dac7ea8,0xf9b9f41cd1a90cab,0x5106c66727088891,0xa079314a8a7aa0cc}, + {0xbaca971f705d6820,0x32cf35c216d31b74,0xcda1b48f6a782676,0x42dd0c61745b57af}, + {0x774f50e70700fa3c,0xfe706a77d17875e0,0x50acd4b9e4f085bc,0xa70b2f3a3373b5cf}, + {0xa3d467e6532333ed,0x9143409c675fea0a,0x186d4c8b7de757db,0x006e698e91bc1742}, + {0x042690d62241c815,0xf8a04fddc8420797,0x9ff8cf1394eaada4,0x921b7749e0687334}, + {0x3ba03d72cd709236,0x12f95d885e21e3d3,0xba18560bb5d4d50a,0xa3607627494476ab}, + {0xade31f9ca5377f89,0x635510178eec1003,0x3dca939c351bf98d,0x339c87aee1cf78dd}, + {0xe45a6287cc1287d4,0x7cf6c8c56ed07634,0xadf6eda911dd0200,0x87211a5d3722f0f6}, + {0x7b07d341c0de902d,0x69838993df5c9429,0xb8921642be862244,0x555819247b006cca}, + {0x4b8ebd3e261a1065,0xec8c767eb1653ceb,0x482e17c892519544,0xb61af0cc04b533a5}, + {0x4fb9d38c4e2f7113,0x50030b8523699320,0x5716f5c60cedd7d8,0x0673e662c18aadef}, + {0x641233031f77a5fb,0x1932c76990a0d465,0xb79ab4fbf32c92e8,0xc0a7370dd0467550}, + {0xdb899bf50910763a,0xf026477f262eb097,0x76b70a1b2163a0d4,0x93a2873f23165f6e}, + {0xba2a66c196ce2eb8,0x19383fd3ffab287b,0xaed33c3223646076,0x1274559077e98698}, + {0x035a94843c44ec7a,0x6de99478a3c009e3,0x8a7ecba43ae87e6e,0x458c9cbfca30c71a}, + {0xe3695ac8419682c5,0xaeee4d4d0392ec66,0xd99792a67250c187,0x91e0f202f4c924b3}, + {0x9c784cfbf5192c27,0xc113eee0e80c2eae,0x3f7b5a6101ce5f5e,0x842e2d646ecd9d6e}, + {0x957028a6befc0d73,0xcbb8df5afe2e23c3,0xc00f5c490d8dafb4,0x67d7ee99cddb8452}, + {0xac8c3e869f704d2d,0xc928ad50bd4faf6e,0x114a0001a078d1a0,0x8375ad6cc681586b}, + {0x59a53e3fb149cca9,0x69cf3f7ab419768e,0x79d945a746a788b8,0x979b7e9387ae017f}, + {0x41f7712568f43935,0xf17647a51bb6cff9,0x593eb0f68e21db19,0x77bf0442e77fdbdd}, + {0xd430085cbe62c90e,0x445d0af933a0c884,0x92f5c9b29a5de145,0x6778e9aad04a6c94}, + {0x4914b4bd446c5d64,0x21b19c795fec736d,0x72cf9cdf7fa1c0db,0xf67226412058b23c}, + {0x1e7346a99e1464a3,0xacb82da3ac217e94,0x4d1f4486473e6c18,0x23274da141c63725}, + {0xf58a0445c9b4903b,0x4f196615648056a4,0xeaf0d8fc78e51fe3,0xc71e969830bec69e}, + {0xcec3175fd17dee42,0x6fa60eda34cf3b0f,0x016ff6fe365a227b,0x148ed225daf52abf}, + {0x5eb5954a6c060dcd,0x67ed2e3411fbde9d,0xdaddfd054f15c5a4,0x80e12ae0d1591ef3}, + {0xc9c76eda44553b71,0x7c4675538cbdcd1e,0xa2128f16928c1efd,0xc13aaef8cfacc959}, + {0x525318d3ea7544bd,0x6f3e0f4d85ce7b2a,0x397102e6892ab449,0xd028319bc9ef0676}, + {0xc55bc06690da6f96,0xea6a73d17ce2969a,0xfa21bd37fa658e1e,0x32d421c8c9a9d437}, + {0x4f53f0e462a9f4f0,0x18c65d2ba362d43b,0x53b8871400599e70,0xf291e9ac535cfe6e}, + {0x2a420a66918ee17a,0x4dae04d613a5a05f,0xc12c868048f09ef7,0x900c4ca4fb306ac2}, + {0x357f0638ee05acbc,0x389db47cc78620f7,0x3c531ff5b9fff02b,0x902c96f5fb2c18f9}, + {0x57abb6151ae9319f,0x917bd98253c43360,0x36b4e4e17d9c5182,0xc2a4751705897c3b}, + {0x91ee0ad214084c1b,0xfe17b657a9ea9054,0x7b304880e7a3efb6,0xd497c8cea46cf443}, + {0xb97e1c63dcc46441,0x22898ec1ecb0f186,0x40dd2915e34e92ae,0x83e63e8886604034}, + {0xf159f13af4545efc,0x6b0312cbfce549f7,0x1632f9e6624b3c5e,0xc387a21c7c20a6d6}, + {0xe81b4468c49ba628,0x9962cd4b58abb1e7,0xda2145ce9fe59f2e,0x6021807944cfc8e1}, + {0x9e98852b17310f23,0x3cbe1c8bceb45120,0x0e165b29c57ec0eb,0x305bf854fb1aea8d}, + {0x1c3dbdac479d54f7,0x4cda9c1c1bbb1a19,0x7d330c571f17bc88,0x826548b30e26b7d7}, + {0x446afa2ca1809535,0x8d3c9693ee673350,0x7893a83f58de1ffc,0xb19954f7647195ff}, + {0x21b77a7b577e945a,0x0c3e91d3f1f89e09,0xdd7b8e8a59fae93c,0x6435f276c4582559}, + {0x4d0e6426007bc199,0x5c13184bcf7dd24a,0x26f1f87322e213d0,0x97243e676a3eb387}, + {0x14cbfff5b787dedd,0x355794e80f8cd847,0xf2c951e3c0d77a3d,0xe558cf2f7b5f2991}, + {0xf87b23ea7452e43c,0x92521695b010b548,0xb7af363918a98cf1,0x473e6304c6f3f9cf}, + {0xe86f5e030902695a,0x884c59759075978e,0x862a4f44f20c857d,0x2348092c2d62a7ed}, + {0xbebdf27580f800b3,0x4c82348a99cfaf36,0x7fec6e2fb343c70a,0xd0a2b036a8d95707}, + {0x59ef03fcb5a57f39,0xfb04bb079290dd73,0x30e0751c7c8e4263,0x4078bcf952cf1a62}, + {0xa19ffba37095d58a,0x9d164dabb30dff6a,0x16de88d2bac7642a,0x8232b5dca704cbcd}, + {0x329dfc2b2636492c,0xf0397ad762a31307,0x78adfe730ebe751e,0x5783b8d9d2f05dfd}, + {0xf2d6e8a736f23aa1,0xe2102f9bd2267093,0xdf2af690beecc500,0x11398c83a817f593}, + {0xd46565aaafab2385,0xddff3f9a0b99928d,0x5eb2072a49c5a5ab,0x53a03f6a8eb6a094}, + {0x57fb689ec7092868,0xc2040eb173de1a44,0x810031fb7b19e630,0x53960a9b3b1ef568}, + {0x40007920454fbf71,0xac025a589e98d1ef,0x9e256036a7fbd143,0xc13cf073bd649440}, + {0xd06cd6829f0fea3d,0x2a51b1d71d1ac07b,0x3546a5854571bbc6,0xc30b6bf46c0b42fe}, + {0x62488646a13da231,0xe28973393fb6f682,0x9ed13dc9f5432f8f,0x31b84f2be241c94e}, + {0x9bb19ea5428d66ae,0xe0080b8616f3babc,0x9610055711788ae5,0x7652d184a46c90fe}, + {0x112c63f926d9850e,0xe5905a268850e663,0xb9fd3996e6d72608,0xa7aa33543146d58a}, + {0x77de728df392f575,0x637633946129f8e6,0x72a867e08e3bfce6,0x754f7149e15a365b}, + {0x3511c4139b98679f,0x56a8a361da8cbe81,0x2a34d15423a9eb45,0x82ae1da57cd32e57}, + {0xcb3ecb886171f719,0xfcbf82d884e8e020,0xc6d2502bd1e6f6cf,0x80bb7b1db5c2a777}, + {0x81b8745892f03d2d,0xbc5f38b14116148b,0x4b6d0194055b86d8,0x241dbd17e3eb4ba9}, + {0x5bbc585152fcd142,0x930f31c230a2050e,0xabf51e10a3e969e5,0x72a0a1c90ead638e}, + {0xcadb18ff93f7f93e,0x1b8e009b5719bf82,0x743c0ab2c8bc284a,0x7144a02ff1130223}, + {0x41b95e62522de019,0xcd3465a01c9b93fb,0x236600ff15e70ef3,0x3658cd0c29ea6f20}, + {0xb9c59bf0b27dc282,0x47955c29304112de,0x3f16c72af19bcb3f,0xa0e568c9c5397d69}, + {0x9251cf7a209add18,0x8e3a95a336fe4170,0xf28c14a751527126,0xb3d3a9a208590971}, + {0x5b129f35a37c28ff,0xe3f8ba25b41817b9,0x200b734d2501265f,0x52344985724cceca}, + {0xa8e27fd1e60dffab,0xa8ea4523b64f5aa4,0xa475b8437f8165a1,0xd644c1691c3c7548}, + {0x5ddae2f669e64957,0x1fcef31f0b9af756,0x3e6da61c7980074e,0x206f828242ab6764}, + {0x33144ea9f76bb631,0x9f36e03e21fa3065,0xfe08e97dc86bceb2,0x640b723c98cd7479}, + {0x1636152634146114,0xc18c0793a80805cd,0x2b106edd3834043c,0x4191bf5c7fbacdf8}, + {0x429dddfd03ef7bc4,0x4db9b9d6da197cd3,0xe74baaea7f22abc0,0x4364ff1e20f72e64}, + {0xca8a9a678e94da68,0x6535f14dbed15563,0x98f34f0a20bd3f3c,0xd12c84164701e27f}, + {0xc02c8d4c379b7ce5,0x7069499c81e1f16e,0x9bf97727b1a05c04,0xf27fa10bb0a78610}, + {0x4cf536f0cf11a349,0xbd9dfa2a6eb41391,0x565f1d6e23bbbc0d,0xc76bbb697c18cf7f}, + {0xa17601bde8ac478c,0x8db87c51403e365d,0x4088a87a96d9c622,0x31f82a7918dd0d06}, + {0x29ee14687120f04e,0xfea2e736c3636d5c,0x7f8c89823855588a,0xf0da86215a008e8c}, + {0xdd645ec1d816c223,0x0aa7edbc5ba5d0cf,0xfced1c8e126396e5,0x201b07bc6f65eddb}, + {0xfb25e20cd48f4855,0xa8b3d1435e85371a,0x3ee9acb3f939329e,0xd075efbe502f25a4}, + {0x0541c9b35049c704,0x94986dc9cd668f39,0x17f4cfb2726cd68b,0x508c14a670636ed4}, + {0xa2b783ac55d68039,0xc130ab2d841d773e,0xd6d29b14f588465d,0xb790ad979cce43f8}, + {0x4f8ce0df03c43b98,0xbbda15818c06d7a2,0x380dd95f0f042fdb,0x05f429bccfb597f3}, + {0xc742e63ad5c5f5e6,0xcbcb225fbbbe33e2,0xa8edf59089d52ced,0xa0e788a338b45f4d}, + {0x20e95da4bdb0c82f,0x3e63b532cc85e2d9,0x163e3d2b90d4ddaf,0xc71593e07530219a}, + {0x7992357ab8d37b59,0x4aea96f315f3c064,0x1ba04f945b33146b,0xf65bed5593247ff4}, + {0x2d4ad59bdce5563d,0x3a24253d449dc88d,0x41c7ffbd062c28f4,0x42734ae219aa9361}, + {0x644204f2ea9b71e3,0xe551983ade3b5122,0x1bc727382db55ea1,0xe276d03e4bd6fc9a}, + {0xfb20c1e51a924e81,0x2f795f1d4507decd,0x154de4d0aca02046,0x72ddcd99451381dd}, + {0xc09ac8020e255c2b,0xa4eff29a2c29d3f3,0x7977c4f4c2f24381,0x349ff7a6efa4d791}, + {0xea5d2cd9592cb4e6,0xf63dcd3ff0c8104a,0x66d7254c1252ca0d,0x822791068962c667}, + {0x7b9c477dde2ad4a4,0xd3460c638eb797b0,0x1889eaef7acad771,0xb23db19bd8554e11}, + {0x6f1c469240cd647f,0x31825907e279b274,0xb97cebbf2c37c29e,0x74ce50e87690b22e}, + {0xfb92d64637ac0508,0x97999c37b92d0720,0xa23a9e76c1578849,0x66aa9c79979e14fb}, + {0xcf78e912e65a8877,0xb7dcb878bdeec090,0xe678ac56695a99fc,0x0338870b34c11cee}, + {0x5529c228e771c374,0xd8ab910e6e0a23f9,0xcd86f7b11bf07839,0xe3358c0867358f64}, + {0x7c0e69e5db7dc1c3,0x355a9bbca9523a64,0x86985b53d32a3f4b,0xc715ea89b184099b}, + {0xac499c49b8a4cdc4,0x22485e1df13ea826,0xf91367c2ad8807da,0x863b3b9193879ebd}, + {0x8086427544d93f9b,0xf378d24905271a4e,0x8a2211f2e881884b,0x27f11aae6fbdeb19}, + {0xd4d702e312991728,0xd57d86c18df5deb9,0x68b550520aac07f8,0x6163e0c25242d715}, + {0x0484539b5bd55737,0x69b34b6b4664d575,0xcafeeeea78048b31,0x25a0aca017ec768d}, + {0x955f03fc32b86250,0xb3ed04233eabbafd,0xb4da5d10fb30568d,0xa1d5c520656d8e7f}, + {0x18e6772ac0c7b0b5,0x1e8c41bfa134bd72,0x36b1b28f157526b2,0xf5ac9222151e43e1}, + {0xb500af50c3647566,0x181d28f85aca7575,0x9a16455dfd6341a1,0xc6d058b2c1e37c22}, + {0x01b46ff0be3c6ef8,0x7f5abf4a7e4a72fe,0xe18780f7372db81b,0x91d1172dbd7c1d3b}, + {0x62e68a7598567ebd,0x4654b8ed6f377911,0x051bf02a5685ca63,0xd08b010696df1fa9}, + {0x656ce860674f0d36,0x8bcbf7bc1ef730bf,0x00a0260df392d280,0x33930145fd64eecf}, + {0x17743293297fc288,0x5b59ca56522bb36a,0xe58ef14098fd4053,0x7444ed68eb16e657}, + {0x31beae245608121f,0xea349f5c00e7cc25,0xf076aacf6db8c528,0x13c58f0b1e99ac1a}, + {0x910f9e30c8455d7b,0xc1ebc494beb98220,0x201a3557ec66e851,0x610dd21bbd2f6b9f}, + {0x317d8fa79aa99e03,0x7b670f771c4590dd,0x77052e1a54ac4638,0x17309eb8c690df96}, + {0xddae9fdfd80030d4,0x84daf3404eae25e8,0xe93997a2e172c485,0x51f2159ecb7b5e41}, + {0x9f02a3e12da8bc2c,0x1c746f4b943dc8e5,0xb31951aeeaac4e5e,0x0128a606643b4341}, + {0xebd158803af98ce2,0x08e82db8ead7c10b,0xba172e80caa61667,0xf61ff900e1918b8a}, + {0x8c3c570f9ffae2bc,0xff0827921f27e4f5,0x6256d4a0913919b5,0xc1f4fcc60f17957e}, + {0x648ade6556f9d114,0xf2e85e1746058ffe,0xc9605989ede623cf,0xf3d09098541725a9}, + {0xc57b49460d911255,0xc0767005f4affb44,0x486c21436602612a,0x87617ddb2a9643c0}, + {0xc2038cd71c6d3ead,0x8fe1e58a5096a181,0x51cde6590d0f6b27,0xf59bf938475aa39a}, + {0x9d8138454badbf16,0xaf8306904b15d8a8,0x83bd9fd79c159b39,0xb85db82acdbbf3ae}, + {0x560807274e8b13db,0xb33b8a036f1617ca,0x72bc05868c923532,0xb7b8ee25c3388851}, + {0xc042df127c4f6747,0x704ed715ba3ca7d4,0x678f93c55bc0c5d2,0xd2ee482f0bfe6c9a}, + {0xbd60c5ba33d87b10,0x6c2ff096c60536d6,0x0ce4b4b8c86a8f5b,0x86a0bcebf81d6e4d}, + {0xf9384ef3a44799c2,0x8b78ec1c676a7fcd,0x5f7c3edb312b00da,0x2390763c1712af67}, +}; + +#define GF_exp_invmer_e_1 AIMER_NAMESPACE(GF_exp_invmer_e_1) +void GF_exp_invmer_e_1(GF out, const GF in); +#define GF_exp_invmer_e_2 AIMER_NAMESPACE(GF_exp_invmer_e_2) +void GF_exp_invmer_e_2(GF out, const GF in); +#define GF_exp_invmer_e_3 AIMER_NAMESPACE(GF_exp_invmer_e_3) +void GF_exp_invmer_e_3(GF out, const GF in); +#define GF_exp_mer_e_star AIMER_NAMESPACE(GF_exp_mer_e_star) +void GF_exp_mer_e_star(GF out, const GF in); + +#define generate_matrices_L_and_U AIMER_NAMESPACE(generate_matrices_L_and_U) +void generate_matrices_L_and_U( + GF matrix_L[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF matrix_U[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define generate_matrix_LU AIMER_NAMESPACE(generate_matrix_LU) +void generate_matrix_LU(GF matrix_A[AIM2_NUM_INPUT_SBOX][AIM2_NUM_BITS_FIELD], + GF vector_b, + const uint8_t iv[AIM2_IV_SIZE]); + +#define aim2_sbox_outputs AIMER_NAMESPACE(aim2_sbox_outputs) +void aim2_sbox_outputs(GF sbox_outputs[AIM2_NUM_INPUT_SBOX], const GF pt); + +#define aim2 AIMER_NAMESPACE(aim2) +void aim2(uint8_t ct[AIM2_NUM_BYTES_FIELD], + const uint8_t pt[AIM2_NUM_BYTES_FIELD], + const uint8_t iv[AIM2_IV_SIZE]); + +#endif // AIM2_H diff --git a/crypto_sign/aimer256f/m4speed/api.h b/crypto_sign/aimer256f/m4speed/api.h new file mode 100644 index 00000000..2bc176d6 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 64 +#define CRYPTO_SECRETKEYBYTES 96 +#define CRYPTO_BYTES 25120 +#define CRYPTO_ALGNAME "aimer256f" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer256f/m4speed/field.c b/crypto_sign/aimer256f/m4speed/field.c new file mode 100644 index 00000000..5c27f63a --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/field.c @@ -0,0 +1,608 @@ +// SPDX-License-Identifier: MIT + +#include "field.h" +#include +#include + +#define mask_64 0x00000000ffffffff +#define mask_final 0x000000000000ffff + +#define mask0_64 0x000000ff000000ff +#define mask0 0x000000ff + +#define mask1_64 0x000f000f000f000f +#define mask1 0x000f000f + +#define mask2_64 0x0303030303030303 +#define mask2 0x03030303 + +#define mask3_64 0x1111111111111111 +#define mask3 0x11111111 + +#define zero_padding(x0, mask1, mask2, mask3) \ + x0 = (x0 | (x0 << 12)) & mask1; \ + x0 = (x0 | (x0 << 6 )) & mask2; \ + x0 = (x0 | (x0 << 3 )) & mask3; + +#define inv_zero_padding(x0, mask0, mask1, mask2, mask_final) \ + x0 = (x0 | (x0 >> 3 )) & mask2; \ + x0 = (x0 | (x0 >> 6 )) & mask1; \ + x0 = (x0 | (x0 >> 12)) & mask0; \ + x0 = (x0 | (x0 >> 24)) & mask_final; + +void GF_mul(GF c, const GF a, const GF b) +{ + uint64_t t[4] = {0,}; + uint64_t temp[8] = {0,}; + uint64_t sub[10] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + sub[2] = a[2] ^ a[3]; + sub[3] = b[2] ^ b[3]; + sub[4] = a[0] ^ a[2]; + sub[5] = a[1] ^ a[3]; + sub[6] = b[0] ^ b[2]; + sub[7] = b[1] ^ b[3]; + sub[8] = sub[4] ^ sub[5]; + sub[9] = sub[6] ^ sub[7]; + + poly64_mul(&a[0], &b[0], &t[0], &temp[0]); + poly64_mul(&a[1], &b[1], &t[2], &t[1]); + t[0] ^= t[1]; + + poly64_mul(&a[2], &b[2], &t[3], &t[1]); + t[1] ^= t[2]; + + poly64_mul(&a[3], &b[3], &temp[7], &t[2]); + t[2] ^= t[3]; + + temp[6] = temp[7] ^ t[2]; + temp[3] = t[2] ^ t[1]; + temp[2] = t[1] ^ t[0]; + temp[1] = t[0] ^ temp[0]; + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul(&sub[2], &sub[3], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[6] ^= t[1]; + + temp[5] = temp[7] ^ temp[3]; + temp[4] = temp[6] ^ temp[2]; + temp[3] ^= temp[1]; + temp[2] ^= temp[0]; + + poly64_mul(&sub[4], &sub[6], &t[1], &t[0]); + poly64_mul(&sub[5], &sub[7], &t[3], &t[2]); + t[1] ^= t[2]; + t[2] = t[1] ^ t[3]; + t[1] ^= t[0]; + + temp[2] ^= t[0]; + temp[3] ^= t[1]; + temp[4] ^= t[2]; + temp[5] ^= t[3]; + + poly64_mul(&sub[8], &sub[9], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[4] ^ ((temp[7] >> 54) ^ (temp[7] >> 59) ^ (temp[7] >> 62)); + + c[3] = temp[3] ^ temp[7]; + c[3] ^= (temp[7] << 10) | (temp[6] >> 54); + c[3] ^= (temp[7] << 5) | (temp[6] >> 59); + c[3] ^= (temp[7] << 2) | (temp[6] >> 62); + + c[2] = temp[2] ^ temp[6]; + c[2] ^= (temp[6] << 10) | (temp[5] >> 54); + c[2] ^= (temp[6] << 5) | (temp[5] >> 59); + c[2] ^= (temp[6] << 2) | (temp[5] >> 62); + + c[1] = temp[1] ^ temp[5]; + c[1] ^= (temp[5] << 10) | (t[0] >> 54); + c[1] ^= (temp[5] << 5) | (t[0] >> 59); + c[1] ^= (temp[5] << 2) | (t[0] >> 62); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 10); + c[0] ^= (t[0] << 5); + c[0] ^= (t[0] << 2); +} + +void GF_mul_add(GF c, const GF a, const GF b) +{ + uint64_t t[4] = {0,}; + uint64_t temp[8] = {0,}; + uint64_t sub[10] = {0,}; + + sub[0] = a[0] ^ a[1]; + sub[1] = b[0] ^ b[1]; + sub[2] = a[2] ^ a[3]; + sub[3] = b[2] ^ b[3]; + sub[4] = a[0] ^ a[2]; + sub[5] = a[1] ^ a[3]; + sub[6] = b[0] ^ b[2]; + sub[7] = b[1] ^ b[3]; + sub[8] = sub[4] ^ sub[5]; + sub[9] = sub[6] ^ sub[7]; + + poly64_mul(&a[0], &b[0], &t[0], &temp[0]); + poly64_mul(&a[1], &b[1], &t[2], &t[1]); + t[0] ^= t[1]; + + poly64_mul(&a[2], &b[2], &t[3], &t[1]); + t[1] ^= t[2]; + + poly64_mul(&a[3], &b[3], &temp[7], &t[2]); + t[2] ^= t[3]; + + temp[6] = temp[7] ^ t[2]; + temp[3] = t[2] ^ t[1]; + temp[2] = t[1] ^ t[0]; + temp[1] = t[0] ^ temp[0]; + + poly64_mul(&sub[0], &sub[1], &t[1], &t[0]); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul(&sub[2], &sub[3], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[6] ^= t[1]; + + temp[5] = temp[7] ^ temp[3]; + temp[4] = temp[6] ^ temp[2]; + temp[3] ^= temp[1]; + temp[2] ^= temp[0]; + + poly64_mul(&sub[4], &sub[6], &t[1], &t[0]); + poly64_mul(&sub[5], &sub[7], &t[3], &t[2]); + t[1] ^= t[2]; + t[2] = t[1] ^ t[3]; + t[1] ^= t[0]; + + temp[2] ^= t[0]; + temp[3] ^= t[1]; + temp[4] ^= t[2]; + temp[5] ^= t[3]; + + poly64_mul(&sub[8], &sub[9], &t[1], &t[0]); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[4] ^ ((temp[7] >> 54) ^ (temp[7] >> 59) ^ (temp[7] >> 62)); + + c[3] ^= temp[3] ^ temp[7]; + c[3] ^= (temp[7] << 10) | (temp[6] >> 54); + c[3] ^= (temp[7] << 5) | (temp[6] >> 59); + c[3] ^= (temp[7] << 2) | (temp[6] >> 62); + + c[2] ^= temp[2] ^ temp[6]; + c[2] ^= (temp[6] << 10) | (temp[5] >> 54); + c[2] ^= (temp[6] << 5) | (temp[5] >> 59); + c[2] ^= (temp[6] << 2) | (temp[5] >> 62); + + c[1] ^= temp[1] ^ temp[5]; + c[1] ^= (temp[5] << 10) | (t[0] >> 54); + c[1] ^= (temp[5] << 5) | (t[0] >> 59); + c[1] ^= (temp[5] << 2) | (t[0] >> 62); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 10); + c[0] ^= (t[0] << 5); + c[0] ^= (t[0] << 2); +} + +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t temp_c2 = 0; + uint64_t temp_c3 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 4, index >>= 4, b_ptr += 4) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + temp_c2 ^= (b_ptr[0][2] & mask); + temp_c3 ^= (b_ptr[0][3] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + temp_c2 ^= (b_ptr[1][2] & mask); + temp_c3 ^= (b_ptr[1][3] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + temp_c2 ^= (b_ptr[2][2] & mask); + temp_c3 ^= (b_ptr[2][3] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + temp_c2 ^= (b_ptr[3][2] & mask); + temp_c3 ^= (b_ptr[3][3] & mask); + } + } + c[0] = temp_c0; + c[1] = temp_c1; + c[2] = temp_c2; + c[3] = temp_c3; +} + +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]) +{ + const uint64_t *a_ptr = a; + const GF *b_ptr = b; + + uint64_t temp_c0 = 0; + uint64_t temp_c1 = 0; + uint64_t temp_c2 = 0; + uint64_t temp_c3 = 0; + uint64_t mask; + for (size_t i = AIM2_NUM_WORDS_FIELD; i; --i, ++a_ptr) + { + uint64_t index = *a_ptr; + for (size_t j = AIM2_NUM_BITS_WORD; j; j -= 4, index >>= 4, b_ptr += 4) + { + mask = -(index & 1); + temp_c0 ^= (b_ptr[0][0] & mask); + temp_c1 ^= (b_ptr[0][1] & mask); + temp_c2 ^= (b_ptr[0][2] & mask); + temp_c3 ^= (b_ptr[0][3] & mask); + + mask = -((index >> 1) & 1); + temp_c0 ^= (b_ptr[1][0] & mask); + temp_c1 ^= (b_ptr[1][1] & mask); + temp_c2 ^= (b_ptr[1][2] & mask); + temp_c3 ^= (b_ptr[1][3] & mask); + + mask = -((index >> 2) & 1); + temp_c0 ^= (b_ptr[2][0] & mask); + temp_c1 ^= (b_ptr[2][1] & mask); + temp_c2 ^= (b_ptr[2][2] & mask); + temp_c3 ^= (b_ptr[2][3] & mask); + + mask = -((index >> 3) & 1); + temp_c0 ^= (b_ptr[3][0] & mask); + temp_c1 ^= (b_ptr[3][1] & mask); + temp_c2 ^= (b_ptr[3][2] & mask); + temp_c3 ^= (b_ptr[3][3] & mask); + } + } + c[0] ^= temp_c0; + c[1] ^= temp_c1; + c[2] ^= temp_c2; + c[3] ^= temp_c3; +} + +static void poly64_mul_s(uint64_t *z1, uint64_t *z0, uint64_t x, uint64_t y) +{ + // x_low + uint32_t x4 = x >> 32; + + uint32_t x0 = x & mask_64; + uint32_t x1 = (x0 >> 8) & mask0; + uint32_t x2 = (x0 >> 16) & mask0; + uint32_t x3 = (x0 >> 24) & mask0; + x0 &= mask0; + + // x_high + uint32_t x5 = (x4 >> 8) & mask0; + uint32_t x6 = (x4 >> 16) & mask0; + uint32_t x7 = (x4 >> 24) & mask0; + x4 &= mask0; + + // y_low + uint32_t y4 = y >> 32; + + uint32_t y0 = y & mask_64; + uint32_t y1 = (y0 >> 8) & mask0; + uint32_t y2 = (y0 >> 16) & mask0; + uint32_t y3 = (y0 >> 24) & mask0; + y0 &= mask0; + + // y_high + uint32_t y5 = (y4 >> 8) & mask0; + uint32_t y6 = (y4 >> 16) & mask0; + uint32_t y7 = (y4 >> 24) & mask0; + y4 &= mask0; + + // x padding + zero_padding(x0, mask1, mask2, mask3); + zero_padding(x1, mask1, mask2, mask3); + zero_padding(x2, mask1, mask2, mask3); + zero_padding(x3, mask1, mask2, mask3); + zero_padding(x4, mask1, mask2, mask3); + zero_padding(x5, mask1, mask2, mask3); + zero_padding(x6, mask1, mask2, mask3); + zero_padding(x7, mask1, mask2, mask3); + + // y padding + zero_padding(y0, mask1, mask2, mask3); + zero_padding(y1, mask1, mask2, mask3); + zero_padding(y2, mask1, mask2, mask3); + zero_padding(y3, mask1, mask2, mask3); + zero_padding(y4, mask1, mask2, mask3); + zero_padding(y5, mask1, mask2, mask3); + zero_padding(y6, mask1, mask2, mask3); + zero_padding(y7, mask1, mask2, mask3); + + //x0-3 * y0-3 + uint64_t a0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t a1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + a0 ^= (a1 << 32); + a1 = a1 >> 32; + a1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t a2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + a1 ^= (a2 << 32); + a2 = a2 >> 32; + a2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t a3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + a2 ^= (a3 << 32); + a3 = a3 >> 32; + + a3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + //x4-7 * y4-7 + uint64_t b0 = ((uint64_t)x4 * (uint64_t)y4) & mask3_64; + uint64_t b1 = ((((uint64_t)x4 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y4) & mask3_64)); + b0 ^= (b1 << 32); + b1 = b1 >> 32; + b1 ^= ((((uint64_t)x4 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y4) & mask3_64)); + + uint64_t b2 = ((((uint64_t)x4 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x5 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y5) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y4) & mask3_64)); + b1 ^= (b2 << 32); + b2 = b2 >> 32; + b2 ^= ((((uint64_t)x5 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x6 * (uint64_t)y6) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y5) & mask3_64)); + + uint64_t b3 = ((((uint64_t)x6 * (uint64_t)y7) & mask3_64) ^ + (((uint64_t)x7 * (uint64_t)y6) & mask3_64)); + b2 ^= (b3 << 32); + b3 = b3 >> 32; + + b3 ^= ((uint64_t)x7 * (uint64_t)y7) & mask3_64; + + //middle part + x0 ^= x4; + x1 ^= x5; + x2 ^= x6; + x3 ^= x7; + + y0 ^= y4; + y1 ^= y5; + y2 ^= y6; + y3 ^= y7; + + uint64_t c0 = ((uint64_t)x0 * (uint64_t)y0) & mask3_64; + uint64_t c1 = ((((uint64_t)x0 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y0) & mask3_64)); + c0 ^= (c1 << 32); + c1 = c1 >> 32; + c1 ^= ((((uint64_t)x0 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y0) & mask3_64)); + + uint64_t c2 = ((((uint64_t)x0 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x1 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y1) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y0) & mask3_64)); + c1 ^= (c2 << 32); + c2 = c2 >> 32; + c2 ^= ((((uint64_t)x1 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x2 * (uint64_t)y2) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y1) & mask3_64)); + + uint64_t c3 = ((((uint64_t)x2 * (uint64_t)y3) & mask3_64) ^ + (((uint64_t)x3 * (uint64_t)y2) & mask3_64)); + c2 ^= (c3 << 32); + c3 = c3 >> 32; + + c3 ^= ((uint64_t)x3 * (uint64_t)y3) & mask3_64; + + c0 = c0 ^ a0 ^ b0; + c1 = c1 ^ a1 ^ b1; + c2 = c2 ^ a2 ^ b2; + c3 = c3 ^ a3 ^ b3; + + a2 ^= c0; + a3 ^= c1; + b0 ^= c2; + b1 ^= c3; + + // result inv_padding + inv_zero_padding(a0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(a3, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b0, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b1, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b2, mask0_64, mask1_64, mask2_64, mask_final); + inv_zero_padding(b3, mask0_64, mask1_64, mask2_64, mask_final); + + *z0 = a0 | (a1 << 16) | (a2 << 32) | (a3 << 48); + *z1 = b0 | (b1 << 16) | (b2 << 32) | (b3 << 48); +} + +void GF_mul_s(GF c, const GF a, const GF b) +{ + uint64_t t[4] = {0,}; + uint64_t add[4] = {0,}; + uint64_t temp[8] = {0,}; + + poly64_mul_s(&t[0], &temp[0], a[0], b[0]); + poly64_mul_s(&t[2], &t[1], a[1], b[1]); + t[0] ^= t[1]; + + poly64_mul_s(&t[3], &t[1], a[2], b[2]); + t[1] ^= t[2]; + + poly64_mul_s(&temp[7], &t[2], a[3], b[3]); + t[2] ^= t[3]; + + temp[6] = temp[7] ^ t[2]; + temp[3] = t[2] ^ t[1]; + temp[2] = t[1] ^ t[0]; + temp[1] = t[0] ^ temp[0]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[2] ^ a[3]), (b[2] ^ b[3])); + temp[3] ^= t[0]; + temp[6] ^= t[1]; + + temp[5] = temp[7] ^ temp[3]; + temp[4] = temp[6] ^ temp[2]; + temp[3] ^= temp[1]; + temp[2] ^= temp[0]; + + add[0] = a[0] ^ a[2]; + add[1] = a[1] ^ a[3]; + add[2] = b[0] ^ b[2]; + add[3] = b[1] ^ b[3]; + poly64_mul_s(&t[1], &t[0], add[0], add[2]); + poly64_mul_s(&t[3], &t[2], add[1], add[3]); + t[1] ^= t[2]; + t[2] = t[1] ^ t[3]; + t[1] ^= t[0]; + + temp[2] ^= t[0]; + temp[3] ^= t[1]; + temp[4] ^= t[2]; + temp[5] ^= t[3]; + + poly64_mul_s(&t[1], &t[0], (add[0] ^ add[1]), (add[2] ^ add[3])); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[4] ^ ((temp[7] >> 54) ^ (temp[7] >> 59) ^ (temp[7] >> 62)); + + c[3] = temp[3] ^ temp[7]; + c[3] ^= (temp[7] << 10) | (temp[6] >> 54); + c[3] ^= (temp[7] << 5) | (temp[6] >> 59); + c[3] ^= (temp[7] << 2) | (temp[6] >> 62); + + c[2] = temp[2] ^ temp[6]; + c[2] ^= (temp[6] << 10) | (temp[5] >> 54); + c[2] ^= (temp[6] << 5) | (temp[5] >> 59); + c[2] ^= (temp[6] << 2) | (temp[5] >> 62); + + c[1] = temp[1] ^ temp[5]; + c[1] ^= (temp[5] << 10) | (t[0] >> 54); + c[1] ^= (temp[5] << 5) | (t[0] >> 59); + c[1] ^= (temp[5] << 2) | (t[0] >> 62); + + c[0] = temp[0] ^ t[0]; + c[0] ^= (t[0] << 10); + c[0] ^= (t[0] << 5); + c[0] ^= (t[0] << 2); +} + +void GF_mul_add_s(GF c, const GF a, const GF b) +{ + uint64_t t[4] = {0,}; + uint64_t add[4] = {0,}; + uint64_t temp[8] = {0,}; + + poly64_mul_s(&t[0], &temp[0], a[0], b[0]); + poly64_mul_s(&t[2], &t[1], a[1], b[1]); + t[0] ^= t[1]; + + poly64_mul_s(&t[3], &t[1], a[2], b[2]); + t[1] ^= t[2]; + + poly64_mul_s(&temp[7], &t[2], a[3], b[3]); + t[2] ^= t[3]; + + temp[6] = temp[7] ^ t[2]; + temp[3] = t[2] ^ t[1]; + temp[2] = t[1] ^ t[0]; + temp[1] = t[0] ^ temp[0]; + + poly64_mul_s(&t[1], &t[0], (a[0] ^ a[1]), (b[0] ^ b[1])); + temp[1] ^= t[0]; + temp[2] ^= t[1]; + + poly64_mul_s(&t[1], &t[0], (a[2] ^ a[3]), (b[2] ^ b[3])); + temp[3] ^= t[0]; + temp[6] ^= t[1]; + + temp[5] = temp[7] ^ temp[3]; + temp[4] = temp[6] ^ temp[2]; + temp[3] ^= temp[1]; + temp[2] ^= temp[0]; + + add[0] = a[0] ^ a[2]; + add[1] = a[1] ^ a[3]; + add[2] = b[0] ^ b[2]; + add[3] = b[1] ^ b[3]; + poly64_mul_s(&t[1], &t[0], add[0], add[2]); + poly64_mul_s(&t[3], &t[2], add[1], add[3]); + t[1] ^= t[2]; + t[2] = t[1] ^ t[3]; + t[1] ^= t[0]; + + temp[2] ^= t[0]; + temp[3] ^= t[1]; + temp[4] ^= t[2]; + temp[5] ^= t[3]; + + poly64_mul_s(&t[1], &t[0], (add[0] ^ add[1]), (add[2] ^ add[3])); + temp[3] ^= t[0]; + temp[4] ^= t[1]; + + t[0] = temp[4] ^ ((temp[7] >> 54) ^ (temp[7] >> 59) ^ (temp[7] >> 62)); + + c[3] ^= temp[3] ^ temp[7]; + c[3] ^= (temp[7] << 10) | (temp[6] >> 54); + c[3] ^= (temp[7] << 5) | (temp[6] >> 59); + c[3] ^= (temp[7] << 2) | (temp[6] >> 62); + + c[2] ^= temp[2] ^ temp[6]; + c[2] ^= (temp[6] << 10) | (temp[5] >> 54); + c[2] ^= (temp[6] << 5) | (temp[5] >> 59); + c[2] ^= (temp[6] << 2) | (temp[5] >> 62); + + c[1] ^= temp[1] ^ temp[5]; + c[1] ^= (temp[5] << 10) | (t[0] >> 54); + c[1] ^= (temp[5] << 5) | (t[0] >> 59); + c[1] ^= (temp[5] << 2) | (t[0] >> 62); + + c[0] ^= temp[0] ^ t[0]; + c[0] ^= (t[0] << 10); + c[0] ^= (t[0] << 5); + c[0] ^= (t[0] << 2); +} diff --git a/crypto_sign/aimer256f/m4speed/field.h b/crypto_sign/aimer256f/m4speed/field.h new file mode 100644 index 00000000..089ad983 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/field.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +#ifndef FIELD_H +#define FIELD_H + +#include "params.h" +#include +#include + +typedef uint64_t GF[4]; + +#define poly64_mul AIMER_NAMESPACE(poly64_mul) +void poly64_mul(const uint64_t *a, const uint64_t *b, uint64_t *c1, uint64_t *c0); +#define GF_set0 AIMER_NAMESPACE(GF_set0) +void GF_set0(GF a); +#define GF_copy AIMER_NAMESPACE(GF_copy) +void GF_copy(GF out, const GF in); +#define GF_to_bytes AIMER_NAMESPACE(GF_to_bytes) +void GF_to_bytes(uint8_t *out, const GF in); +#define GF_from_bytes AIMER_NAMESPACE(GF_from_bytes) +void GF_from_bytes(GF out, const uint8_t *in); + +#define GF_add AIMER_NAMESPACE(GF_add) +void GF_add(GF c, const GF a, const GF b); +#define GF_mul AIMER_NAMESPACE(GF_mul) +void GF_mul(GF c, const GF a, const GF b); +#define GF_mul_add AIMER_NAMESPACE(GF_mul_add) +void GF_mul_add(GF c, const GF a, const GF b); +#define GF_transposed_matmul AIMER_NAMESPACE(GF_transposed_matmul) +void GF_transposed_matmul(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); +#define GF_transposed_matmul_add AIMER_NAMESPACE(GF_transposed_matmul_add) +void GF_transposed_matmul_add(GF c, const GF a, const GF b[AIM2_NUM_BITS_FIELD]); + +#define GF_mul_s AIMER_NAMESPACE(GF_mul_s) +void GF_mul_s(GF c, const GF a, const GF b); +#define GF_mul_add_s AIMER_NAMESPACE(GF_mul_add_s) +void GF_mul_add_s(GF c, const GF a, const GF b); +#define GF_sqr_s AIMER_NAMESPACE(GF_sqr_s) +void GF_sqr_s(GF c, const GF a); + +#endif // FIELD_H diff --git a/crypto_sign/aimer256f/m4speed/hash.c b/crypto_sign/aimer256f/m4speed/hash.c new file mode 120000 index 00000000..e3d8e7dd --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/hash.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4speed/hash.h b/crypto_sign/aimer256f/m4speed/hash.h new file mode 120000 index 00000000..0e0c3961 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/hash.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4speed/params.h b/crypto_sign/aimer256f/m4speed/params.h new file mode 100644 index 00000000..39714e9a --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer256f_m4speed_##s + +#define SECURITY_BITS 256 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 3 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 65 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer256f/m4speed/sign.c b/crypto_sign/aimer256f/m4speed/sign.c new file mode 100644 index 00000000..ff32211b --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/sign.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[0], mult_chk->x_shares[0]); + for (size_t i = 1; i < 11; i++) + { + GF_sqr_s(mult_chk->z_shares[0], mult_chk->z_shares[0]); + } + GF_mul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + GF_sqr_s(mult_chk->z_shares[2], mult_chk->x_shares[2]); + for (size_t i = 1; i < 7; i++) + { + GF_sqr_s(mult_chk->z_shares[2], mult_chk->z_shares[2]); + } + GF_mul_add(mult_chk->z_shares[2], mult_chk->x_shares[2], aim2_constants[2]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[2], + matrix_A[2]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE], + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE], + mult_chk_t mult_chk[AIMER_T][AIMER_N], + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const uint8_t *sk, const uint8_t *m, size_t mlen) +{ + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt + hash_init_prefix(&ctx, HASH_PREFIX_3); + hash_update(&ctx, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, random, SECURITY_BYTES); + hash_final(&ctx); + hash_squeeze(&ctx, sign->salt, AIMER_SALT_SIZE); + + // generate root seeds and expand seed trees + for (size_t rep = 0; rep < AIMER_T; rep++) + { + hash_squeeze(&ctx, nodes[rep][0], AIMER_SEED_SIZE); + } + expand_trees(nodes, sign->salt); + hash_ctx_release(&ctx); + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // initialize adjustment values + tape_t delta, tape; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + commit_and_expand_tape(&tape, commits[rep][party], &ctx_precom, + nodes[rep][party + AIMER_N - 1], rep, party); + hash_update(&ctx, commits[rep][party], AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + GF_set0(mult_chk[rep][party].x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], sbox_outputs[2]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[2], delta.t_shares[2]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk[rep][party].x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk[rep][party].pt_share, tape.pt_share); + GF_copy(mult_chk[rep][party].x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk[rep][party].x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk[rep][party].x_shares[2], tape.t_shares[2]); + GF_copy(alpha_v_shares[rep][0][party], tape.a_share); + GF_copy(alpha_v_shares[rep][1][party], tape.c_share); + + aim2_mpc(&mult_chk[rep][party], + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_2_and_3(signature_t *sign, + GF alpha_v_shares[AIMER_T][2][AIMER_N], + const mult_chk_t mult_chk[AIMER_T][AIMER_N]) +{ + GF epsilons[AIMER_L + 1]; + + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + GF_set0(alpha); + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // alpha_share = a_share + sum x_share[i] * eps[i] + // v_share = c_share - pt_share * alpha + sum z_share[i] * eps[i] + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[rep][0][party], + mult_chk[rep][party].x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].z_shares[3], epsilons[3]); + + GF_add(alpha, alpha, alpha_v_shares[rep][0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[rep][1][party], + mult_chk[rep][party].pt_share, alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares[rep], + AIM2_NUM_BYTES_FIELD * 2 * AIMER_N); + } + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + hash_ctx_release(&ctx_e); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + hash_instance ctx; + signature_t *sign = (signature_t *)sig; + + ////////////////////////////////////////////////////////////////////////// + // Phase 1: Committing to the seeds and the execution views of parties. // + ////////////////////////////////////////////////////////////////////////// + + // nodes for seed trees + uint8_t nodes[AIMER_T][2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + // commitments for seeds + uint8_t commits[AIMER_T][AIMER_N][AIMER_COMMIT_SIZE]; + + // multiplication check inputs + mult_chk_t mult_chk[AIMER_T][AIMER_N]; + + // multiplication check outputs + GF alpha_v_shares[AIMER_T][2][AIMER_N]; + + // commitments for phase 1 + run_phase_1(sign, commits, nodes, mult_chk, alpha_v_shares, sk, m, mlen); + + ///////////////////////////////////////////////////////////////// + // Phase 2, 3: Challenging and committing to the simulation of // + // the multiplication checking protocol. // + ///////////////////////////////////////////////////////////////// + + // compute the commitment of phase 3 + run_phase_2_and_3(sign, alpha_v_shares, + (const mult_chk_t (*)[AIMER_N])mult_chk); + + ////////////////////////////////////////////////////// + // Phase 4: Challenging views of the MPC protocols. // + ////////////////////////////////////////////////////// + + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + ////////////////////////////////////////////////////// + // Phase 5: Opening the views of the MPC protocols. // + ////////////////////////////////////////////////////// + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes[rep], i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits[rep][i_bar], + AIMER_COMMIT_SIZE); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, + alpha_v_shares[rep][0][i_bar]); + } + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[2]); + GF_add(tape.t_shares[2], tape.t_shares[2], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer256f/m4speed/sign.h b/crypto_sign/aimer256f/m4speed/sign.h new file mode 120000 index 00000000..0cab7ef0 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4speed/tree.c b/crypto_sign/aimer256f/m4speed/tree.c new file mode 120000 index 00000000..0b937a00 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4speed/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4speed/tree.h b/crypto_sign/aimer256f/m4speed/tree.h new file mode 120000 index 00000000..9ccb9413 --- /dev/null +++ b/crypto_sign/aimer256f/m4speed/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4speed/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/__asm_field.S b/crypto_sign/aimer256f/m4stack/__asm_field.S new file mode 120000 index 00000000..445dedad --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer256f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/aim2.c b/crypto_sign/aimer256f/m4stack/aim2.c new file mode 120000 index 00000000..02a4b990 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/aim2.h b/crypto_sign/aimer256f/m4stack/aim2.h new file mode 120000 index 00000000..47e3f0c6 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/api.h b/crypto_sign/aimer256f/m4stack/api.h new file mode 120000 index 00000000..29d58337 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/api.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/field.c b/crypto_sign/aimer256f/m4stack/field.c new file mode 120000 index 00000000..7a96d5b1 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/field.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/field.h b/crypto_sign/aimer256f/m4stack/field.h new file mode 120000 index 00000000..d1f61f8f --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/field.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/hash.c b/crypto_sign/aimer256f/m4stack/hash.c new file mode 120000 index 00000000..e3d8e7dd --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/hash.h b/crypto_sign/aimer256f/m4stack/hash.h new file mode 120000 index 00000000..0e0c3961 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/params.h b/crypto_sign/aimer256f/m4stack/params.h new file mode 100644 index 00000000..3134a863 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer256f_m4stack_##s + +#define SECURITY_BITS 256 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 3 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 65 // number of parallel repetitions (Tau) +#define AIMER_N 16 // number of MPC parties (N) +#define AIMER_LOGN 4 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer256f/m4stack/sign.c b/crypto_sign/aimer256f/m4stack/sign.c new file mode 100644 index 00000000..601718ad --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/sign.c @@ -0,0 +1,654 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[0], mult_chk->x_shares[0]); + for (size_t i = 1; i < 11; i++) + { + GF_sqr_s(mult_chk->z_shares[0], mult_chk->z_shares[0]); + } + GF_mul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + GF_sqr_s(mult_chk->z_shares[2], mult_chk->x_shares[2]); + for (size_t i = 1; i < 7; i++) + { + GF_sqr_s(mult_chk->z_shares[2], mult_chk->z_shares[2]); + } + GF_mul_add(mult_chk->z_shares[2], mult_chk->x_shares[2], aim2_constants[2]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[2], + matrix_A[2]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], sbox_outputs[2]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[2], delta.t_shares[2]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_share, mult_chk.x_shares[3], epsilons[3]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[2]); + GF_add(tape.t_shares[2], tape.t_shares[2], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer256f/m4stack/sign.h b/crypto_sign/aimer256f/m4stack/sign.h new file mode 120000 index 00000000..c46aabad --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/tree.c b/crypto_sign/aimer256f/m4stack/tree.c new file mode 120000 index 00000000..09dffdf6 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer256f/m4stack/tree.h b/crypto_sign/aimer256f/m4stack/tree.h new file mode 120000 index 00000000..53fc8d73 --- /dev/null +++ b/crypto_sign/aimer256f/m4stack/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/__asm_field.S b/crypto_sign/aimer256s/m4speed/__asm_field.S new file mode 120000 index 00000000..445dedad --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/__asm_field.S @@ -0,0 +1 @@ +../../aimer256f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/aim2.c b/crypto_sign/aimer256s/m4speed/aim2.c new file mode 120000 index 00000000..02a4b990 --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/aim2.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/aim2.h b/crypto_sign/aimer256s/m4speed/aim2.h new file mode 120000 index 00000000..47e3f0c6 --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/aim2.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/api.h b/crypto_sign/aimer256s/m4speed/api.h new file mode 100644 index 00000000..b19100cf --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/api.h @@ -0,0 +1,44 @@ +/* +NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software. + +NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. + +You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States. +*/ + +#ifndef API_H +#define API_H + +#include "params.h" +#include +#include + +#define CRYPTO_PUBLICKEYBYTES 64 +#define CRYPTO_SECRETKEYBYTES 96 +#define CRYPTO_BYTES 17056 +#define CRYPTO_ALGNAME "aimer256s" + +#define crypto_sign_keypair AIMER_NAMESPACE(crypto_sign_keypair) +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + +#define crypto_sign_signature AIMER_NAMESPACE(crypto_sign_signature) +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign AIMER_NAMESPACE(crypto_sign) +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +#define crypto_sign_verify AIMER_NAMESPACE(crypto_sign_verify) +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk); + +#define crypto_sign_open AIMER_NAMESPACE(crypto_sign_open) +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + +#endif diff --git a/crypto_sign/aimer256s/m4speed/field.c b/crypto_sign/aimer256s/m4speed/field.c new file mode 120000 index 00000000..7a96d5b1 --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/field.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/field.h b/crypto_sign/aimer256s/m4speed/field.h new file mode 120000 index 00000000..d1f61f8f --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/field.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/hash.c b/crypto_sign/aimer256s/m4speed/hash.c new file mode 120000 index 00000000..48d0050f --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/hash.c @@ -0,0 +1 @@ +../../aimer192s/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/hash.h b/crypto_sign/aimer256s/m4speed/hash.h new file mode 120000 index 00000000..761cf62e --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/hash.h @@ -0,0 +1 @@ +../../aimer192s/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/params.h b/crypto_sign/aimer256s/m4speed/params.h new file mode 100644 index 00000000..97da601d --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/params.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer256s_m4speed_##s + +#define SECURITY_BITS 256 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 3 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 33 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#define PRE_TREE_IDX 256 + +#endif // PARAMS_H diff --git a/crypto_sign/aimer256s/m4speed/sign.c b/crypto_sign/aimer256s/m4speed/sign.c new file mode 100644 index 00000000..b983fafc --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/sign.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void commit_and_expand_tape_phase_3(tape_t *tape, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_skip_squeeze(&ctx, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[0], mult_chk->x_shares[0]); + for (size_t i = 1; i < 11; i++) + { + GF_sqr_s(mult_chk->z_shares[0], mult_chk->z_shares[0]); + } + GF_mul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + GF_sqr_s(mult_chk->z_shares[2], mult_chk->x_shares[2]); + for (size_t i = 1; i < 7; i++) + { + GF_sqr_s(mult_chk->z_shares[2], mult_chk->z_shares[2]); + } + GF_mul_add(mult_chk->z_shares[2], mult_chk->x_shares[2], aim2_constants[2]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[2], + matrix_A[2]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], sbox_outputs[2]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[2], delta.t_shares[2]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape_phase_3(&tape, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, + const hash_instance *ctx_tree, + const uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE]) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + memcpy(nodes, pre_nodes[rep][0], (2 * PRE_TREE_IDX - 1) * AIMER_SEED_SIZE); + expand_tree(nodes, ctx_tree, rep); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_share, mult_chk.x_shares[3], epsilons[3]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + uint8_t pre_nodes[AIMER_T][2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE] = {0,}; + + hash_instance ctx_tree; + hash_init_prefix(&ctx_tree, HASH_PREFIX_4); + hash_update(&ctx_tree, sign->salt, AIMER_SALT_SIZE); + + pre_expand_trees(pre_nodes, &ctx_tree, root_seeds); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_3(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + run_phase_1_to_5(sign, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, &ctx_tree, + (const uint8_t (*)[2 * PRE_TREE_IDX - 1][AIMER_SEED_SIZE])pre_nodes); + + hash_ctx_release(&ctx_tree); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature( + sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, + size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[2]); + GF_add(tape.t_shares[2], tape.t_shares[2], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify( + signature, CRYPTO_BYTES, + message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer256s/m4speed/sign.h b/crypto_sign/aimer256s/m4speed/sign.h new file mode 120000 index 00000000..ad443300 --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/sign.h @@ -0,0 +1 @@ +../../aimer128s/m4speed/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/tree.c b/crypto_sign/aimer256s/m4speed/tree.c new file mode 120000 index 00000000..b086c3b3 --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/tree.c @@ -0,0 +1 @@ +../../aimer128s/m4speed/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4speed/tree.h b/crypto_sign/aimer256s/m4speed/tree.h new file mode 120000 index 00000000..f3e5d95b --- /dev/null +++ b/crypto_sign/aimer256s/m4speed/tree.h @@ -0,0 +1 @@ +../../aimer128s/m4speed/tree.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/__asm_field.S b/crypto_sign/aimer256s/m4stack/__asm_field.S new file mode 120000 index 00000000..445dedad --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/__asm_field.S @@ -0,0 +1 @@ +../../aimer256f/m4speed/__asm_field.S \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/aim2.c b/crypto_sign/aimer256s/m4stack/aim2.c new file mode 120000 index 00000000..02a4b990 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/aim2.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/aim2.h b/crypto_sign/aimer256s/m4stack/aim2.h new file mode 120000 index 00000000..47e3f0c6 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/aim2.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/aim2.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/api.h b/crypto_sign/aimer256s/m4stack/api.h new file mode 120000 index 00000000..c93ab8de --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/api.h @@ -0,0 +1 @@ +../../aimer256s/m4speed/api.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/field.c b/crypto_sign/aimer256s/m4stack/field.c new file mode 120000 index 00000000..7a96d5b1 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/field.c @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/field.h b/crypto_sign/aimer256s/m4stack/field.h new file mode 120000 index 00000000..d1f61f8f --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/field.h @@ -0,0 +1 @@ +../../aimer256f/m4speed/field.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/hash.c b/crypto_sign/aimer256s/m4stack/hash.c new file mode 120000 index 00000000..e3d8e7dd --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/hash.c @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/hash.h b/crypto_sign/aimer256s/m4stack/hash.h new file mode 120000 index 00000000..0e0c3961 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/hash.h @@ -0,0 +1 @@ +../../aimer192f/m4speed/hash.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/params.h b/crypto_sign/aimer256s/m4stack/params.h new file mode 100644 index 00000000..63a4c90f --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/params.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +#ifndef PARAMS_H +#define PARAMS_H + +#define AIMER_NAMESPACE(s) samsungsds_aimer256s_m4stack_##s + +#define SECURITY_BITS 256 // security parameter +#define SECURITY_BYTES (SECURITY_BITS / 8) // byte size of security parameter + +#define AIM2_NUM_BITS_FIELD SECURITY_BITS // number of bits in field element +#define AIM2_NUM_BYTES_FIELD SECURITY_BYTES // number of bytes in field element +#define AIM2_NUM_WORDS_FIELD (SECURITY_BITS / 64) // number of 64-bit words in element +#define AIM2_NUM_BITS_WORD 64 // number of bits in word +#define AIM2_IV_SIZE SECURITY_BYTES // byte size of AIM2 initial vector + +#define AIM2_NUM_INPUT_SBOX 3 // number of AIM2 input S-boxes + +#define AIMER_SALT_SIZE SECURITY_BYTES // byte size of salt +#define AIMER_SEED_SIZE SECURITY_BYTES // byte size of seed +#define AIMER_COMMIT_SIZE (SECURITY_BYTES * 2) // byte size of commitment + +#define AIMER_L AIM2_NUM_INPUT_SBOX +#define AIMER_T 33 // number of parallel repetitions (Tau) +#define AIMER_N 256 // number of MPC parties (N) +#define AIMER_LOGN 8 // log_2(N) + +#endif // PARAMS_H diff --git a/crypto_sign/aimer256s/m4stack/sign.c b/crypto_sign/aimer256s/m4stack/sign.c new file mode 100644 index 00000000..601718ad --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/sign.c @@ -0,0 +1,654 @@ +// SPDX-License-Identifier: MIT + +#include "api.h" +#include "aim2.h" +#include "field.h" +#include "hash.h" +#include "params.h" +#include "randombytes.h" +#include "sign.h" +#include "tree.h" +#include +#include +#include +#include + +void commit_and_expand_tape(tape_t *tape, uint8_t *commit, + const hash_instance *ctx_precom, + const uint8_t seed[AIMER_SEED_SIZE], + size_t rep, size_t party) +{ + hash_instance ctx; + uint8_t buffer[AIMER_SEED_SIZE + 2]; + + buffer[0] = (uint8_t)(rep); + buffer[1] = (uint8_t)(party); + memcpy(buffer + 2, seed, AIMER_SEED_SIZE); + + hash_ctx_clone(&ctx, ctx_precom); + hash_update(&ctx, buffer, AIMER_SEED_SIZE + 2); + hash_final(&ctx); + hash_squeeze(&ctx, commit, AIMER_COMMIT_SIZE); + hash_squeeze(&ctx, (uint8_t *)tape, sizeof(tape_t)); + hash_ctx_release(&ctx); +} + +void aim2_mpc(mult_chk_t *mult_chk, + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF ct_GF) +{ + // pt + c = t ^ {2 ^ e - 1} + // --> t ^ {2 ^ e} + t * c = t * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[0], mult_chk->x_shares[0]); + for (size_t i = 1; i < 11; i++) + { + GF_sqr_s(mult_chk->z_shares[0], mult_chk->z_shares[0]); + } + GF_mul_add(mult_chk->z_shares[0], mult_chk->x_shares[0], aim2_constants[0]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[0], + matrix_A[0]); + + GF_mul(mult_chk->z_shares[1], mult_chk->x_shares[1], aim2_constants[1]); + GF_transposed_matmul_add(mult_chk->z_shares[1], mult_chk->x_shares[1], + aim2_e2_power_matrix); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[1], + matrix_A[1]); + + GF_sqr_s(mult_chk->z_shares[2], mult_chk->x_shares[2]); + for (size_t i = 1; i < 7; i++) + { + GF_sqr_s(mult_chk->z_shares[2], mult_chk->z_shares[2]); + } + GF_mul_add(mult_chk->z_shares[2], mult_chk->x_shares[2], aim2_constants[2]); + GF_transposed_matmul_add(mult_chk->x_shares[AIMER_L], mult_chk->x_shares[2], + matrix_A[2]); + + // x ^ {2 ^ e - 1} = pt + ct + // --> x ^ {2 ^ e} + x * ct = x * pt + // --> z = x * pt + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_sqr_s(mult_chk->z_shares[AIMER_L], mult_chk->z_shares[AIMER_L]); + GF_mul_add(mult_chk->z_shares[AIMER_L], mult_chk->x_shares[AIMER_L], ct_GF); +} + +// committing to the seeds and the execution views of the parties +void run_phase_1(signature_t *sign, + const GF pt_GF, const GF sbox_outputs[AIMER_L], + const uint8_t mu[AIMER_COMMIT_SIZE], + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + hash_instance ctx; + + // hash_instance for h_1 + hash_init_prefix(&ctx, HASH_PREFIX_1); + hash_update(&ctx, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + hash_update(&ctx, commits, AIMER_COMMIT_SIZE); + + // compute offsets + GF_add(delta.pt_share, delta.pt_share, tape.pt_share); + GF_add(delta.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(delta.a_share, delta.a_share, tape.a_share); + GF_add(delta.c_share, delta.c_share, tape.c_share); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_add(delta.pt_share, delta.pt_share, pt_GF); + GF_add(delta.t_shares[0], delta.t_shares[0], sbox_outputs[0]); + GF_add(delta.t_shares[1], delta.t_shares[1], sbox_outputs[1]); + GF_add(delta.t_shares[2], delta.t_shares[2], sbox_outputs[2]); + GF_mul_add_s(delta.c_share, pt_GF, delta.a_share); + + GF_to_bytes(sign->proofs[rep].delta_pt_bytes, delta.pt_share); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[0], delta.t_shares[0]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[1], delta.t_shares[1]); + GF_to_bytes(sign->proofs[rep].delta_ts_bytes[2], delta.t_shares[2]); + GF_to_bytes(sign->proofs[rep].delta_c_bytes, delta.c_share); + } + } + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_precom); + + // commit to salt, (all commitments of parties' seeds, + // delta_pt, delta_t, delta_c) for all repetitions + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_3(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b, const GF ct_GF) +{ + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF epsilons[AIMER_L + 1]; + + // prepare h2 + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_2); + hash_update(&ctx, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx, sign->salt, AIMER_SALT_SIZE); + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + GF alpha = {0,}; + for (size_t rep = 0; rep < AIMER_T; rep++) + { + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF_set0(alpha); + for (size_t party = 0; party < AIMER_N; party++) + { + // generate execution views and commitments + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + party - 1], rep, party); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk)); + + // adjust the last share and prepare the proof and h_1 + if (party == AIMER_N - 1) + { + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + } + hash_update(&ctx, (const uint8_t *)alpha_v_shares, sizeof(alpha_v_shares)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + hash_final(&ctx); + hash_squeeze(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); +} + +void run_phase_1_to_5(signature_t *sign, + const uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE], + const GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD], + const GF vector_b) +{ + // prepare challenge parties + hash_instance ctx; + hash_init(&ctx); + hash_update(&ctx, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx, indices, AIMER_T); + hash_ctx_release(&ctx); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + uint8_t commits[AIMER_COMMIT_SIZE]; + uint8_t nodes[2 * AIMER_N - 1][AIMER_SEED_SIZE]; + + GF epsilons[AIMER_L + 1]; + + // prepare epsilons + hash_instance ctx_e; + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + + // compute parties' seeds using binary tree + expand_tree(nodes, sign->salt, rep, root_seeds[rep]); + reveal_all_but(sign->proofs[rep].reveal_path, + (const uint8_t (*)[AIMER_SEED_SIZE])nodes, i_bar); + + // expand challenge + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha_share = {0,}; + + tape_t tape; + commit_and_expand_tape(&tape, commits, &ctx_precom, + nodes[AIMER_N + i_bar - 1], rep, i_bar); + memcpy(sign->proofs[rep].missing_commitment, commits, + AIMER_COMMIT_SIZE); + + GF_set0(mult_chk.x_shares[AIMER_L]); + + // adjust the last share and prepare the proof and h_1 + if (i_bar == AIMER_N - 1) + { + // initialize adjustment values + tape_t delta; + memset(&delta, 0, sizeof(tape_t)); + + GF_from_bytes(delta.pt_share, sign->proofs[rep].delta_pt_bytes); + GF_from_bytes(delta.t_shares[0], sign->proofs[rep].delta_ts_bytes[0]); + GF_from_bytes(delta.t_shares[1], sign->proofs[rep].delta_ts_bytes[1]); + GF_from_bytes(delta.t_shares[2], sign->proofs[rep].delta_ts_bytes[2]); + GF_from_bytes(delta.c_share, sign->proofs[rep].delta_c_bytes); + + GF_add(tape.pt_share, delta.pt_share, tape.pt_share); + GF_add(tape.t_shares[0], delta.t_shares[0], tape.t_shares[0]); + GF_add(tape.t_shares[1], delta.t_shares[1], tape.t_shares[1]); + GF_add(tape.t_shares[2], delta.t_shares[2], tape.t_shares[2]); + GF_add(tape.c_share, delta.c_share, tape.c_share); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + for (size_t ell = 0; ell < AIMER_L; ell++) + { + GF_copy(mult_chk.x_shares[ell], tape.t_shares[ell]); + + // x_* = sum_i A[i] * t[i] + b + GF_transposed_matmul_add(mult_chk.x_shares[AIMER_L], + tape.t_shares[ell], matrix_A[ell]); + } + GF_copy(alpha_share, tape.a_share); + + GF_mul_add(alpha_share, mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_share, mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_share, mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_share, mult_chk.x_shares[3], epsilons[3]); + GF_to_bytes(sign->proofs[rep].missing_alpha_share_bytes, alpha_share); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); +} + +//////////////////////////////////////////////////////////////////////////////// +int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) +{ + if (!pk || !sk) + { + return -1; + } + + randombytes(sk, AIM2_NUM_BYTES_FIELD); + randombytes(pk, AIM2_IV_SIZE); + + aim2(pk + AIM2_IV_SIZE, sk, pk); + memcpy(sk + AIM2_NUM_BYTES_FIELD, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + + return 0; +} + +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + signature_t *sign = (signature_t *)sig; + + GF pt_GF = {0,}, ct_GF = {0,}; + GF_from_bytes(pt_GF, sk); + GF_from_bytes(ct_GF, sk + AIM2_NUM_BYTES_FIELD + AIM2_IV_SIZE); + + // message pre-hashing + hash_instance ctx; + hash_init_prefix(&ctx, HASH_PREFIX_0); + hash_update(&ctx, sk + AIM2_NUM_BYTES_FIELD, + AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx, m, mlen); + hash_final(&ctx); + + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_squeeze(&ctx, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx); + + // compute first L sboxes' outputs + GF sbox_outputs[AIMER_L]; + aim2_sbox_outputs(sbox_outputs, pt_GF); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, sk + AIM2_NUM_BYTES_FIELD); + + // generate per-signature randomness + uint8_t random[SECURITY_BYTES]; + randombytes(random, SECURITY_BYTES); + + // generate salt and root seeds + hash_instance ctx_roots; + hash_init_prefix(&ctx_roots, HASH_PREFIX_3); + hash_update(&ctx_roots, sk, AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_roots, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_roots, random, SECURITY_BYTES); + hash_final(&ctx_roots); + hash_squeeze(&ctx_roots, sign->salt, AIMER_SALT_SIZE); + + uint8_t root_seeds[AIMER_T][AIMER_SEED_SIZE]; + hash_squeeze(&ctx_roots, (uint8_t *)root_seeds, AIMER_T * AIMER_SEED_SIZE); + hash_ctx_release(&ctx_roots); + + run_phase_1(sign, pt_GF, (const GF *)sbox_outputs, mu, + (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds); + + run_phase_1_to_3(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b, ct_GF); + + run_phase_1_to_5(sign, (const uint8_t (*)[AIMER_SEED_SIZE])root_seeds, + (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, + vector_b); + + *siglen = CRYPTO_BYTES; + + return 0; +} + +int crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk) +{ + crypto_sign_signature(sm + mlen, smlen, m, mlen, sk); + + memcpy(sm, m, mlen); + *smlen += mlen; + + return 0; +} + +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, + const uint8_t *pk) +{ + if (siglen != CRYPTO_BYTES) + { + return -1; + } + + const signature_t *sign = (const signature_t *)sig; + + GF ct_GF = {0,}; + GF_from_bytes(ct_GF, pk + AIM2_IV_SIZE); + + // derive the binary matrix and the vector from the initial vector + GF matrix_A[AIMER_L][AIM2_NUM_BITS_FIELD]; + GF vector_b = {0,}; + generate_matrix_LU(matrix_A, vector_b, pk); + + hash_instance ctx_e, ctx_h1, ctx_h2; + + // indices = Expand(h_2) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_2, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + uint8_t indices[AIMER_T]; // AIMER_N <= 256 + hash_squeeze(&ctx_e, indices, AIMER_T); + hash_ctx_release(&ctx_e); + for (size_t rep = 0; rep < AIMER_T; rep++) + { + indices[rep] &= (1 << AIMER_LOGN) - 1; + } + + // epsilons = Expand(h_1) + hash_init(&ctx_e); + hash_update(&ctx_e, sign->h_1, AIMER_COMMIT_SIZE); + hash_final(&ctx_e); + + // message pre-hashing + uint8_t mu[AIMER_COMMIT_SIZE]; + hash_init_prefix(&ctx_h1, HASH_PREFIX_0); + hash_update(&ctx_h1, pk, AIM2_IV_SIZE + AIM2_NUM_BYTES_FIELD); + hash_update(&ctx_h1, m, mlen); + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + // ready for computing h_1' and h_2' + hash_init_prefix(&ctx_h1, HASH_PREFIX_1); + hash_update(&ctx_h1, mu, AIMER_COMMIT_SIZE); + hash_update(&ctx_h1, sign->salt, AIMER_SALT_SIZE); + + hash_init_prefix(&ctx_h2, HASH_PREFIX_2); + hash_update(&ctx_h2, sign->h_1, AIMER_COMMIT_SIZE); + hash_update(&ctx_h2, sign->salt, AIMER_SALT_SIZE); + + hash_instance ctx_precom; + hash_init_prefix(&ctx_precom, HASH_PREFIX_5); + hash_update(&ctx_precom, sign->salt, AIMER_SALT_SIZE); + + for (size_t rep = 0; rep < AIMER_T; rep++) + { + size_t i_bar = indices[rep]; + uint8_t nodes[2 * AIMER_N - 2][AIMER_SEED_SIZE]; + + reconstruct_tree(nodes, sign->salt, sign->proofs[rep].reveal_path, + rep, i_bar); + + GF pt_shares[AIMER_N]; + GF alpha_v_shares[2][AIMER_N]; + GF_set0(alpha_v_shares[1][i_bar]); + + GF epsilons[AIMER_L + 1]; + hash_squeeze(&ctx_e, (uint8_t *)epsilons, sizeof(epsilons)); + + GF alpha = {0,}; + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + hash_update(&ctx_h1, sign->proofs[rep].missing_commitment, + AIMER_COMMIT_SIZE); + GF_from_bytes(alpha_v_shares[0][i_bar], + sign->proofs[rep].missing_alpha_share_bytes); + GF_add(alpha, alpha, alpha_v_shares[0][i_bar]); + continue; + } + + tape_t tape; + uint8_t commit[AIMER_COMMIT_SIZE]; + commit_and_expand_tape(&tape, commit, &ctx_precom, + nodes[AIMER_N + party - 2], rep, party); + hash_update(&ctx_h1, commit, AIMER_COMMIT_SIZE); + + // adjust last shares + mult_chk_t mult_chk; + memset(&mult_chk, 0, sizeof(mult_chk_t)); + if (party == AIMER_N - 1) + { + GF temp = {0,}; + + GF_from_bytes(temp, sign->proofs[rep].delta_pt_bytes); + GF_add(tape.pt_share, tape.pt_share, temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[0]); + GF_add(tape.t_shares[0], tape.t_shares[0], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[1]); + GF_add(tape.t_shares[1], tape.t_shares[1], temp); + GF_from_bytes(temp, sign->proofs[rep].delta_ts_bytes[2]); + GF_add(tape.t_shares[2], tape.t_shares[2], temp); + + GF_from_bytes(temp, sign->proofs[rep].delta_c_bytes); + GF_add(tape.c_share, tape.c_share, temp); + + GF_copy(mult_chk.x_shares[AIMER_L], vector_b); + } + + // run the MPC simulation and prepare the mult check inputs + GF_copy(mult_chk.x_shares[0], tape.t_shares[0]); + GF_copy(mult_chk.x_shares[1], tape.t_shares[1]); + GF_copy(mult_chk.x_shares[2], tape.t_shares[2]); + GF_copy(pt_shares[party], tape.pt_share); + GF_copy(alpha_v_shares[0][party], tape.a_share); + GF_copy(alpha_v_shares[1][party], tape.c_share); + aim2_mpc(&mult_chk, (const GF (*)[AIM2_NUM_BITS_FIELD])matrix_A, ct_GF); + + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[0], epsilons[0]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[1], epsilons[1]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[2], epsilons[2]); + GF_mul_add(alpha_v_shares[0][party], mult_chk.x_shares[3], epsilons[3]); + GF_mul_add(alpha_v_shares[1][party], mult_chk.z_shares[3], epsilons[3]); + + GF_add(alpha, alpha, alpha_v_shares[0][party]); + } + + // alpha is opened, so we can finish calculating v_share + for (size_t party = 0; party < AIMER_N; party++) + { + if (party == i_bar) + { + continue; + } + + GF_mul_add(alpha_v_shares[1][party], pt_shares[party], alpha); + GF_add(alpha_v_shares[1][i_bar], alpha_v_shares[1][i_bar], + alpha_v_shares[1][party]); + } + + // v is opened + hash_update(&ctx_h2, (const uint8_t *)alpha_v_shares, + sizeof(alpha_v_shares)); + + // NOTE: depend on the order of values in proof_t + hash_update(&ctx_h1, sign->proofs[rep].delta_pt_bytes, + AIM2_NUM_BYTES_FIELD * (AIMER_L + 2)); + } + hash_ctx_release(&ctx_e); + hash_ctx_release(&ctx_precom); + + uint8_t h_1_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h1); + hash_squeeze(&ctx_h1, h_1_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h1); + + uint8_t h_2_prime[AIMER_COMMIT_SIZE]; + hash_final(&ctx_h2); + hash_squeeze(&ctx_h2, h_2_prime, AIMER_COMMIT_SIZE); + hash_ctx_release(&ctx_h2); + + if (memcmp(h_1_prime, sign->h_1, AIMER_COMMIT_SIZE) != 0 || + memcmp(h_2_prime, sign->h_2, AIMER_COMMIT_SIZE) != 0) + { + return -1; + } + + return 0; +} + +int crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk) +{ + if (smlen < CRYPTO_BYTES) + { + return -1; + } + + const size_t message_len = smlen - CRYPTO_BYTES; + const uint8_t *message = sm; + const uint8_t *signature = sm + message_len; + + if (crypto_sign_verify(signature, CRYPTO_BYTES, message, message_len, pk)) + { + return -1; + } + + memmove(m, message, message_len); + *mlen = message_len; + + return 0; +} diff --git a/crypto_sign/aimer256s/m4stack/sign.h b/crypto_sign/aimer256s/m4stack/sign.h new file mode 120000 index 00000000..c46aabad --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/sign.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/sign.h \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/tree.c b/crypto_sign/aimer256s/m4stack/tree.c new file mode 120000 index 00000000..09dffdf6 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/tree.c @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.c \ No newline at end of file diff --git a/crypto_sign/aimer256s/m4stack/tree.h b/crypto_sign/aimer256s/m4stack/tree.h new file mode 120000 index 00000000..53fc8d73 --- /dev/null +++ b/crypto_sign/aimer256s/m4stack/tree.h @@ -0,0 +1 @@ +../../aimer128f/m4stack/tree.h \ No newline at end of file From 229b36bcf12b2c276afad4f1502a7216b693a72b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 31 Oct 2024 14:45:47 +0800 Subject: [PATCH 102/107] Add AIMer benchmarks (#366) * Add AIMer implementations(m4speed, m4stack) for all NIST security levels * change aimer128f to symlinks * Symlinks updates for AIMer * update benchmarks * update skiplist --------- Co-authored-by: Sangyub Lee --- benchmarks.csv | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ benchmarks.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ skiplist.py | 24 ++++++++++++++++++------ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index 77b1d42f..59408b27 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -19,14 +19,26 @@ ml-kem-768 (10 executions),m4fspeed,631949,631658,632164,656369,656082,656596,70 ml-kem-768 (10 executions),m4fstack,634227,632761,644635,662468,661003,672877,711996,710530,722405 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) +aimer128f (10 executions),m4speed,490087,490087,490088,28590420,28590395,28590439,26750578,26749771,26751014 +aimer128f (10 executions),m4stack,490082,490082,490083,46470710,46470162,46471507,26743713,26743128,26744143 aimer128f (10 executions),mem_opt,564325,564324,564326,46875341,46874593,46876276,26989249,26988505,26989828 aimer128f (10 executions),ref,564323,564323,564324,28991142,28991115,28991171,26994617,26994234,26994927 +aimer128s (10 executions),m4speed,490085,490085,490086,277353540,277345110,277354485,225136633,225136625,225136640 +aimer128s (10 executions),m4stack,490088,490088,490088,372458535,372458327,372459135,225134323,225134115,225134367 aimer128s (10 executions),mem_opt,564323,564323,564325,374834586,374834473,374834973,227230761,227230441,227230833 +aimer192f (10 executions),m4speed,1192752,1192752,1192753,80106923,80106896,80106945,75084294,75083653,75085373 +aimer192f (10 executions),m4stack,1192753,1192753,1192754,116329912,116328844,116330708,75138063,75137469,75138892 aimer192f (10 executions),mem_opt,1397043,1397043,1397043,117993511,117991579,117995094,76372135,76370763,76373839 aimer192f (10 executions),ref,1397040,1397040,1397041,81884026,81883991,81884035,76458825,76456517,76460984 +aimer192s (10 executions),m4speed,1192756,1192756,1192758,763112898,763110056,763113314,617799254,617799226,617799272 +aimer192s (10 executions),m4stack,1192756,1192756,1192756,904630579,904630192,904631379,617834636,617834607,617834652 aimer192s (10 executions),mem_opt,1397047,1397039,1397079,916637185,916637133,916637425,629249382,629249345,629249415 +aimer256f (10 executions),m4speed,2899948,2899948,2899949,160891483,160891455,160891501,166071755,166068640,166073951 +aimer256f (10 executions),m4stack,2899950,2899947,2899985,228360437,228359438,228362262,166042220,166040702,166043056 aimer256f (10 executions),mem_opt,3344254,3344250,3344255,233973308,233969892,233976707,170620601,170617448,170623743 aimer256f (10 executions),ref,3344258,3344255,3344292,164484408,164483962,164484481,170648722,170647189,170651027 +aimer256s (10 executions),m4speed,2899956,2899949,2899989,1391295720,1391289067,1391297144,1321985344,1321984834,1321985426 +aimer256s (10 executions),m4stack,2899950,2899950,2899950,1712314043,1712314001,1712314175,1322034101,1322034066,1322034132 aimer256s (10 executions),mem_opt,3344262,3344252,3344293,1752719642,1752719422,1752720844,1361337862,1361336718,1361338013 ascon-sign-128f-robust (10 executions),ref,122506162,122506099,122506254,2855797836,2855797243,2855798602,174707763,169973472,179525137 ascon-sign-128f-simple (10 executions),ref,69376878,69376875,69376883,1629111557,1629111334,1629112028,97798317,95509050,98714007 @@ -179,14 +191,26 @@ ml-kem-768,m4fspeed,5396,6468,6452,,,,,, ml-kem-768,m4fstack,2820,2860,2844,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [bytes],Sign [bytes],Verify [bytes],,,,,, +aimer128f,m4speed,8720,123376,15448,,,,,, +aimer128f,m4stack,8720,13864,15440,,,,,, aimer128f,mem_opt,8728,13864,15440,,,,,, aimer128f,ref,8728,123376,15448,,,,,, +aimer128s,m4speed,8720,166204,34624,,,,,, +aimer128s,m4stack,8720,27324,34624,,,,,, aimer128s,mem_opt,8728,27324,34624,,,,,, +aimer192f,m4speed,19184,273104,31608,,,,,, +aimer192f,m4stack,19184,29976,31608,,,,,, aimer192f,mem_opt,19192,29976,31608,,,,,, aimer192f,ref,19192,273104,31608,,,,,, +aimer192s,m4speed,19184,349788,60384,,,,,, +aimer192s,m4stack,19184,43220,60384,,,,,, aimer192s,mem_opt,19192,43220,60384,,,,,, +aimer256f,m4speed,50032,573176,78608,,,,,, +aimer256f,m4stack,50032,77056,78568,,,,,, aimer256f,mem_opt,50040,77164,78568,,,,,, aimer256f,ref,50040,573284,78716,,,,,, +aimer256s,m4speed,50032,615856,116936,,,,,, +aimer256s,m4stack,50032,76032,116936,,,,,, aimer256s,mem_opt,50040,76140,117044,,,,,, ascon-sign-128f-robust,ref,3260,2772,2992,,,,,, ascon-sign-128f-simple,ref,2632,2144,2448,,,,,, @@ -340,14 +364,26 @@ ml-kem-768,m4fspeed,75.5,74.4,69.3,,,,,, ml-kem-768,m4fstack,75.3,73.9,68.7,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, +aimer128f,m4speed,57.9,49.5,50.1,,,,,, +aimer128f,m4stack,57.9,66.6,50.1,,,,,, aimer128f,mem_opt,50.6,66.1,49.6,,,,,, aimer128f,ref,50.6,48.8,49.6,,,,,, +aimer128s,m4speed,57.9,43.2,50.7,,,,,, +aimer128s,m4stack,57.9,68.3,50.7,,,,,, aimer128s,mem_opt,50.6,67.9,50.2,,,,,, +aimer192f,m4speed,62.3,40.7,41.2,,,,,, +aimer192f,m4stack,62.3,57.2,41.2,,,,,, aimer192f,mem_opt,53.5,56.4,40.5,,,,,, aimer192f,ref,53.5,39.8,40.5,,,,,, +aimer192s,m4speed,62.3,43.4,41.7,,,,,, +aimer192s,m4stack,62.3,58.9,41.7,,,,,, aimer192s,mem_opt,53.5,58.1,40.9,,,,,, +aimer256f,m4speed,67.7,28.6,27.8,,,,,, +aimer256f,m4stack,67.7,41.5,27.8,,,,,, aimer256f,mem_opt,58.9,40.6,27.0,,,,,, aimer256f,ref,58.9,28.0,27.0,,,,,, +aimer256s,m4speed,67.7,32.2,28.0,,,,,, +aimer256s,m4stack,67.7,43.3,28.0,,,,,, aimer256s,mem_opt,58.9,42.4,27.2,,,,,, ascon-sign-128f-robust,ref,0.0,0.0,0.0,,,,,, ascon-sign-128f-simple,ref,0.0,0.0,0.0,,,,,, @@ -500,14 +536,26 @@ ml-kem-768,m4fspeed,16012,0,0,16012,,,,, ml-kem-768,m4fstack,13316,0,0,13316,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, +aimer128f,m4speed,15992,0,0,15992,,,,, +aimer128f,m4stack,16392,0,0,16392,,,,, aimer128f,mem_opt,17476,0,0,17476,,,,, aimer128f,ref,17076,0,0,17076,,,,, +aimer128s,m4speed,16764,0,0,16764,,,,, +aimer128s,m4stack,16368,0,0,16368,,,,, aimer128s,mem_opt,17452,0,0,17452,,,,, +aimer192f,m4speed,23528,0,0,23528,,,,, +aimer192f,m4stack,23956,0,0,23956,,,,, aimer192f,mem_opt,25384,0,0,25384,,,,, aimer192f,ref,24956,0,0,24956,,,,, +aimer192s,m4speed,24256,0,0,24256,,,,, +aimer192s,m4stack,23860,0,0,23860,,,,, aimer192s,mem_opt,25288,0,0,25288,,,,, +aimer256f,m4speed,25596,0,0,25596,,,,, +aimer256f,m4stack,26096,0,0,26096,,,,, aimer256f,mem_opt,27804,0,0,27804,,,,, aimer256f,ref,27304,0,0,27304,,,,, +aimer256s,m4speed,26372,0,0,26372,,,,, +aimer256s,m4stack,25928,0,0,25928,,,,, aimer256s,mem_opt,27636,0,0,27636,,,,, ascon-sign-128f-robust,ref,17664,0,0,17664,,,,, ascon-sign-128f-simple,ref,17596,0,0,17596,,,,, diff --git a/benchmarks.md b/benchmarks.md index c82aedd1..fd8ed7c0 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -21,14 +21,26 @@ ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | +| aimer128f (10 executions) | m4speed | AVG: 490,087
MIN: 490,087
MAX: 490,088 | AVG: 28,590,420
MIN: 28,590,395
MAX: 28,590,439 | AVG: 26,750,578
MIN: 26,749,771
MAX: 26,751,014 | +| aimer128f (10 executions) | m4stack | AVG: 490,082
MIN: 490,082
MAX: 490,083 | AVG: 46,470,710
MIN: 46,470,162
MAX: 46,471,507 | AVG: 26,743,713
MIN: 26,743,128
MAX: 26,744,143 | | aimer128f (10 executions) | mem_opt | AVG: 564,325
MIN: 564,324
MAX: 564,326 | AVG: 46,875,341
MIN: 46,874,593
MAX: 46,876,276 | AVG: 26,989,249
MIN: 26,988,505
MAX: 26,989,828 | | aimer128f (10 executions) | ref | AVG: 564,323
MIN: 564,323
MAX: 564,324 | AVG: 28,991,142
MIN: 28,991,115
MAX: 28,991,171 | AVG: 26,994,617
MIN: 26,994,234
MAX: 26,994,927 | +| aimer128s (10 executions) | m4speed | AVG: 490,085
MIN: 490,085
MAX: 490,086 | AVG: 277,353,540
MIN: 277,345,110
MAX: 277,354,485 | AVG: 225,136,633
MIN: 225,136,625
MAX: 225,136,640 | +| aimer128s (10 executions) | m4stack | AVG: 490,088
MIN: 490,088
MAX: 490,088 | AVG: 372,458,535
MIN: 372,458,327
MAX: 372,459,135 | AVG: 225,134,323
MIN: 225,134,115
MAX: 225,134,367 | | aimer128s (10 executions) | mem_opt | AVG: 564,323
MIN: 564,323
MAX: 564,325 | AVG: 374,834,586
MIN: 374,834,473
MAX: 374,834,973 | AVG: 227,230,761
MIN: 227,230,441
MAX: 227,230,833 | +| aimer192f (10 executions) | m4speed | AVG: 1,192,752
MIN: 1,192,752
MAX: 1,192,753 | AVG: 80,106,923
MIN: 80,106,896
MAX: 80,106,945 | AVG: 75,084,294
MIN: 75,083,653
MAX: 75,085,373 | +| aimer192f (10 executions) | m4stack | AVG: 1,192,753
MIN: 1,192,753
MAX: 1,192,754 | AVG: 116,329,912
MIN: 116,328,844
MAX: 116,330,708 | AVG: 75,138,063
MIN: 75,137,469
MAX: 75,138,892 | | aimer192f (10 executions) | mem_opt | AVG: 1,397,043
MIN: 1,397,043
MAX: 1,397,043 | AVG: 117,993,511
MIN: 117,991,579
MAX: 117,995,094 | AVG: 76,372,135
MIN: 76,370,763
MAX: 76,373,839 | | aimer192f (10 executions) | ref | AVG: 1,397,040
MIN: 1,397,040
MAX: 1,397,041 | AVG: 81,884,026
MIN: 81,883,991
MAX: 81,884,035 | AVG: 76,458,825
MIN: 76,456,517
MAX: 76,460,984 | +| aimer192s (10 executions) | m4speed | AVG: 1,192,756
MIN: 1,192,756
MAX: 1,192,758 | AVG: 763,112,898
MIN: 763,110,056
MAX: 763,113,314 | AVG: 617,799,254
MIN: 617,799,226
MAX: 617,799,272 | +| aimer192s (10 executions) | m4stack | AVG: 1,192,756
MIN: 1,192,756
MAX: 1,192,756 | AVG: 904,630,579
MIN: 904,630,192
MAX: 904,631,379 | AVG: 617,834,636
MIN: 617,834,607
MAX: 617,834,652 | | aimer192s (10 executions) | mem_opt | AVG: 1,397,047
MIN: 1,397,039
MAX: 1,397,079 | AVG: 916,637,185
MIN: 916,637,133
MAX: 916,637,425 | AVG: 629,249,382
MIN: 629,249,345
MAX: 629,249,415 | +| aimer256f (10 executions) | m4speed | AVG: 2,899,948
MIN: 2,899,948
MAX: 2,899,949 | AVG: 160,891,483
MIN: 160,891,455
MAX: 160,891,501 | AVG: 166,071,755
MIN: 166,068,640
MAX: 166,073,951 | +| aimer256f (10 executions) | m4stack | AVG: 2,899,950
MIN: 2,899,947
MAX: 2,899,985 | AVG: 228,360,437
MIN: 228,359,438
MAX: 228,362,262 | AVG: 166,042,220
MIN: 166,040,702
MAX: 166,043,056 | | aimer256f (10 executions) | mem_opt | AVG: 3,344,254
MIN: 3,344,250
MAX: 3,344,255 | AVG: 233,973,308
MIN: 233,969,892
MAX: 233,976,707 | AVG: 170,620,601
MIN: 170,617,448
MAX: 170,623,743 | | aimer256f (10 executions) | ref | AVG: 3,344,258
MIN: 3,344,255
MAX: 3,344,292 | AVG: 164,484,408
MIN: 164,483,962
MAX: 164,484,481 | AVG: 170,648,722
MIN: 170,647,189
MAX: 170,651,027 | +| aimer256s (10 executions) | m4speed | AVG: 2,899,956
MIN: 2,899,949
MAX: 2,899,989 | AVG: 1,391,295,720
MIN: 1,391,289,067
MAX: 1,391,297,144 | AVG: 1,321,985,344
MIN: 1,321,984,834
MAX: 1,321,985,426 | +| aimer256s (10 executions) | m4stack | AVG: 2,899,950
MIN: 2,899,950
MAX: 2,899,950 | AVG: 1,712,314,043
MIN: 1,712,314,001
MAX: 1,712,314,175 | AVG: 1,322,034,101
MIN: 1,322,034,066
MAX: 1,322,034,132 | | aimer256s (10 executions) | mem_opt | AVG: 3,344,262
MIN: 3,344,252
MAX: 3,344,293 | AVG: 1,752,719,642
MIN: 1,752,719,422
MAX: 1,752,720,844 | AVG: 1,361,337,862
MIN: 1,361,336,718
MAX: 1,361,338,013 | | ascon-sign-128f-robust (10 executions) | ref | AVG: 122,506,162
MIN: 122,506,099
MAX: 122,506,254 | AVG: 2,855,797,836
MIN: 2,855,797,243
MAX: 2,855,798,602 | AVG: 174,707,763
MIN: 169,973,472
MAX: 179,525,137 | | ascon-sign-128f-simple (10 executions) | ref | AVG: 69,376,878
MIN: 69,376,875
MAX: 69,376,883 | AVG: 1,629,111,557
MIN: 1,629,111,334
MAX: 1,629,112,028 | AVG: 97,798,317
MIN: 95,509,050
MAX: 98,714,007 | @@ -183,14 +195,26 @@ ## Signature Schemes | Scheme | Implementation | Key Generation [bytes] | Sign [bytes] | Verify [bytes] | | ------ | -------------- | ---------------------- | ------------ | -------------- | +| aimer128f | m4speed | 8,720 | 123,376 | 15,448 | +| aimer128f | m4stack | 8,720 | 13,864 | 15,440 | | aimer128f | mem_opt | 8,728 | 13,864 | 15,440 | | aimer128f | ref | 8,728 | 123,376 | 15,448 | +| aimer128s | m4speed | 8,720 | 166,204 | 34,624 | +| aimer128s | m4stack | 8,720 | 27,324 | 34,624 | | aimer128s | mem_opt | 8,728 | 27,324 | 34,624 | +| aimer192f | m4speed | 19,184 | 273,104 | 31,608 | +| aimer192f | m4stack | 19,184 | 29,976 | 31,608 | | aimer192f | mem_opt | 19,192 | 29,976 | 31,608 | | aimer192f | ref | 19,192 | 273,104 | 31,608 | +| aimer192s | m4speed | 19,184 | 349,788 | 60,384 | +| aimer192s | m4stack | 19,184 | 43,220 | 60,384 | | aimer192s | mem_opt | 19,192 | 43,220 | 60,384 | +| aimer256f | m4speed | 50,032 | 573,176 | 78,608 | +| aimer256f | m4stack | 50,032 | 77,056 | 78,568 | | aimer256f | mem_opt | 50,040 | 77,164 | 78,568 | | aimer256f | ref | 50,040 | 573,284 | 78,716 | +| aimer256s | m4speed | 50,032 | 615,856 | 116,936 | +| aimer256s | m4stack | 50,032 | 76,032 | 116,936 | | aimer256s | mem_opt | 50,040 | 76,140 | 117,044 | | ascon-sign-128f-robust | ref | 3,260 | 2,772 | 2,992 | | ascon-sign-128f-simple | ref | 2,632 | 2,144 | 2,448 | @@ -346,14 +370,26 @@ ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | +| aimer128f | m4speed | 57.9% | 49.5% | 50.1% | +| aimer128f | m4stack | 57.9% | 66.6% | 50.1% | | aimer128f | mem_opt | 50.6% | 66.1% | 49.6% | | aimer128f | ref | 50.6% | 48.8% | 49.6% | +| aimer128s | m4speed | 57.9% | 43.2% | 50.7% | +| aimer128s | m4stack | 57.9% | 68.3% | 50.7% | | aimer128s | mem_opt | 50.6% | 67.9% | 50.2% | +| aimer192f | m4speed | 62.3% | 40.7% | 41.2% | +| aimer192f | m4stack | 62.3% | 57.2% | 41.2% | | aimer192f | mem_opt | 53.5% | 56.4% | 40.5% | | aimer192f | ref | 53.5% | 39.8% | 40.5% | +| aimer192s | m4speed | 62.3% | 43.4% | 41.7% | +| aimer192s | m4stack | 62.3% | 58.9% | 41.7% | | aimer192s | mem_opt | 53.5% | 58.1% | 40.9% | +| aimer256f | m4speed | 67.7% | 28.6% | 27.8% | +| aimer256f | m4stack | 67.7% | 41.5% | 27.8% | | aimer256f | mem_opt | 58.9% | 40.6% | 27.0% | | aimer256f | ref | 58.9% | 28.0% | 27.0% | +| aimer256s | m4speed | 67.7% | 32.2% | 28.0% | +| aimer256s | m4stack | 67.7% | 43.3% | 28.0% | | aimer256s | mem_opt | 58.9% | 42.4% | 27.2% | | ascon-sign-128f-robust | ref | 0.0% | 0.0% | 0.0% | | ascon-sign-128f-simple | ref | 0.0% | 0.0% | 0.0% | @@ -508,14 +544,26 @@ ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | +| aimer128f | m4speed | 15,992 | 0 | 0 | 15,992 | +| aimer128f | m4stack | 16,392 | 0 | 0 | 16,392 | | aimer128f | mem_opt | 17,476 | 0 | 0 | 17,476 | | aimer128f | ref | 17,076 | 0 | 0 | 17,076 | +| aimer128s | m4speed | 16,764 | 0 | 0 | 16,764 | +| aimer128s | m4stack | 16,368 | 0 | 0 | 16,368 | | aimer128s | mem_opt | 17,452 | 0 | 0 | 17,452 | +| aimer192f | m4speed | 23,528 | 0 | 0 | 23,528 | +| aimer192f | m4stack | 23,956 | 0 | 0 | 23,956 | | aimer192f | mem_opt | 25,384 | 0 | 0 | 25,384 | | aimer192f | ref | 24,956 | 0 | 0 | 24,956 | +| aimer192s | m4speed | 24,256 | 0 | 0 | 24,256 | +| aimer192s | m4stack | 23,860 | 0 | 0 | 23,860 | | aimer192s | mem_opt | 25,288 | 0 | 0 | 25,288 | +| aimer256f | m4speed | 25,596 | 0 | 0 | 25,596 | +| aimer256f | m4stack | 26,096 | 0 | 0 | 26,096 | | aimer256f | mem_opt | 27,804 | 0 | 0 | 27,804 | | aimer256f | ref | 27,304 | 0 | 0 | 27,304 | +| aimer256s | m4speed | 26,372 | 0 | 0 | 26,372 | +| aimer256s | m4stack | 25,928 | 0 | 0 | 25,928 | | aimer256s | mem_opt | 27,636 | 0 | 0 | 27,636 | | ascon-sign-128f-robust | ref | 17,664 | 0 | 0 | 17,664 | | ascon-sign-128f-simple | ref | 17,596 | 0 | 0 | 17,596 | diff --git a/skiplist.py b/skiplist.py index ac08857a..ae2c41ce 100644 --- a/skiplist.py +++ b/skiplist.py @@ -1,16 +1,28 @@ skip_list = [ - {'scheme': 'aimer192s', 'implementation': 'opt_mem', 'estmemory': 70656}, {'scheme': 'aimer192s', 'implementation': 'ref', 'estmemory': 2036736}, - {'scheme': 'aimer192f', 'implementation': 'opt_mem', 'estmemory': 46080}, {'scheme': 'aimer192f', 'implementation': 'ref', 'estmemory': 287744}, - {'scheme': 'aimer128s', 'implementation': 'opt_mem', 'estmemory': 39936}, {'scheme': 'aimer128s', 'implementation': 'ref', 'estmemory': 924672}, - {'scheme': 'aimer256f', 'implementation': 'opt_mem', 'estmemory': 105472}, {'scheme': 'aimer256f', 'implementation': 'ref', 'estmemory': 600064}, - {'scheme': 'aimer256s', 'implementation': 'opt_mem', 'estmemory': 135168}, {'scheme': 'aimer256s', 'implementation': 'ref', 'estmemory': 4148224}, - {'scheme': 'aimer128f', 'implementation': 'opt_mem', 'estmemory': 22528}, {'scheme': 'aimer128f', 'implementation': 'ref', 'estmemory': 131072}, + {'scheme': 'aimer192s', 'implementation': 'm4stack', 'estmemory': 70656}, + {'scheme': 'aimer192s', 'implementation': 'm4speed', 'estmemory': 360448}, + {'scheme': 'aimer192f', 'implementation': 'm4stack', 'estmemory': 46080}, + {'scheme': 'aimer192f', 'implementation': 'm4speed', 'estmemory': 287744}, + {'scheme': 'aimer128s', 'implementation': 'm4stack', 'estmemory': 39936}, + {'scheme': 'aimer128s', 'implementation': 'm4speed', 'estmemory': 172032}, + {'scheme': 'aimer256f', 'implementation': 'm4stack', 'estmemory': 105472}, + {'scheme': 'aimer256f', 'implementation': 'm4speed', 'estmemory': 600064}, + {'scheme': 'aimer256s', 'implementation': 'm4stack', 'estmemory': 135168}, + {'scheme': 'aimer256s', 'implementation': 'm4speed', 'estmemory': 633856}, + {'scheme': 'aimer128f', 'implementation': 'm4stack', 'estmemory': 22528}, + {'scheme': 'aimer128f', 'implementation': 'm4speed', 'estmemory': 131072}, + {'scheme': 'aimer192s_mem', 'implementation': 'mem_opt', 'estmemory': 70656}, + {'scheme': 'aimer192f_mem', 'implementation': 'mem_opt', 'estmemory': 46080}, + {'scheme': 'aimer128s_mem', 'implementation': 'mem_opt', 'estmemory': 39936}, + {'scheme': 'aimer256f_mem', 'implementation': 'mem_opt', 'estmemory': 105472}, + {'scheme': 'aimer256s_mem', 'implementation': 'mem_opt', 'estmemory': 135168}, + {'scheme': 'aimer128f_mem', 'implementation': 'mem_opt', 'estmemory': 22528}, {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, From 3200c9e3a29bfd954bacd581cb3b0d6c3c7f73c4 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 31 Oct 2024 16:26:08 +0800 Subject: [PATCH 103/107] Remove eliminated schemes from NIST PQC digital signature competition (#365) * Remove eliminated schemes from NIST PQC digital signature competition NIST announced the second round candidates on October 24, 2024: https://groups.google.com/a/list.nist.gov/g/pqc-forum/c/khAfIZPktRE/m/bBZWmET-AAAJ Eliminated schemes (with implementations in mupq): - ascon-sign - biscuit - meds - sphinca-a - tuov None of those have dedicated implementations in pqm4. aimer and haetae also got eliminated, but remain candidates of KPQC (https://www.kpqc.or.kr/competition.html). Let's keep them around. * adjust README * update mupq * fix aimer skiplist --- README.md | 12 +++++--- benchmarks.csv | 76 ------------------------------------------------- benchmarks.md | 77 -------------------------------------------------- mupq | 2 +- skiplist.py | 47 ++++-------------------------- 5 files changed, 15 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index 2c0ec888..b93095a4 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,17 @@ The design goals of the library are to offer * integration of clean implementations from [PQClean](https://github.com/PQClean/PQClean); and * easy integration of new schemes and implementations into the framework. -## Previous NIST PQC +## Scope of pqm4 -The master branch of **pqm4** contains schemes that either [selected for standardization by NIST](https://csrc.nist.gov/Projects/post-quantum-cryptography/selected-algorithms-2022), -part of the [4th round of the NIST PQC standardization process](https://csrc.nist.gov/Projects/post-quantum-cryptography/round-4-submissions), -or part or the [first round of additional signatures of the NIST PQC standardization process](https://csrc.nist.gov/projects/pqc-dig-sig/round-1-additional-signatures). +The master branch of **pqm4** contains schemes that either +- standardized by NIST in [FIPS203](https://csrc.nist.gov/pubs/fips/203/final), [FIPS204](https://csrc.nist.gov/pubs/fips/203/final), or [FIPS205](https://csrc.nist.gov/pubs/fips/203/final), +- [selected for standardization by NIST](https://csrc.nist.gov/Projects/post-quantum-cryptography/selected-algorithms-2022), +- part of the [4th round of the NIST PQC standardization process](https://csrc.nist.gov/Projects/post-quantum-cryptography/round-4-submissions), +- part or the [first round of additional signatures of the NIST PQC standardization process](https://csrc.nist.gov/projects/pqc-dig-sig/round-1-additional-signatures), +- part of the [second round of the KpqC competition](https://www.kpqc.or.kr/competition.html). Implementations for previous NIST PQC rounds are available here: +- Signature Round 1: https://github.com/mupq/pqm4/releases/tag/SignatureRound1 - Round 3: https://github.com/mupq/pqm4/releases/tag/Round3 - Round 2: https://github.com/mupq/pqm4/releases/tag/Round2 - Round 1: https://github.com/mupq/pqm4/releases/tag/Round1 diff --git a/benchmarks.csv b/benchmarks.csv index 59408b27..ddfa372d 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -40,17 +40,6 @@ aimer256f (10 executions),ref,3344258,3344255,3344292,164484408,164483962,164484 aimer256s (10 executions),m4speed,2899956,2899949,2899989,1391295720,1391289067,1391297144,1321985344,1321984834,1321985426 aimer256s (10 executions),m4stack,2899950,2899950,2899950,1712314043,1712314001,1712314175,1322034101,1322034066,1322034132 aimer256s (10 executions),mem_opt,3344262,3344252,3344293,1752719642,1752719422,1752720844,1361337862,1361336718,1361338013 -ascon-sign-128f-robust (10 executions),ref,122506162,122506099,122506254,2855797836,2855797243,2855798602,174707763,169973472,179525137 -ascon-sign-128f-simple (10 executions),ref,69376878,69376875,69376883,1629111557,1629111334,1629112028,97798317,95509050,98714007 -ascon-sign-128s-robust (10 executions),ref,7842366557,7842366432,7842366620,59267552580,59267543517,59267565672,60232378,57865239,62848708 -ascon-sign-128s-simple (10 executions),ref,4441129007,4441128624,4441129583,33877719255,33877704467,33877739518,33665713,31101669,34993483 -ascon-sign-192f-robust (10 executions),ref,222614206,222614156,222614345,5712962198,5712960682,5712963829,321026499,315341414,327745233 -ascon-sign-192f-simple (10 executions),ref,128167067,128167038,128167083,3345487807,3345484178,3345492588,179328421,175094665,183794127 -ascon-sign-192s-robust (10 executions),ref,14249838562,14249837693,14249840118,126646612223,126646594160,126646651564,111451290,108763808,114965691 -ascon-sign-192s-simple (10 executions),ref,8204011592,8204011246,8204011971,74760768141,74760751354,74760789761,61679880,58983014,64202741 -biscuit128f (10 executions),ref,1054719,1054719,1054720,274072426,274072411,274072461,254371114,254371087,254371140 -biscuit192f (10 executions),ref,1886203,1886199,1886238,765314258,765314227,765314291,713412502,713412394,713412608 -biscuit256f (10 executions),ref,3301990,3301983,3302022,1747187940,1747187918,1747187973,1678998604,1678998013,1678998987 cross-sha2-r-sdp-1-fast (10 executions),ref,5614888,5590276,5650611,216566013,215745202,217395250,143008126,141803162,144002548 cross-sha2-r-sdp-3-fast (10 executions),ref,8201340,8148672,8208465,241899820,241815860,242049039,123896179,123524606,124545760 cross-sha2-r-sdpg-1-fast (10 executions),ref,2151163,2115797,2174685,116162852,116120174,116181821,87741423,87209686,88267494 @@ -92,8 +81,6 @@ mayo1 (10 executions),ref,7977004,7976973,7977015,18005446,18005440,18005487,629 mayo2 (10 executions),m4f,11917959,11917940,11917980,11979613,11979582,11979624,5130148,5130131,5130180 mayo2 (10 executions),ref,18432706,18432701,18432740,23546659,23546640,23546680,5494246,5494236,5494276 mayo3 (10 executions),m4f,18946738,18946737,18946740,32477408,32477407,32477411,16852927,16852799,16853047 -meds13220 (10 executions),ref,47801890,47796259,47805424,1774401869,1773011038,1779733959,1767764521,1766326468,1773152168 -meds55604 (10 executions),ref,253603604,253590695,253615749,8009948412,8009909000,8009995748,8320756990,8320682364,8320835448 mirith_IIIa_fast (10 executions),ref,3009088,3009084,3009123,891195817,891191657,891198221,831725932,831697264,831742620 mirith_IIIb_fast (10 executions),ref,4565011,4565007,4565046,1298812706,1298810546,1298815343,1214260655,1214247570,1214277229 mirith_Ia_fast (10 executions),ref,1303728,1303721,1303764,296732107,296728990,296734109,276059526,276031297,276080171 @@ -152,12 +139,6 @@ snova-25-8-16-3-ssk (10 executions),ref,35195324,35195216,35195579,112654217,931 snova-28-17-16-2-esk (10 executions),ref,51177590,51177548,51177647,23387139,21270788,42311786,19180389,19180360,19180440 snova-28-17-16-2-ssk (10 executions),ref,51065038,51064999,51065086,52865514,50757388,71788606,19180379,19180357,19180425 snova-37-8-16-4-ssk (10 executions),ref,122023801,122023399,122024216,533063912,533033960,533090127,335806349,335805890,335806820 -sphincs-a-sha2-128f (10 executions),ref,30278936,30278762,30279211,382270810,382269421,382271497,35695646,35693840,35698828 -sphincs-a-sha2-128s (10 executions),ref,814836852,814834574,814838039,6981930727,6981924687,6981936443,187090082,187087928,187093600 -sphincs-a-sha2-192f (10 executions),ref,45930664,45930481,45930983,634374072,634373011,634375225,35145783,35144266,35146607 -sphincs-a-shake-128f (10 executions),ref,61578406,61578107,61578885,1188147363,1188146489,1188148063,76330135,76328602,76331478 -sphincs-a-shake-128s (10 executions),ref,2342298427,2342296403,2342299607,22926754899,22926752978,22926758555,241835141,241830735,241838908 -sphincs-a-shake-192f (10 executions),ref,110027677,110027323,110027950,1814954350,1814953585,1814955913,64022276,64020853,64023988 sphincs-sha2-128f-simple (10 executions),clean,15742990,15742958,15742996,368575228,368575193,368575246,21923628,21369867,22456717 sphincs-sha2-128s-simple (10 executions),clean,1007731522,1007731504,1007731551,7657558168,7657558117,7657558212,7471794,7228491,7797915 sphincs-sha2-192f-simple (10 executions),clean,23570224,23570214,23570257,666398438,666398401,666398468,35457937,35087854,35973969 @@ -212,17 +193,6 @@ aimer256f,ref,50040,573284,78716,,,,,, aimer256s,m4speed,50032,615856,116936,,,,,, aimer256s,m4stack,50032,76032,116936,,,,,, aimer256s,mem_opt,50040,76140,117044,,,,,, -ascon-sign-128f-robust,ref,3260,2772,2992,,,,,, -ascon-sign-128f-simple,ref,2632,2144,2448,,,,,, -ascon-sign-128s-robust,ref,3452,2916,2240,,,,,, -ascon-sign-128s-simple,ref,2824,2268,1752,,,,,, -ascon-sign-192f-robust,ref,6092,4924,4504,,,,,, -ascon-sign-192f-simple,ref,4808,3640,3704,,,,,, -ascon-sign-192s-robust,ref,6380,5116,4332,,,,,, -ascon-sign-192s-simple,ref,5096,3812,3048,,,,,, -biscuit128f,ref,600,137348,14560,,,,,, -biscuit192f,ref,640,265964,20796,,,,,, -biscuit256f,ref,720,477468,33108,,,,,, cross-sha2-r-sdp-1-fast,ref,5200,218304,105604,,,,,, cross-sha2-r-sdp-3-fast,ref,9920,324764,158132,,,,,, cross-sha2-r-sdpg-1-fast,ref,2760,130824,69536,,,,,, @@ -264,8 +234,6 @@ mayo1,ref,74444,218644,399348,,,,,, mayo2,m4f,111532,124644,278444,,,,,, mayo2,ref,111532,238324,270260,,,,,, mayo3,m4f,244748,340668,469780,,,,,, -meds13220,ref,44000,180404,47716,,,,,, -meds55604,ref,162196,392852,160324,,,,,, mirith_IIIa_fast,ref,21832,266480,46156,,,,,, mirith_IIIb_fast,ref,32872,298208,59172,,,,,, mirith_Ia_fast,ref,10208,122424,22836,,,,,, @@ -324,12 +292,6 @@ snova-25-8-16-3-ssk,ref,190696,190836,122656,,,,,, snova-28-17-16-2-esk,ref,309216,127232,199684,,,,,, snova-28-17-16-2-ssk,ref,309216,309356,199684,,,,,, snova-37-8-16-4-ssk,ref,640324,640428,411516,,,,,, -sphincs-a-sha2-128f,ref,281168,280772,280656,,,,,, -sphincs-a-sha2-128s,ref,585984,585732,585396,,,,,, -sphincs-a-sha2-192f,ref,504084,502636,502356,,,,,, -sphincs-a-shake-128f,ref,281072,280676,280560,,,,,, -sphincs-a-shake-128s,ref,585888,585636,585264,,,,,, -sphincs-a-shake-192f,ref,503544,502092,501816,,,,,, sphincs-sha2-128f-simple,clean,2856,2468,2664,,,,,, sphincs-sha2-128s-simple,clean,3084,2556,1968,,,,,, sphincs-sha2-192f-simple,clean,5468,4404,4356,,,,,, @@ -385,17 +347,6 @@ aimer256f,ref,58.9,28.0,27.0,,,,,, aimer256s,m4speed,67.7,32.2,28.0,,,,,, aimer256s,m4stack,67.7,43.3,28.0,,,,,, aimer256s,mem_opt,58.9,42.4,27.2,,,,,, -ascon-sign-128f-robust,ref,0.0,0.0,0.0,,,,,, -ascon-sign-128f-simple,ref,0.0,0.0,0.0,,,,,, -ascon-sign-128s-robust,ref,0.0,0.0,0.0,,,,,, -ascon-sign-128s-simple,ref,0.0,0.0,0.0,,,,,, -ascon-sign-192f-robust,ref,0.0,0.0,0.0,,,,,, -ascon-sign-192f-simple,ref,0.0,0.0,0.0,,,,,, -ascon-sign-192s-robust,ref,0.0,0.0,0.0,,,,,, -ascon-sign-192s-simple,ref,0.0,0.0,0.0,,,,,, -biscuit128f,ref,54.3,9.7,8.9,,,,,, -biscuit192f,ref,54.0,6.0,5.5,,,,,, -biscuit256f,ref,54.0,4.4,4.2,,,,,, cross-sha2-r-sdp-1-fast,ref,90.2,86.3,91.0,,,,,, cross-sha2-r-sdp-3-fast,ref,86.5,79.8,81.7,,,,,, cross-sha2-r-sdpg-1-fast,ref,92.9,90.9,92.1,,,,,, @@ -437,8 +388,6 @@ mayo1,ref,39.1,17.7,49.6,,,,,, mayo2,m4f,35.2,35.5,81.2,,,,,, mayo2,ref,22.8,18.1,75.8,,,,,, mayo3,m4f,55.4,32.6,62.2,,,,,, -meds13220,ref,2.5,5.1,4.8,,,,,, -meds55604,ref,1.6,3.0,2.9,,,,,, mirith_IIIa_fast,ref,64.3,6.7,6.5,,,,,, mirith_IIIb_fast,ref,64.5,4.7,4.6,,,,,, mirith_Ia_fast,ref,61.4,10.1,9.7,,,,,, @@ -497,12 +446,6 @@ snova-25-8-16-3-ssk,ref,9.7,3.5,8.0,,,,,, snova-28-17-16-2-esk,ref,10.6,0.2,28.1,,,,,, snova-28-17-16-2-ssk,ref,10.6,10.7,28.1,,,,,, snova-37-8-16-4-ssk,ref,8.8,2.0,3.4,,,,,, -sphincs-a-sha2-128f,ref,43.3,86.6,48.2,,,,,, -sphincs-a-sha2-128s,ref,72.9,88.3,11.7,,,,,, -sphincs-a-sha2-192f,ref,57.5,88.3,46.0,,,,,, -sphincs-a-shake-128f,ref,72.3,96.2,76.0,,,,,, -sphincs-a-shake-128s,ref,90.9,96.9,31.8,,,,,, -sphincs-a-shake-192f,ref,82.6,96.5,70.7,,,,,, sphincs-sha2-128f-simple,clean,90.8,90.7,90.6,,,,,, sphincs-sha2-128s-simple,clean,90.8,90.7,90.4,,,,,, sphincs-sha2-192f-simple,clean,90.2,90.8,90.7,,,,,, @@ -557,17 +500,6 @@ aimer256f,ref,27304,0,0,27304,,,,, aimer256s,m4speed,26372,0,0,26372,,,,, aimer256s,m4stack,25928,0,0,25928,,,,, aimer256s,mem_opt,27636,0,0,27636,,,,, -ascon-sign-128f-robust,ref,17664,0,0,17664,,,,, -ascon-sign-128f-simple,ref,17596,0,0,17596,,,,, -ascon-sign-128s-robust,ref,17972,0,0,17972,,,,, -ascon-sign-128s-simple,ref,17904,0,0,17904,,,,, -ascon-sign-192f-robust,ref,17960,0,0,17960,,,,, -ascon-sign-192f-simple,ref,17912,0,0,17912,,,,, -ascon-sign-192s-robust,ref,18472,0,0,18472,,,,, -ascon-sign-192s-simple,ref,18424,0,0,18424,,,,, -biscuit128f,ref,7580,0,0,7580,,,,, -biscuit192f,ref,7780,0,0,7780,,,,, -biscuit256f,ref,8216,0,0,8216,,,,, cross-sha2-r-sdp-1-fast,ref,14244,0,104,14348,,,,, cross-sha2-r-sdp-3-fast,ref,14744,0,128,14872,,,,, cross-sha2-r-sdpg-1-fast,ref,18409,0,104,18513,,,,, @@ -609,8 +541,6 @@ mayo1,ref,26436,8,0,26444,,,,, mayo2,m4f,17292,8,0,17300,,,,, mayo2,ref,24404,8,0,24412,,,,, mayo3,m4f,23612,8,0,23620,,,,, -meds13220,ref,16844,0,0,16844,,,,, -meds55604,ref,9012,0,0,9012,,,,, mirith_IIIa_fast,ref,7720,256,0,7976,,,,, mirith_IIIb_fast,ref,7760,256,0,8016,,,,, mirith_Ia_fast,ref,7610,256,0,7866,,,,, @@ -669,12 +599,6 @@ snova-25-8-16-3-ssk,ref,28240,0,299,28539,,,,, snova-28-17-16-2-esk,ref,16436,0,280,16716,,,,, snova-28-17-16-2-ssk,ref,16436,0,280,16716,,,,, snova-37-8-16-4-ssk,ref,52440,0,336,52776,,,,, -sphincs-a-sha2-128f,ref,6343,0,0,6343,,,,, -sphincs-a-sha2-128s,ref,6899,0,0,6899,,,,, -sphincs-a-sha2-192f,ref,6867,0,0,6867,,,,, -sphincs-a-shake-128f,ref,5552,0,0,5552,,,,, -sphincs-a-shake-128s,ref,6108,0,0,6108,,,,, -sphincs-a-shake-192f,ref,5916,0,0,5916,,,,, sphincs-sha2-128f-simple,clean,4956,0,0,4956,,,,, sphincs-sha2-128s-simple,clean,5264,0,0,5264,,,,, sphincs-sha2-192f-simple,clean,5444,0,0,5444,,,,, diff --git a/benchmarks.md b/benchmarks.md index fd8ed7c0..e131b348 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -42,17 +42,6 @@ | aimer256s (10 executions) | m4speed | AVG: 2,899,956
MIN: 2,899,949
MAX: 2,899,989 | AVG: 1,391,295,720
MIN: 1,391,289,067
MAX: 1,391,297,144 | AVG: 1,321,985,344
MIN: 1,321,984,834
MAX: 1,321,985,426 | | aimer256s (10 executions) | m4stack | AVG: 2,899,950
MIN: 2,899,950
MAX: 2,899,950 | AVG: 1,712,314,043
MIN: 1,712,314,001
MAX: 1,712,314,175 | AVG: 1,322,034,101
MIN: 1,322,034,066
MAX: 1,322,034,132 | | aimer256s (10 executions) | mem_opt | AVG: 3,344,262
MIN: 3,344,252
MAX: 3,344,293 | AVG: 1,752,719,642
MIN: 1,752,719,422
MAX: 1,752,720,844 | AVG: 1,361,337,862
MIN: 1,361,336,718
MAX: 1,361,338,013 | -| ascon-sign-128f-robust (10 executions) | ref | AVG: 122,506,162
MIN: 122,506,099
MAX: 122,506,254 | AVG: 2,855,797,836
MIN: 2,855,797,243
MAX: 2,855,798,602 | AVG: 174,707,763
MIN: 169,973,472
MAX: 179,525,137 | -| ascon-sign-128f-simple (10 executions) | ref | AVG: 69,376,878
MIN: 69,376,875
MAX: 69,376,883 | AVG: 1,629,111,557
MIN: 1,629,111,334
MAX: 1,629,112,028 | AVG: 97,798,317
MIN: 95,509,050
MAX: 98,714,007 | -| ascon-sign-128s-robust (10 executions) | ref | AVG: 7,842,366,557
MIN: 7,842,366,432
MAX: 7,842,366,620 | AVG: 59,267,552,580
MIN: 59,267,543,517
MAX: 59,267,565,672 | AVG: 60,232,378
MIN: 57,865,239
MAX: 62,848,708 | -| ascon-sign-128s-simple (10 executions) | ref | AVG: 4,441,129,007
MIN: 4,441,128,624
MAX: 4,441,129,583 | AVG: 33,877,719,255
MIN: 33,877,704,467
MAX: 33,877,739,518 | AVG: 33,665,713
MIN: 31,101,669
MAX: 34,993,483 | -| ascon-sign-192f-robust (10 executions) | ref | AVG: 222,614,206
MIN: 222,614,156
MAX: 222,614,345 | AVG: 5,712,962,198
MIN: 5,712,960,682
MAX: 5,712,963,829 | AVG: 321,026,499
MIN: 315,341,414
MAX: 327,745,233 | -| ascon-sign-192f-simple (10 executions) | ref | AVG: 128,167,067
MIN: 128,167,038
MAX: 128,167,083 | AVG: 3,345,487,807
MIN: 3,345,484,178
MAX: 3,345,492,588 | AVG: 179,328,421
MIN: 175,094,665
MAX: 183,794,127 | -| ascon-sign-192s-robust (10 executions) | ref | AVG: 14,249,838,562
MIN: 14,249,837,693
MAX: 14,249,840,118 | AVG: 126,646,612,223
MIN: 126,646,594,160
MAX: 126,646,651,564 | AVG: 111,451,290
MIN: 108,763,808
MAX: 114,965,691 | -| ascon-sign-192s-simple (10 executions) | ref | AVG: 8,204,011,592
MIN: 8,204,011,246
MAX: 8,204,011,971 | AVG: 74,760,768,141
MIN: 74,760,751,354
MAX: 74,760,789,761 | AVG: 61,679,880
MIN: 58,983,014
MAX: 64,202,741 | -| biscuit128f (10 executions) | ref | AVG: 1,054,719
MIN: 1,054,719
MAX: 1,054,720 | AVG: 274,072,426
MIN: 274,072,411
MAX: 274,072,461 | AVG: 254,371,114
MIN: 254,371,087
MAX: 254,371,140 | -| biscuit192f (10 executions) | ref | AVG: 1,886,203
MIN: 1,886,199
MAX: 1,886,238 | AVG: 765,314,258
MIN: 765,314,227
MAX: 765,314,291 | AVG: 713,412,502
MIN: 713,412,394
MAX: 713,412,608 | -| biscuit256f (10 executions) | ref | AVG: 3,301,990
MIN: 3,301,983
MAX: 3,302,022 | AVG: 1,747,187,940
MIN: 1,747,187,918
MAX: 1,747,187,973 | AVG: 1,678,998,604
MIN: 1,678,998,013
MAX: 1,678,998,987 | | cross-sha2-r-sdp-1-fast (10 executions) | ref | AVG: 5,614,888
MIN: 5,590,276
MAX: 5,650,611 | AVG: 216,566,013
MIN: 215,745,202
MAX: 217,395,250 | AVG: 143,008,126
MIN: 141,803,162
MAX: 144,002,548 | | cross-sha2-r-sdp-3-fast (10 executions) | ref | AVG: 8,201,340
MIN: 8,148,672
MAX: 8,208,465 | AVG: 241,899,820
MIN: 241,815,860
MAX: 242,049,039 | AVG: 123,896,179
MIN: 123,524,606
MAX: 124,545,760 | | cross-sha2-r-sdpg-1-fast (10 executions) | ref | AVG: 2,151,163
MIN: 2,115,797
MAX: 2,174,685 | AVG: 116,162,852
MIN: 116,120,174
MAX: 116,181,821 | AVG: 87,741,423
MIN: 87,209,686
MAX: 88,267,494 | @@ -94,8 +83,6 @@ | mayo2 (10 executions) | m4f | AVG: 11,917,959
MIN: 11,917,940
MAX: 11,917,980 | AVG: 11,979,613
MIN: 11,979,582
MAX: 11,979,624 | AVG: 5,130,148
MIN: 5,130,131
MAX: 5,130,180 | | mayo2 (10 executions) | ref | AVG: 18,432,706
MIN: 18,432,701
MAX: 18,432,740 | AVG: 23,546,659
MIN: 23,546,640
MAX: 23,546,680 | AVG: 5,494,246
MIN: 5,494,236
MAX: 5,494,276 | | mayo3 (10 executions) | m4f | AVG: 18,946,738
MIN: 18,946,737
MAX: 18,946,740 | AVG: 32,477,408
MIN: 32,477,407
MAX: 32,477,411 | AVG: 16,852,927
MIN: 16,852,799
MAX: 16,853,047 | -| meds13220 (10 executions) | ref | AVG: 47,801,890
MIN: 47,796,259
MAX: 47,805,424 | AVG: 1,774,401,869
MIN: 1,773,011,038
MAX: 1,779,733,959 | AVG: 1,767,764,521
MIN: 1,766,326,468
MAX: 1,773,152,168 | -| meds55604 (10 executions) | ref | AVG: 253,603,604
MIN: 253,590,695
MAX: 253,615,749 | AVG: 8,009,948,412
MIN: 8,009,909,000
MAX: 8,009,995,748 | AVG: 8,320,756,990
MIN: 8,320,682,364
MAX: 8,320,835,448 | | mirith_IIIa_fast (10 executions) | ref | AVG: 3,009,088
MIN: 3,009,084
MAX: 3,009,123 | AVG: 891,195,817
MIN: 891,191,657
MAX: 891,198,221 | AVG: 831,725,932
MIN: 831,697,264
MAX: 831,742,620 | | mirith_IIIb_fast (10 executions) | ref | AVG: 4,565,011
MIN: 4,565,007
MAX: 4,565,046 | AVG: 1,298,812,706
MIN: 1,298,810,546
MAX: 1,298,815,343 | AVG: 1,214,260,655
MIN: 1,214,247,570
MAX: 1,214,277,229 | | mirith_Ia_fast (10 executions) | ref | AVG: 1,303,728
MIN: 1,303,721
MAX: 1,303,764 | AVG: 296,732,107
MIN: 296,728,990
MAX: 296,734,109 | AVG: 276,059,526
MIN: 276,031,297
MAX: 276,080,171 | @@ -154,12 +141,6 @@ | snova-28-17-16-2-esk (10 executions) | ref | AVG: 51,177,590
MIN: 51,177,548
MAX: 51,177,647 | AVG: 23,387,139
MIN: 21,270,788
MAX: 42,311,786 | AVG: 19,180,389
MIN: 19,180,360
MAX: 19,180,440 | | snova-28-17-16-2-ssk (10 executions) | ref | AVG: 51,065,038
MIN: 51,064,999
MAX: 51,065,086 | AVG: 52,865,514
MIN: 50,757,388
MAX: 71,788,606 | AVG: 19,180,379
MIN: 19,180,357
MAX: 19,180,425 | | snova-37-8-16-4-ssk (10 executions) | ref | AVG: 122,023,801
MIN: 122,023,399
MAX: 122,024,216 | AVG: 533,063,912
MIN: 533,033,960
MAX: 533,090,127 | AVG: 335,806,349
MIN: 335,805,890
MAX: 335,806,820 | -| sphincs-a-sha2-128f (10 executions) | ref | AVG: 30,278,936
MIN: 30,278,762
MAX: 30,279,211 | AVG: 382,270,810
MIN: 382,269,421
MAX: 382,271,497 | AVG: 35,695,646
MIN: 35,693,840
MAX: 35,698,828 | -| sphincs-a-sha2-128s (10 executions) | ref | AVG: 814,836,852
MIN: 814,834,574
MAX: 814,838,039 | AVG: 6,981,930,727
MIN: 6,981,924,687
MAX: 6,981,936,443 | AVG: 187,090,082
MIN: 187,087,928
MAX: 187,093,600 | -| sphincs-a-sha2-192f (10 executions) | ref | AVG: 45,930,664
MIN: 45,930,481
MAX: 45,930,983 | AVG: 634,374,072
MIN: 634,373,011
MAX: 634,375,225 | AVG: 35,145,783
MIN: 35,144,266
MAX: 35,146,607 | -| sphincs-a-shake-128f (10 executions) | ref | AVG: 61,578,406
MIN: 61,578,107
MAX: 61,578,885 | AVG: 1,188,147,363
MIN: 1,188,146,489
MAX: 1,188,148,063 | AVG: 76,330,135
MIN: 76,328,602
MAX: 76,331,478 | -| sphincs-a-shake-128s (10 executions) | ref | AVG: 2,342,298,427
MIN: 2,342,296,403
MAX: 2,342,299,607 | AVG: 22,926,754,899
MIN: 22,926,752,978
MAX: 22,926,758,555 | AVG: 241,835,141
MIN: 241,830,735
MAX: 241,838,908 | -| sphincs-a-shake-192f (10 executions) | ref | AVG: 110,027,677
MIN: 110,027,323
MAX: 110,027,950 | AVG: 1,814,954,350
MIN: 1,814,953,585
MAX: 1,814,955,913 | AVG: 64,022,276
MIN: 64,020,853
MAX: 64,023,988 | | sphincs-sha2-128f-simple (10 executions) | clean | AVG: 15,742,990
MIN: 15,742,958
MAX: 15,742,996 | AVG: 368,575,228
MIN: 368,575,193
MAX: 368,575,246 | AVG: 21,923,628
MIN: 21,369,867
MAX: 22,456,717 | | sphincs-sha2-128s-simple (10 executions) | clean | AVG: 1,007,731,522
MIN: 1,007,731,504
MAX: 1,007,731,551 | AVG: 7,657,558,168
MIN: 7,657,558,117
MAX: 7,657,558,212 | AVG: 7,471,794
MIN: 7,228,491
MAX: 7,797,915 | | sphincs-sha2-192f-simple (10 executions) | clean | AVG: 23,570,224
MIN: 23,570,214
MAX: 23,570,257 | AVG: 666,398,438
MIN: 666,398,401
MAX: 666,398,468 | AVG: 35,457,937
MIN: 35,087,854
MAX: 35,973,969 | @@ -216,17 +197,6 @@ | aimer256s | m4speed | 50,032 | 615,856 | 116,936 | | aimer256s | m4stack | 50,032 | 76,032 | 116,936 | | aimer256s | mem_opt | 50,040 | 76,140 | 117,044 | -| ascon-sign-128f-robust | ref | 3,260 | 2,772 | 2,992 | -| ascon-sign-128f-simple | ref | 2,632 | 2,144 | 2,448 | -| ascon-sign-128s-robust | ref | 3,452 | 2,916 | 2,240 | -| ascon-sign-128s-simple | ref | 2,824 | 2,268 | 1,752 | -| ascon-sign-192f-robust | ref | 6,092 | 4,924 | 4,504 | -| ascon-sign-192f-simple | ref | 4,808 | 3,640 | 3,704 | -| ascon-sign-192s-robust | ref | 6,380 | 5,116 | 4,332 | -| ascon-sign-192s-simple | ref | 5,096 | 3,812 | 3,048 | -| biscuit128f | ref | 600 | 137,348 | 14,560 | -| biscuit192f | ref | 640 | 265,964 | 20,796 | -| biscuit256f | ref | 720 | 477,468 | 33,108 | | cross-sha2-r-sdp-1-fast | ref | 5,200 | 218,304 | 105,604 | | cross-sha2-r-sdp-3-fast | ref | 9,920 | 324,764 | 158,132 | | cross-sha2-r-sdpg-1-fast | ref | 2,760 | 130,824 | 69,536 | @@ -268,8 +238,6 @@ | mayo2 | m4f | 111,532 | 124,644 | 278,444 | | mayo2 | ref | 111,532 | 238,324 | 270,260 | | mayo3 | m4f | 244,748 | 340,668 | 469,780 | -| meds13220 | ref | 44,000 | 180,404 | 47,716 | -| meds55604 | ref | 162,196 | 392,852 | 160,324 | | mirith_IIIa_fast | ref | 21,832 | 266,480 | 46,156 | | mirith_IIIb_fast | ref | 32,872 | 298,208 | 59,172 | | mirith_Ia_fast | ref | 10,208 | 122,424 | 22,836 | @@ -328,12 +296,6 @@ | snova-28-17-16-2-esk | ref | 309,216 | 127,232 | 199,684 | | snova-28-17-16-2-ssk | ref | 309,216 | 309,356 | 199,684 | | snova-37-8-16-4-ssk | ref | 640,324 | 640,428 | 411,516 | -| sphincs-a-sha2-128f | ref | 281,168 | 280,772 | 280,656 | -| sphincs-a-sha2-128s | ref | 585,984 | 585,732 | 585,396 | -| sphincs-a-sha2-192f | ref | 504,084 | 502,636 | 502,356 | -| sphincs-a-shake-128f | ref | 281,072 | 280,676 | 280,560 | -| sphincs-a-shake-128s | ref | 585,888 | 585,636 | 585,264 | -| sphincs-a-shake-192f | ref | 503,544 | 502,092 | 501,816 | | sphincs-sha2-128f-simple | clean | 2,856 | 2,468 | 2,664 | | sphincs-sha2-128s-simple | clean | 3,084 | 2,556 | 1,968 | | sphincs-sha2-192f-simple | clean | 5,468 | 4,404 | 4,356 | @@ -346,7 +308,6 @@ | sphincs-shake-192s-simple | clean | 5,252 | 3,996 | 3,160 | | sphincs-shake-256f-simple | clean | 7,928 | 5,876 | 5,448 | | sphincs-shake-256s-simple | clean | 8,220 | 6,004 | 5,048 | -| tuov_v | ref | 503,544 | 502,092 | 501,816 | # Hashing Evaluation ## Key Encapsulation Schemes | Scheme | Implementation | Key Generation [%] | Encapsulation [%] | Decapsulation [%] | @@ -391,17 +352,6 @@ | aimer256s | m4speed | 67.7% | 32.2% | 28.0% | | aimer256s | m4stack | 67.7% | 43.3% | 28.0% | | aimer256s | mem_opt | 58.9% | 42.4% | 27.2% | -| ascon-sign-128f-robust | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-128f-simple | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-128s-robust | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-128s-simple | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-192f-robust | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-192f-simple | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-192s-robust | ref | 0.0% | 0.0% | 0.0% | -| ascon-sign-192s-simple | ref | 0.0% | 0.0% | 0.0% | -| biscuit128f | ref | 54.3% | 9.7% | 8.9% | -| biscuit192f | ref | 54.0% | 6.0% | 5.5% | -| biscuit256f | ref | 54.0% | 4.4% | 4.2% | | cross-sha2-r-sdp-1-fast | ref | 90.2% | 86.3% | 91.0% | | cross-sha2-r-sdp-3-fast | ref | 86.5% | 79.8% | 81.7% | | cross-sha2-r-sdpg-1-fast | ref | 92.9% | 90.9% | 92.1% | @@ -443,8 +393,6 @@ | mayo2 | m4f | 35.2% | 35.5% | 81.2% | | mayo2 | ref | 22.8% | 18.1% | 75.8% | | mayo3 | m4f | 55.4% | 32.6% | 62.2% | -| meds13220 | ref | 2.5% | 5.1% | 4.8% | -| meds55604 | ref | 1.6% | 3.0% | 2.9% | | mirith_IIIa_fast | ref | 64.3% | 6.7% | 6.5% | | mirith_IIIb_fast | ref | 64.5% | 4.7% | 4.6% | | mirith_Ia_fast | ref | 61.4% | 10.1% | 9.7% | @@ -503,12 +451,6 @@ | snova-28-17-16-2-esk | ref | 10.6% | 0.2% | 28.1% | | snova-28-17-16-2-ssk | ref | 10.6% | 10.7% | 28.1% | | snova-37-8-16-4-ssk | ref | 8.8% | 2.0% | 3.4% | -| sphincs-a-sha2-128f | ref | 43.3% | 86.6% | 48.2% | -| sphincs-a-sha2-128s | ref | 72.9% | 88.3% | 11.7% | -| sphincs-a-sha2-192f | ref | 57.5% | 88.3% | 46.0% | -| sphincs-a-shake-128f | ref | 72.3% | 96.2% | 76.0% | -| sphincs-a-shake-128s | ref | 90.9% | 96.9% | 31.8% | -| sphincs-a-shake-192f | ref | 82.6% | 96.5% | 70.7% | | sphincs-sha2-128f-simple | clean | 90.8% | 90.7% | 90.6% | | sphincs-sha2-128s-simple | clean | 90.8% | 90.7% | 90.4% | | sphincs-sha2-192f-simple | clean | 90.2% | 90.8% | 90.7% | @@ -565,17 +507,6 @@ | aimer256s | m4speed | 26,372 | 0 | 0 | 26,372 | | aimer256s | m4stack | 25,928 | 0 | 0 | 25,928 | | aimer256s | mem_opt | 27,636 | 0 | 0 | 27,636 | -| ascon-sign-128f-robust | ref | 17,664 | 0 | 0 | 17,664 | -| ascon-sign-128f-simple | ref | 17,596 | 0 | 0 | 17,596 | -| ascon-sign-128s-robust | ref | 17,972 | 0 | 0 | 17,972 | -| ascon-sign-128s-simple | ref | 17,904 | 0 | 0 | 17,904 | -| ascon-sign-192f-robust | ref | 17,960 | 0 | 0 | 17,960 | -| ascon-sign-192f-simple | ref | 17,912 | 0 | 0 | 17,912 | -| ascon-sign-192s-robust | ref | 18,472 | 0 | 0 | 18,472 | -| ascon-sign-192s-simple | ref | 18,424 | 0 | 0 | 18,424 | -| biscuit128f | ref | 7,580 | 0 | 0 | 7,580 | -| biscuit192f | ref | 7,780 | 0 | 0 | 7,780 | -| biscuit256f | ref | 8,216 | 0 | 0 | 8,216 | | cross-sha2-r-sdp-1-fast | ref | 14,244 | 0 | 104 | 14,348 | | cross-sha2-r-sdp-3-fast | ref | 14,744 | 0 | 128 | 14,872 | | cross-sha2-r-sdpg-1-fast | ref | 18,409 | 0 | 104 | 18,513 | @@ -617,8 +548,6 @@ | mayo2 | m4f | 17,292 | 8 | 0 | 17,300 | | mayo2 | ref | 24,404 | 8 | 0 | 24,412 | | mayo3 | m4f | 23,612 | 8 | 0 | 23,620 | -| meds13220 | ref | 16,844 | 0 | 0 | 16,844 | -| meds55604 | ref | 9,012 | 0 | 0 | 9,012 | | mirith_IIIa_fast | ref | 7,720 | 256 | 0 | 7,976 | | mirith_IIIb_fast | ref | 7,760 | 256 | 0 | 8,016 | | mirith_Ia_fast | ref | 7,610 | 256 | 0 | 7,866 | @@ -677,12 +606,6 @@ | snova-28-17-16-2-esk | ref | 16,436 | 0 | 280 | 16,716 | | snova-28-17-16-2-ssk | ref | 16,436 | 0 | 280 | 16,716 | | snova-37-8-16-4-ssk | ref | 52,440 | 0 | 336 | 52,776 | -| sphincs-a-sha2-128f | ref | 6,343 | 0 | 0 | 6,343 | -| sphincs-a-sha2-128s | ref | 6,899 | 0 | 0 | 6,899 | -| sphincs-a-sha2-192f | ref | 6,867 | 0 | 0 | 6,867 | -| sphincs-a-shake-128f | ref | 5,552 | 0 | 0 | 5,552 | -| sphincs-a-shake-128s | ref | 6,108 | 0 | 0 | 6,108 | -| sphincs-a-shake-192f | ref | 5,916 | 0 | 0 | 5,916 | | sphincs-sha2-128f-simple | clean | 4,956 | 0 | 0 | 4,956 | | sphincs-sha2-128s-simple | clean | 5,264 | 0 | 0 | 5,264 | | sphincs-sha2-192f-simple | clean | 5,444 | 0 | 0 | 5,444 | diff --git a/mupq b/mupq index 8e62b94b..21dbaf66 160000 --- a/mupq +++ b/mupq @@ -1 +1 @@ -Subproject commit 8e62b94bfb8125fc81ac2774f8aa8b44120bc619 +Subproject commit 21dbaf66627cbb3ac326e4b695a70b13e21d3914 diff --git a/skiplist.py b/skiplist.py index ae2c41ce..4ae65098 100644 --- a/skiplist.py +++ b/skiplist.py @@ -17,12 +17,12 @@ {'scheme': 'aimer256s', 'implementation': 'm4speed', 'estmemory': 633856}, {'scheme': 'aimer128f', 'implementation': 'm4stack', 'estmemory': 22528}, {'scheme': 'aimer128f', 'implementation': 'm4speed', 'estmemory': 131072}, - {'scheme': 'aimer192s_mem', 'implementation': 'mem_opt', 'estmemory': 70656}, - {'scheme': 'aimer192f_mem', 'implementation': 'mem_opt', 'estmemory': 46080}, - {'scheme': 'aimer128s_mem', 'implementation': 'mem_opt', 'estmemory': 39936}, - {'scheme': 'aimer256f_mem', 'implementation': 'mem_opt', 'estmemory': 105472}, - {'scheme': 'aimer256s_mem', 'implementation': 'mem_opt', 'estmemory': 135168}, - {'scheme': 'aimer128f_mem', 'implementation': 'mem_opt', 'estmemory': 22528}, + {'scheme': 'aimer192s', 'implementation': 'mem_opt', 'estmemory': 70656}, + {'scheme': 'aimer192f', 'implementation': 'mem_opt', 'estmemory': 46080}, + {'scheme': 'aimer128s', 'implementation': 'mem_opt', 'estmemory': 39936}, + {'scheme': 'aimer256f', 'implementation': 'mem_opt', 'estmemory': 105472}, + {'scheme': 'aimer256s', 'implementation': 'mem_opt', 'estmemory': 135168}, + {'scheme': 'aimer128f', 'implementation': 'mem_opt', 'estmemory': 22528}, {'scheme': 'ascon-sign-128f-robust', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128f-simple', 'implementation': 'ref', 'estmemory': 21504}, {'scheme': 'ascon-sign-128s-robust', 'implementation': 'ref', 'estmemory': 12288}, @@ -35,12 +35,6 @@ {'scheme': 'bikel1', 'implementation': 'opt', 'estmemory': 90112}, {'scheme': 'bikel3', 'implementation': 'm4f', 'estmemory': 194560}, {'scheme': 'bikel3', 'implementation': 'opt', 'estmemory': 175104}, - {'scheme': 'biscuit128f', 'implementation': 'ref', 'estmemory': 145408}, - {'scheme': 'biscuit128s', 'implementation': 'ref', 'estmemory': 1099776}, - {'scheme': 'biscuit192f', 'implementation': 'ref', 'estmemory': 282624}, - {'scheme': 'biscuit192s', 'implementation': 'ref', 'estmemory': 2257920}, - {'scheme': 'biscuit256f', 'implementation': 'ref', 'estmemory': 505856}, - {'scheme': 'biscuit256s', 'implementation': 'ref', 'estmemory': 4004864}, {'scheme': 'cross-sha2-r-sdp-1-fast', 'implementation': 'ref', 'estmemory': 234496}, {'scheme': 'cross-sha2-r-sdp-1-small', 'implementation': 'ref', 'estmemory': 721920}, {'scheme': 'cross-sha2-r-sdp-3-fast', 'implementation': 'ref', 'estmemory': 365568}, @@ -115,12 +109,6 @@ {'scheme': 'mceliece6960119f', 'implementation': 'clean', 'estmemory': 2586624}, {'scheme': 'mceliece8192128', 'implementation': 'clean', 'estmemory': 3259392}, {'scheme': 'mceliece8192128f', 'implementation': 'clean', 'estmemory': 3260416}, - {'scheme': 'meds13220', 'implementation': 'ref', 'estmemory': 209920}, - {'scheme': 'meds134180', 'implementation': 'ref', 'estmemory': 1152000}, - {'scheme': 'meds167717', 'implementation': 'ref', 'estmemory': 927744}, - {'scheme': 'meds41711', 'implementation': 'ref', 'estmemory': 1387520}, - {'scheme': 'meds55604', 'implementation': 'ref', 'estmemory': 509952}, - {'scheme': 'meds9923', 'implementation': 'ref', 'estmemory': 1019904}, {'scheme': 'mirith_IIIa_fast', 'implementation': 'ref', 'estmemory': 287744}, {'scheme': 'mirith_IIIa_short', 'implementation': 'ref', 'estmemory': 2197504}, {'scheme': 'mirith_IIIb_fast', 'implementation': 'ref', 'estmemory': 320512}, @@ -213,18 +201,6 @@ {'scheme': 'snova-61-33-16-2-ssk', 'implementation': 'ref', 'estmemory': 2717696}, {'scheme': 'snova-66-15-16-3-esk', 'implementation': 'ref', 'estmemory': 2617344}, {'scheme': 'snova-66-15-16-3-ssk', 'implementation': 'ref', 'estmemory': 2185216}, - {'scheme': 'sphincs-a-sha2-128f', 'implementation': 'ref', 'estmemory': 301056}, - {'scheme': 'sphincs-a-sha2-128s', 'implementation': 'ref', 'estmemory': 595968}, - {'scheme': 'sphincs-a-sha2-192f', 'implementation': 'ref', 'estmemory': 542720}, - {'scheme': 'sphincs-a-sha2-192s', 'implementation': 'ref', 'estmemory': 1307648}, - {'scheme': 'sphincs-a-sha2-256f', 'implementation': 'ref', 'estmemory': 1124352}, - {'scheme': 'sphincs-a-sha2-256s', 'implementation': 'ref', 'estmemory': 2291712}, - {'scheme': 'sphincs-a-shake-128f', 'implementation': 'ref', 'estmemory': 301056}, - {'scheme': 'sphincs-a-shake-128s', 'implementation': 'ref', 'estmemory': 595968}, - {'scheme': 'sphincs-a-shake-192f', 'implementation': 'ref', 'estmemory': 541696}, - {'scheme': 'sphincs-a-shake-192s', 'implementation': 'ref', 'estmemory': 1306624}, - {'scheme': 'sphincs-a-shake-256f', 'implementation': 'ref', 'estmemory': 1124352}, - {'scheme': 'sphincs-a-shake-256s', 'implementation': 'ref', 'estmemory': 2291712}, {'scheme': 'sphincs-sha2-128f-simple', 'implementation': 'clean', 'estmemory': 21504}, {'scheme': 'sphincs-sha2-128s-simple', 'implementation': 'clean', 'estmemory': 12288}, {'scheme': 'sphincs-sha2-192f-simple', 'implementation': 'clean', 'estmemory': 43008}, @@ -237,17 +213,6 @@ {'scheme': 'sphincs-shake-192s-simple', 'implementation': 'clean', 'estmemory': 22528}, {'scheme': 'sphincs-shake-256f-simple', 'implementation': 'clean', 'estmemory': 59392}, {'scheme': 'sphincs-shake-256s-simple', 'implementation': 'clean', 'estmemory': 38912}, - {'scheme': 'tuov_iii', 'implementation': 'ref', 'estmemory': 3281920}, - {'scheme': 'tuov_iii_pkc', 'implementation': 'ref', 'estmemory': 3468288}, - {'scheme': 'tuov_iii_pkc_skc', 'implementation': 'ref', 'estmemory': 3790848}, - {'scheme': 'tuov_ip', 'implementation': 'ref', 'estmemory': 3790848}, - {'scheme': 'tuov_ip_pkc', 'implementation': 'ref', 'estmemory': 799744}, - {'scheme': 'tuov_ip_pkc_skc', 'implementation': 'ref', 'estmemory': 865280}, - {'scheme': 'tuov_is', 'implementation': 'ref', 'estmemory': 1111040}, - {'scheme': 'tuov_is_pkc', 'implementation': 'ref', 'estmemory': 1176576}, - {'scheme': 'tuov_is_pkc_skc', 'implementation': 'ref', 'estmemory': 1275904}, - {'scheme': 'tuov_v_pkc', 'implementation': 'ref', 'estmemory': 7083008}, - {'scheme': 'tuov_v_pkc_skc', 'implementation': 'ref', 'estmemory': 4639744}, {'scheme': 'falcon-padded-1024', 'implementation': 'clean', 'estmemory': 91136}, {'scheme': 'falcon-padded-512', 'implementation': 'clean', 'estmemory': 48128}, {'scheme': 'ml-dsa-87', 'implementation': 'm4fstack', 'estmemory': 21504}, From 40f33ea1d28309e75c228fd1b8731ed0001311fa Mon Sep 17 00:00:00 2001 From: Amin Abdulrahman Date: Tue, 12 Nov 2024 09:54:06 +0100 Subject: [PATCH 104/107] Full ram for ml-dsa-87 on stm32f4discovery (#368) --- mk/stm32f4discovery.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/stm32f4discovery.mk b/mk/stm32f4discovery.mk index f69ee7db..4be2c2cf 100644 --- a/mk/stm32f4discovery.mk +++ b/mk/stm32f4discovery.mk @@ -25,7 +25,7 @@ elf/boardtest-fast.elf: CPPFLAGS+=-DSRAM_TIMING_TEST -DHAS_SRAM2 -DHAS_CCM elf/crypto_kem_frodokem640aes_m4_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/mupq_pqclean_crypto_kem_frodokem640shake_opt_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld -elf/crypto_sign_dilithium5_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld +elf/crypto_sign_ml-dsa-87_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/crypto_sign_perk-256-%_m4_testvectors.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/crypto_sign_perk-256-fast%_m4_test.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld elf/crypto_sign_haetae5_m4f_%.elf: LDSCRIPT=ldscripts/stm32f4discovery_fullram.ld From 4a980373f96b68a4237c7959918d224cd4062c37 Mon Sep 17 00:00:00 2001 From: vincentvbh Date: Fri, 22 Nov 2024 12:25:01 +0100 Subject: [PATCH 105/107] map to canonical --- crypto_kem/ml-kem-512/m4fspeed/poly.c | 1 + crypto_kem/ml-kem-512/m4fstack/poly.c | 1 + crypto_kem/ml-kem-768/m4fspeed/poly.c | 9 +++++---- crypto_kem/ml-kem-768/m4fstack/poly.c | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crypto_kem/ml-kem-512/m4fspeed/poly.c b/crypto_kem/ml-kem-512/m4fspeed/poly.c index 401b26b7..5a6d0abb 100644 --- a/crypto_kem/ml-kem-512/m4fspeed/poly.c +++ b/crypto_kem/ml-kem-512/m4fspeed/poly.c @@ -366,6 +366,7 @@ void poly_tobytes(unsigned char *r, poly *a) { int i; uint16_t t0, t1; + poly_reduce(a); poly_reduce(a); for (i = 0; i < KYBER_N / 2; i++) { diff --git a/crypto_kem/ml-kem-512/m4fstack/poly.c b/crypto_kem/ml-kem-512/m4fstack/poly.c index 443fdbae..ed54ec87 100644 --- a/crypto_kem/ml-kem-512/m4fstack/poly.c +++ b/crypto_kem/ml-kem-512/m4fstack/poly.c @@ -366,6 +366,7 @@ void poly_tobytes(unsigned char *r, poly *a) { int i; uint16_t t0, t1; + poly_reduce(a); poly_reduce(a); for (i = 0; i < KYBER_N / 2; i++) { diff --git a/crypto_kem/ml-kem-768/m4fspeed/poly.c b/crypto_kem/ml-kem-768/m4fspeed/poly.c index b52060f9..b909a85c 100644 --- a/crypto_kem/ml-kem-768/m4fspeed/poly.c +++ b/crypto_kem/ml-kem-768/m4fspeed/poly.c @@ -142,7 +142,7 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { d0 >>= 31; t[k] = d0 & 0x7ff; } - + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -366,6 +366,7 @@ void poly_tobytes(unsigned char *r, poly *a) { int i; uint16_t t0, t1; + poly_reduce(a); poly_reduce(a); for (i = 0; i < KYBER_N / 2; i++) { @@ -465,7 +466,7 @@ void poly_noise(poly *r, const unsigned char *seed, unsigned char nonce, int add * Using strategy of better accumulation (initial step). * Arguments: - const poly *a: pointer to input polynomial * - const poly *b: pointer to input polynomial -* - const poly *a_prime: pointer to a pre-multiplied by zetas +* - const poly *a_prime: pointer to a pre-multiplied by zetas * - int32_t *r_tmp: array for accumulating unreduced results **************************************************/ extern void basemul_asm_opt_16_32(int32_t *, const int16_t *, const int16_t *, const int16_t *); @@ -481,7 +482,7 @@ void poly_basemul_opt_16_32(int32_t *r_tmp, const poly *a, const poly *b, const * Using strategy of better accumulation. * Arguments: - const poly *a: pointer to input polynomial * - const poly *b: pointer to input polynomial -* - const poly *a_prime: pointer to a pre-multiplied by zetas +* - const poly *a_prime: pointer to a pre-multiplied by zetas * - int32_t *r_tmp: array for accumulating unreduced results **************************************************/ extern void basemul_asm_acc_opt_32_32(int32_t *, const int16_t *, const int16_t *, const int16_t *); @@ -497,7 +498,7 @@ void poly_basemul_acc_opt_32_32(int32_t *r_tmp, const poly *a, const poly *b, co * Using strategy of better accumulation (final step). * Arguments: - const poly *a: pointer to input polynomial * - const poly *b: pointer to input polynomial -* - const poly *a_prime: pointer to a pre-multiplied by zetas +* - const poly *a_prime: pointer to a pre-multiplied by zetas * - poly *r: pointer to output polynomial * - int32_t *r_tmp: array for accumulating unreduced results **************************************************/ diff --git a/crypto_kem/ml-kem-768/m4fstack/poly.c b/crypto_kem/ml-kem-768/m4fstack/poly.c index 35475adb..fb13d155 100644 --- a/crypto_kem/ml-kem-768/m4fstack/poly.c +++ b/crypto_kem/ml-kem-768/m4fstack/poly.c @@ -142,7 +142,7 @@ void poly_packcompress(unsigned char *r, poly *a, int i) { d0 >>= 31; t[k] = d0 & 0x7ff; } - + r[352*i+11*j+ 0] = t[0] & 0xff; r[352*i+11*j+ 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3); @@ -366,6 +366,7 @@ void poly_tobytes(unsigned char *r, poly *a) { int i; uint16_t t0, t1; + poly_reduce(a); poly_reduce(a); for (i = 0; i < KYBER_N / 2; i++) { From 4af91da4a82864e107861db1d06204096580d486 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 28 Nov 2024 13:14:17 +0800 Subject: [PATCH 106/107] add ml-kem benchmarks --- benchmarks.csv | 48 ++++++++++++++++++++++++------------------------ benchmarks.md | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/benchmarks.csv b/benchmarks.csv index ddfa372d..4bc2981a 100644 --- a/benchmarks.csv +++ b/benchmarks.csv @@ -8,15 +8,15 @@ bikel3 (10 executions),opt,248083316,248083286,248083345,16405238,16405236,16405 hqc-128 (10 executions),clean,52705201,52705180,52705224,105650897,105650877,105650927,159569179,159569176,159569183 hqc-192 (10 executions),clean,161458617,161458590,161458638,323146261,323146250,323146292,486156251,486156214,486156266 hqc-256 (10 executions),clean,295934078,295934057,295934104,591853870,591853850,591853898,891163005,891162988,891163038 -ml-kem-1024 (10 executions),clean,1540607,1535678,1547404,1712361,1707431,1719164,2024616,2019674,2031410 -ml-kem-1024 (10 executions),m4fspeed,1007759,1004549,1017159,1030702,1027443,1040101,1093153,1089895,1102552 -ml-kem-1024 (10 executions),m4fstack,1010100,1007459,1018999,1038190,1035550,1047090,1101234,1098594,1110134 -ml-kem-512 (10 executions),clean,595882,595636,596329,700689,700440,701134,888740,888494,889189 -ml-kem-512 (10 executions),m4fspeed,388544,387190,398814,392178,390825,402445,429456,428102,439722 -ml-kem-512 (10 executions),m4fstack,386999,386677,387465,392813,392492,393280,430152,429831,430619 -ml-kem-768 (10 executions),clean,990901,986123,997663,1140412,1135630,1147169,1390176,1385399,1396936 -ml-kem-768 (10 executions),m4fspeed,631949,631658,632164,656369,656082,656596,705436,705148,705663 -ml-kem-768 (10 executions),m4fstack,634227,632761,644635,662468,661003,672877,711996,710530,722405 +ml-kem-1024 (10 executions),clean,1536343,1535750,1536698,1708071,1707476,1708427,2020327,2019721,2020672 +ml-kem-1024 (10 executions),m4fspeed,1018976,1014877,1026934,1031565,1027454,1039544,1094008,1089897,1101987 +ml-kem-1024 (10 executions),m4fstack,1020202,1017478,1029553,1037953,1035260,1047298,1100982,1098251,1110327 +ml-kem-512 (10 executions),clean,595793,595576,595971,700605,700383,700779,888653,888436,888831 +ml-kem-512 (10 executions),m4fspeed,392423,392211,392614,390881,390671,391073,428167,427955,428357 +ml-kem-512 (10 executions),m4fstack,392224,391772,392541,392864,392407,393181,430202,429745,430519 +ml-kem-768 (10 executions),clean,988722,985880,998135,1138225,1135419,1147634,1387984,1385144,1397397 +ml-kem-768 (10 executions),m4fspeed,642096,639116,651103,658754,655785,667769,707827,704858,716842 +ml-kem-768 (10 executions),m4fstack,644195,640433,652374,664654,660893,672834,714194,710433,722374 Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [cycles] (mean),Key Generation [cycles] (min),Key Generation [cycles] (max),Sign [cycles] (mean),Sign [cycles] (min),Sign [cycles] (max),Verify [cycles] (mean),Verify [cycles] (min),Verify [cycles] (max) aimer128f (10 executions),m4speed,490087,490087,490088,28590420,28590395,28590439,26750578,26749771,26751014 @@ -315,15 +315,15 @@ bikel3,opt,0.0,6.3,0.2,,,,,, hqc-128,clean,0.4,0.8,0.5,,,,,, hqc-192,clean,0.3,0.5,0.3,,,,,, hqc-256,clean,0.2,0.4,0.3,,,,,, -ml-kem-1024,clean,50.0,45.6,38.6,,,,,, -ml-kem-1024,m4fspeed,76.1,75.5,71.2,,,,,, -ml-kem-1024,m4fstack,75.9,74.9,70.7,,,,,, -ml-kem-512,clean,49.9,41.1,32.5,,,,,, -ml-kem-512,m4fspeed,76.5,73.5,67.2,,,,,, -ml-kem-512,m4fstack,76.6,73.2,66.9,,,,,, -ml-kem-768,clean,48.6,43.2,35.4,,,,,, -ml-kem-768,m4fspeed,75.5,74.4,69.3,,,,,, -ml-kem-768,m4fstack,75.3,73.9,68.7,,,,,, +ml-kem-1024,clean,50.0,45.7,38.6,,,,,, +ml-kem-1024,m4fspeed,75.3,75.5,71.2,,,,,, +ml-kem-1024,m4fstack,75.1,74.9,70.7,,,,,, +ml-kem-512,clean,49.8,41.1,32.5,,,,,, +ml-kem-512,m4fspeed,75.5,73.5,67.1,,,,,, +ml-kem-512,m4fstack,75.6,73.2,66.9,,,,,, +ml-kem-768,clean,48.5,43.2,35.4,,,,,, +ml-kem-768,m4fspeed,74.5,74.4,69.2,,,,,, +ml-kem-768,m4fstack,74.4,73.9,68.7,,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,Key Generation [%],Sign [%],Verify [%],,,,,, aimer128f,m4speed,57.9,49.5,50.1,,,,,, @@ -469,14 +469,14 @@ hqc-128,clean,18628,0,0,18628,,,,, hqc-192,clean,21104,0,0,21104,,,,, hqc-256,clean,26260,0,0,26260,,,,, ml-kem-1024,clean,6160,0,0,6160,,,,, -ml-kem-1024,m4fspeed,16912,0,0,16912,,,,, -ml-kem-1024,m4fstack,14012,0,0,14012,,,,, +ml-kem-1024,m4fspeed,16916,0,0,16916,,,,, +ml-kem-1024,m4fstack,14016,0,0,14016,,,,, ml-kem-512,clean,5116,0,0,5116,,,,, -ml-kem-512,m4fspeed,15844,0,0,15844,,,,, -ml-kem-512,m4fstack,13324,0,0,13324,,,,, +ml-kem-512,m4fspeed,15848,0,0,15848,,,,, +ml-kem-512,m4fstack,13328,0,0,13328,,,,, ml-kem-768,clean,5120,0,0,5120,,,,, -ml-kem-768,m4fspeed,16012,0,0,16012,,,,, -ml-kem-768,m4fstack,13316,0,0,13316,,,,, +ml-kem-768,m4fspeed,16016,0,0,16016,,,,, +ml-kem-768,m4fstack,13320,0,0,13320,,,,, Signature Schemes,,,,,,,,,, Scheme,Implementation,.text [bytes],.data [bytes],.bss [bytes],Total [bytes],,,,, aimer128f,m4speed,15992,0,0,15992,,,,, diff --git a/benchmarks.md b/benchmarks.md index e131b348..afe0ae3a 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -9,15 +9,15 @@ | hqc-128 (10 executions) | clean | AVG: 52,705,201
MIN: 52,705,180
MAX: 52,705,224 | AVG: 105,650,897
MIN: 105,650,877
MAX: 105,650,927 | AVG: 159,569,179
MIN: 159,569,176
MAX: 159,569,183 | | hqc-192 (10 executions) | clean | AVG: 161,458,617
MIN: 161,458,590
MAX: 161,458,638 | AVG: 323,146,261
MIN: 323,146,250
MAX: 323,146,292 | AVG: 486,156,251
MIN: 486,156,214
MAX: 486,156,266 | | hqc-256 (10 executions) | clean | AVG: 295,934,078
MIN: 295,934,057
MAX: 295,934,104 | AVG: 591,853,870
MIN: 591,853,850
MAX: 591,853,898 | AVG: 891,163,005
MIN: 891,162,988
MAX: 891,163,038 | -| ml-kem-1024 (10 executions) | clean | AVG: 1,540,607
MIN: 1,535,678
MAX: 1,547,404 | AVG: 1,712,361
MIN: 1,707,431
MAX: 1,719,164 | AVG: 2,024,616
MIN: 2,019,674
MAX: 2,031,410 | -| ml-kem-1024 (10 executions) | m4fspeed | AVG: 1,007,759
MIN: 1,004,549
MAX: 1,017,159 | AVG: 1,030,702
MIN: 1,027,443
MAX: 1,040,101 | AVG: 1,093,153
MIN: 1,089,895
MAX: 1,102,552 | -| ml-kem-1024 (10 executions) | m4fstack | AVG: 1,010,100
MIN: 1,007,459
MAX: 1,018,999 | AVG: 1,038,190
MIN: 1,035,550
MAX: 1,047,090 | AVG: 1,101,234
MIN: 1,098,594
MAX: 1,110,134 | -| ml-kem-512 (10 executions) | clean | AVG: 595,882
MIN: 595,636
MAX: 596,329 | AVG: 700,689
MIN: 700,440
MAX: 701,134 | AVG: 888,740
MIN: 888,494
MAX: 889,189 | -| ml-kem-512 (10 executions) | m4fspeed | AVG: 388,544
MIN: 387,190
MAX: 398,814 | AVG: 392,178
MIN: 390,825
MAX: 402,445 | AVG: 429,456
MIN: 428,102
MAX: 439,722 | -| ml-kem-512 (10 executions) | m4fstack | AVG: 386,999
MIN: 386,677
MAX: 387,465 | AVG: 392,813
MIN: 392,492
MAX: 393,280 | AVG: 430,152
MIN: 429,831
MAX: 430,619 | -| ml-kem-768 (10 executions) | clean | AVG: 990,901
MIN: 986,123
MAX: 997,663 | AVG: 1,140,412
MIN: 1,135,630
MAX: 1,147,169 | AVG: 1,390,176
MIN: 1,385,399
MAX: 1,396,936 | -| ml-kem-768 (10 executions) | m4fspeed | AVG: 631,949
MIN: 631,658
MAX: 632,164 | AVG: 656,369
MIN: 656,082
MAX: 656,596 | AVG: 705,436
MIN: 705,148
MAX: 705,663 | -| ml-kem-768 (10 executions) | m4fstack | AVG: 634,227
MIN: 632,761
MAX: 644,635 | AVG: 662,468
MIN: 661,003
MAX: 672,877 | AVG: 711,996
MIN: 710,530
MAX: 722,405 | +| ml-kem-1024 (10 executions) | clean | AVG: 1,536,343
MIN: 1,535,750
MAX: 1,536,698 | AVG: 1,708,071
MIN: 1,707,476
MAX: 1,708,427 | AVG: 2,020,327
MIN: 2,019,721
MAX: 2,020,672 | +| ml-kem-1024 (10 executions) | m4fspeed | AVG: 1,018,976
MIN: 1,014,877
MAX: 1,026,934 | AVG: 1,031,565
MIN: 1,027,454
MAX: 1,039,544 | AVG: 1,094,008
MIN: 1,089,897
MAX: 1,101,987 | +| ml-kem-1024 (10 executions) | m4fstack | AVG: 1,020,202
MIN: 1,017,478
MAX: 1,029,553 | AVG: 1,037,953
MIN: 1,035,260
MAX: 1,047,298 | AVG: 1,100,982
MIN: 1,098,251
MAX: 1,110,327 | +| ml-kem-512 (10 executions) | clean | AVG: 595,793
MIN: 595,576
MAX: 595,971 | AVG: 700,605
MIN: 700,383
MAX: 700,779 | AVG: 888,653
MIN: 888,436
MAX: 888,831 | +| ml-kem-512 (10 executions) | m4fspeed | AVG: 392,423
MIN: 392,211
MAX: 392,614 | AVG: 390,881
MIN: 390,671
MAX: 391,073 | AVG: 428,167
MIN: 427,955
MAX: 428,357 | +| ml-kem-512 (10 executions) | m4fstack | AVG: 392,224
MIN: 391,772
MAX: 392,541 | AVG: 392,864
MIN: 392,407
MAX: 393,181 | AVG: 430,202
MIN: 429,745
MAX: 430,519 | +| ml-kem-768 (10 executions) | clean | AVG: 988,722
MIN: 985,880
MAX: 998,135 | AVG: 1,138,225
MIN: 1,135,419
MAX: 1,147,634 | AVG: 1,387,984
MIN: 1,385,144
MAX: 1,397,397 | +| ml-kem-768 (10 executions) | m4fspeed | AVG: 642,096
MIN: 639,116
MAX: 651,103 | AVG: 658,754
MIN: 655,785
MAX: 667,769 | AVG: 707,827
MIN: 704,858
MAX: 716,842 | +| ml-kem-768 (10 executions) | m4fstack | AVG: 644,195
MIN: 640,433
MAX: 652,374 | AVG: 664,654
MIN: 660,893
MAX: 672,834 | AVG: 714,194
MIN: 710,433
MAX: 722,374 | ## Signature Schemes | scheme | implementation | key generation [cycles] | sign [cycles] | verify [cycles] | | ------ | -------------- | ----------------------- | ------------- | --------------- | @@ -319,15 +319,15 @@ | hqc-128 | clean | 0.4% | 0.8% | 0.5% | | hqc-192 | clean | 0.3% | 0.5% | 0.3% | | hqc-256 | clean | 0.2% | 0.4% | 0.3% | -| ml-kem-1024 | clean | 50.0% | 45.6% | 38.6% | -| ml-kem-1024 | m4fspeed | 76.1% | 75.5% | 71.2% | -| ml-kem-1024 | m4fstack | 75.9% | 74.9% | 70.7% | -| ml-kem-512 | clean | 49.9% | 41.1% | 32.5% | -| ml-kem-512 | m4fspeed | 76.5% | 73.5% | 67.2% | -| ml-kem-512 | m4fstack | 76.6% | 73.2% | 66.9% | -| ml-kem-768 | clean | 48.6% | 43.2% | 35.4% | -| ml-kem-768 | m4fspeed | 75.5% | 74.4% | 69.3% | -| ml-kem-768 | m4fstack | 75.3% | 73.9% | 68.7% | +| ml-kem-1024 | clean | 50.0% | 45.7% | 38.6% | +| ml-kem-1024 | m4fspeed | 75.3% | 75.5% | 71.2% | +| ml-kem-1024 | m4fstack | 75.1% | 74.9% | 70.7% | +| ml-kem-512 | clean | 49.8% | 41.1% | 32.5% | +| ml-kem-512 | m4fspeed | 75.5% | 73.5% | 67.1% | +| ml-kem-512 | m4fstack | 75.6% | 73.2% | 66.9% | +| ml-kem-768 | clean | 48.5% | 43.2% | 35.4% | +| ml-kem-768 | m4fspeed | 74.5% | 74.4% | 69.2% | +| ml-kem-768 | m4fstack | 74.4% | 73.9% | 68.7% | ## Signature Schemes | Scheme | Implementation | Key Generation [%] | Sign [%] | Verify [%] | | ------ | -------------- | ------------------ | -------- | ---------- | @@ -475,14 +475,14 @@ | hqc-192 | clean | 21,104 | 0 | 0 | 21,104 | | hqc-256 | clean | 26,260 | 0 | 0 | 26,260 | | ml-kem-1024 | clean | 6,160 | 0 | 0 | 6,160 | -| ml-kem-1024 | m4fspeed | 16,912 | 0 | 0 | 16,912 | -| ml-kem-1024 | m4fstack | 14,012 | 0 | 0 | 14,012 | +| ml-kem-1024 | m4fspeed | 16,916 | 0 | 0 | 16,916 | +| ml-kem-1024 | m4fstack | 14,016 | 0 | 0 | 14,016 | | ml-kem-512 | clean | 5,116 | 0 | 0 | 5,116 | -| ml-kem-512 | m4fspeed | 15,844 | 0 | 0 | 15,844 | -| ml-kem-512 | m4fstack | 13,324 | 0 | 0 | 13,324 | +| ml-kem-512 | m4fspeed | 15,848 | 0 | 0 | 15,848 | +| ml-kem-512 | m4fstack | 13,328 | 0 | 0 | 13,328 | | ml-kem-768 | clean | 5,120 | 0 | 0 | 5,120 | -| ml-kem-768 | m4fspeed | 16,012 | 0 | 0 | 16,012 | -| ml-kem-768 | m4fstack | 13,316 | 0 | 0 | 13,316 | +| ml-kem-768 | m4fspeed | 16,016 | 0 | 0 | 16,016 | +| ml-kem-768 | m4fstack | 13,320 | 0 | 0 | 13,320 | ## Signature Schemes | Scheme | Implementation | .text [bytes] | .data [bytes] | .bss [bytes] | Total [bytes] | | ------ | -------------- | ------------- | ------------- | ------------ | ------------- | From d702a740bdf97208a6853fbe44a5b5890481006c Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 28 Nov 2024 13:21:42 +0800 Subject: [PATCH 107/107] remove broken symlinks Fixes #370. Found with `find . -xtype l` --- crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. | 1 - crypto_sign/ml-dsa-65/m4fstack/smalltt.h | 1 - 2 files changed, 2 deletions(-) delete mode 120000 crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. delete mode 120000 crypto_sign/ml-dsa-65/m4fstack/smalltt.h diff --git a/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. b/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. deleted file mode 120000 index e49ba066..00000000 --- a/crypto_kem/ml-kem-512/m4fspeed/symmetric-fips202. +++ /dev/null @@ -1 +0,0 @@ -../../ml-kem-768/m4fspeed/symmetric-fips202. \ No newline at end of file diff --git a/crypto_sign/ml-dsa-65/m4fstack/smalltt.h b/crypto_sign/ml-dsa-65/m4fstack/smalltt.h deleted file mode 120000 index 5c449aee..00000000 --- a/crypto_sign/ml-dsa-65/m4fstack/smalltt.h +++ /dev/null @@ -1 +0,0 @@ -../../ml-dsa-44/m4fstack/smalltt.h \ No newline at end of file