Compare commits

...

22 Commits
main ... lwc

Author SHA1 Message Date
6c48a29db1 adds initial version of lwc 2025-05-22 11:14:03 +02:00
bccfc67926 removes unused code in cmake 2025-04-15 14:33:03 +02:00
8b3dc54e5c uses write_hex() in exit instead of tohost=0x1 2025-04-15 12:32:09 +02:00
9909769c0a updates to make 64bit compiling 2025-04-15 12:26:32 +02:00
071d9cc8eb updates bsp and cleans hello.c 2025-04-14 17:01:19 +02:00
a5825bfd67 updates preset for 64bit 2025-04-11 15:44:52 +02:00
36404dd7e0 adds -mcmodel=medany and map generation;updaes bsp 2025-04-11 15:41:29 +02:00
658ffbb405 adds map generation and updates bsp 2025-03-21 16:07:17 +01:00
c6bfaf0546 adds volatile to array passed to tohost and updates bsp submodule 2025-03-14 17:53:49 +01:00
e88c1148fb removes default release build 2025-03-14 14:26:49 +01:00
686d01ab3e adds extern to tohost/fromhost to avoid error during BSS initialization 2025-03-14 14:20:53 +01:00
884d445cb9 adds target. map generation to target_link_opinions 2025-03-11 11:49:26 +01:00
eee14af478 updates bsp 2025-03-11 11:46:23 +01:00
727fdcb7bb adds examples of write/tohost usage 2025-03-11 11:45:40 +01:00
3def42153f adds preset,json 2025-02-28 14:03:21 +01:00
75ba2e7588 adds cmake for coremark 2025-02-20 14:08:53 +01:00
1629b165b5 updates bsp 2025-01-16 11:11:18 +01:00
a2e932c56f adds build to gitignore 2025-01-16 11:10:53 +01:00
cde5ae627c updates dhrystone build 2025-01-16 11:09:58 +01:00
85304d1a43 updates bsp and build System 2025-01-06 20:33:30 +01:00
fddf608418 first version of working cmake 2024-12-20 14:33:57 +01:00
90c45d7c3c add first version of cmake 2024-12-17 12:34:07 +01:00
2543 changed files with 579498 additions and 720 deletions

View File

@ -1,11 +0,0 @@
if (NOT DEFINED BOARD)
set(BOARD iss)
endif()
if (NOT DEFINED ISA)
set(ISA imc)
endif()
message(STATUS "Building firmware using ${BOARD} board configuration and isa ${ISA}")
add_custom_target(fw-common ALL
COMMAND make -C hello-world BOARD=${BOARD} ISA=${ISA} && make -C benchmarks/dhrystone BOARD=${BOARD} ISA=${ISA} && make -C benchmarks/coremark BOARD=${BOARD} ISA=${ISA}
USES_TERMINAL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

@ -1 +1 @@
Subproject commit 87dc0ec2304adcb94a25b397a357aadae1304867
Subproject commit 540397494a48b07b1e8282b6059689246b622564

View File

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.21)
project(coremark C)
set(TARGET coremark)
#set(CMAKE_BUILD_TYPE Release)
option(HAVE_NO_INIT_FINI "Enable NO_INIT_FINI" OFF)
if(HAVE_NO_INIT_FINI)
#if HAVE_NO_INIT_FINI is ON
add_definitions(-DHAVE_NO_INIT_FINI)
endif()
# Source files
set(SOURCES
core_portme.c
cvt.c
ee_printf.c
cm/core_list_join.c
cm/core_main.c
cm/core_matrix.c
cm/core_state.c
cm/core_util.c
)
# Create executable
add_executable(coremark ${SOURCES})
target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/cm)
target_compile_options(${TARGET} PRIVATE -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -fno-builtin-strnlen -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-crossjumping -freorder-blocks-and-partition -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -fno-common -funroll-loops -finline-functions -falign-functions=16 -falign-jumps=4 -falign-loops=4 -finline-limit=1000 -fno-if-conversion2 -fselective-scheduling -fno-crossjumping -freorder-blocks-and-partition )
target_compile_definitions(${TARGET} PRIVATE PERFORMANCE_RUN=1 CLOCKS_PER_SEC=10000000 FLAGS_STR="" PERFORMANCE_RUN=1 CLOCKS_PER_SEC=10000000 ITERATIONS=600)
set(BOARD "iss" CACHE STRING "Target board")
add_subdirectory(../../bare-metal-bsp bsp)
target_link_libraries(${TARGET} PRIVATE bsp)
target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map)
include(CMakePrintHelpers)
cmake_print_properties(TARGETS ${TARGET} PROPERTIES COMPILE_DEFINITIONS COMPILE_OPTIONS LINK_OPTIONS INTERFACE_LINK_OPTIONS)
#message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
#message(STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}")
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -S ${TARGET}.elf > ${TARGET}.dis
COMMENT "Creating disassembly for ${TARGET}")

View File

@ -0,0 +1,70 @@
{
"version": 3,
"vendor": {
"conan": {}
},
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_64",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
}
]
}

View File

@ -15,55 +15,58 @@ limitations under the License.
Original Author: Shay Gal-on
*/
#include "coremark.h"
#include "core_portme.h"
//Read cycle CSR
unsigned long long _read_cycle()
{
unsigned long long result;
unsigned long lower;
unsigned long upper1;
unsigned long upper2;
#include "coremark.h"
#include <unistd.h>
// Read cycle CSR
unsigned long long _read_cycle() {
unsigned long long result;
unsigned long lower;
unsigned long upper1;
unsigned long upper2;
asm volatile (
"repeat_cycle_%=: csrr %0, cycleh;\n"
" csrr %1, cycle;\n"
" csrr %2, cycleh;\n"
" bne %0, %2, repeat_cycle_%=;\n"
: "=r" (upper1),"=r" (lower),"=r" (upper2) // Outputs : temp variable for load result
:
:
);
*(unsigned long *)(&result) = lower;
*((unsigned long *)(&result)+1) = upper1;
asm volatile("repeat_cycle_%=: csrr %0, cycleh;\n"
" csrr %1, cycle;\n"
" csrr %2, cycleh;\n"
" bne %0, %2, repeat_cycle_%=;\n"
: "=r"(upper1), "=r"(lower),
"=r"(upper2) // Outputs : temp variable for load result
:
:);
*(unsigned long *)(&result) = lower;
*((unsigned long *)(&result) + 1) = upper1;
return result;
return result;
}
volatile int tohost;
volatile int fromhost;
// extern volatile int tohost;
// extern volatile int fromhost;
void exit(int n){
tohost = 0x1;
for (;;);
void write_hex(int fd, uint32_t hex);
void exit(int n) {
write_hex(STDERR_FILENO, 1);
// tohost = 0x1;
for (;;)
;
}
void __libc_init_array (void) {
/*
size_t count;
size_t i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i] ();
void __libc_init_array(void) {
/*
size_t count;
size_t i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i] ();
#ifdef HAVE_INIT_FINI
_init ();
#endif
#ifdef HAVE_INIT_FINI
_init ();
#endif
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i] ();
*/
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i] ();
*/
}
#if VALIDATION_RUN
volatile ee_s32 seed1_volatile = 0x3415;
@ -89,10 +92,7 @@ volatile ee_s32 seed5_volatile = 0;
time.h and windows.h definitions included.
*/
CORETIMETYPE
barebones_clock()
{
return (CORETIMETYPE)_read_cycle();
}
barebones_clock() { return (CORETIMETYPE)_read_cycle(); }
/* Define : TIMER_RES_DIVIDER
Divider to trade off timer resolution and total time that can be
measured.
@ -101,11 +101,11 @@ barebones_clock()
does not occur. If there are issues with the return value overflowing,
increase this value.
*/
#define GETMYTIME(_t) (*_t = barebones_clock())
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
#define TIMER_RES_DIVIDER 1
#define GETMYTIME(_t) (*_t = barebones_clock())
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
#define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 1
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
#define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
/** Define Host specific (POSIX), or target specific global time variables. */
static CORETIMETYPE start_time_val, stop_time_val;
@ -118,11 +118,7 @@ static CORETIMETYPE start_time_val, stop_time_val;
example code) or zeroing some system parameters - e.g. setting the cpu clocks
cycles to 0.
*/
void
start_time(void)
{
GETMYTIME(&start_time_val);
}
void start_time(void) { GETMYTIME(&start_time_val); }
/* Function : stop_time
This function will be called right after ending the timed portion of the
benchmark.
@ -131,11 +127,7 @@ start_time(void)
example code) or other system parameters - e.g. reading the current value of
cpu cycles counter.
*/
void
stop_time(void)
{
GETMYTIME(&stop_time_val);
}
void stop_time(void) { GETMYTIME(&stop_time_val); }
/* Function : get_time
Return an abstract "ticks" number that signifies time on the system.
@ -146,11 +138,9 @@ stop_time(void)
controlled by <TIMER_RES_DIVIDER>
*/
CORE_TICKS
get_time(void)
{
CORE_TICKS elapsed
= (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
return elapsed;
get_time(void) {
CORE_TICKS elapsed = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
return elapsed;
}
/* Function : time_in_secs
Convert the value returned by get_time to seconds.
@ -159,11 +149,9 @@ get_time(void)
floating point. Default implementation implemented by the EE_TICKS_PER_SEC
macro above.
*/
secs_ret
time_in_secs(CORE_TICKS ticks)
{
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
return retval;
secs_ret time_in_secs(CORE_TICKS ticks) {
secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
return retval;
}
ee_u32 default_num_contexts = 1;
@ -172,27 +160,18 @@ ee_u32 default_num_contexts = 1;
Target specific initialization code
Test for some common mistakes.
*/
void
portable_init(core_portable *p, int *argc, char *argv[])
{
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
{
ee_printf(
"ERROR! Please define ee_ptr_int to a type that holds a "
"pointer!\n");
}
if (sizeof(ee_u32) != 4)
{
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
}
p->portable_id = 1;
ee_printf("portable_init finished.\n");
void portable_init(core_portable *p, int *argc, char *argv[]) {
if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
ee_printf("ERROR! Please define ee_ptr_int to a type that holds a "
"pointer!\n");
}
if (sizeof(ee_u32) != 4) {
ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
}
p->portable_id = 1;
ee_printf("portable_init finished.\n");
}
/* Function : portable_fini
Target specific final code
*/
void
portable_fini(core_portable *p)
{
p->portable_id = 0;
}
void portable_fini(core_portable *p) { p->portable_id = 0; }

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,3 @@
dhrystone
/dhrystone.dis
build/

View File

@ -0,0 +1,31 @@
cmake_minimum_required(VERSION 3.21)
project(dhrystone C)
set(TARGET dhrystone)
option(HAVE_NO_INIT_FINI "Enable NO_INIT_FINI" OFF)
if(HAVE_NO_INIT_FINI)
#if HAVE_NO_INIT_FINI is ON
add_definitions(-DHAVE_NO_INIT_FINI)
endif()
set(ITERATIONS 50000) # 20000 for TGC
add_executable(${TARGET} dhry_1.c dhry_2.c dhry_stubs.c)
target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_compile_options(${TARGET} PRIVATE -fno-inline -fno-builtin-printf -fno-common -Wno-implicit -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las)
target_compile_definitions(${TARGET} PRIVATE ITERATIONS=${ITERATIONS} HZ=32768 TIME NO_INIT)
set(BOARD "iss" CACHE STRING "Target board")
add_subdirectory(../../bare-metal-bsp bsp)
target_link_libraries(${TARGET} PRIVATE bsp)
target_link_options(${TARGET} PRIVATE LINKER:--wrap=scanf)
#target_link_options(${TARGET} PRIVATE LINKER:--wrap=scanf -Wl,--no-gc-sections)
target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map)
include(CMakePrintHelpers)
cmake_print_properties(TARGETS ${TARGET} PROPERTIES COMPILE_DEFINITIONS COMPILE_OPTIONS LINK_OPTIONS INTERFACE_LINK_OPTIONS)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -S ${TARGET}.elf > ${TARGET}.dis
COMMENT "Creating disassembly for ${TARGET}")

View File

@ -0,0 +1,70 @@
{
"version": 3,
"vendor": {
"conan": {}
},
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_64",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
}
]
}

View File

@ -17,6 +17,7 @@ endif
# '-lgcc -lm' are needed to add softfloat routines
CFLAGS := -g -O3 -DITERATIONS=$(ITERATIONS) -DHZ=32768 -DTIME -DNO_INIT -fno-inline -fno-builtin-printf -fno-common -Wno-implicit \
-funroll-loops -fpeel-loops -fgcse-sm -fgcse-las
LDFLAGS := -Wl,--wrap=scanf
TOOL_DIR=$(dir $(compiler))

View File

@ -1,4 +1,5 @@
#include "platform.h"
#include <unistd.h>
#ifndef ITERATIONS
#define ITERATIONS 20000
#endif
@ -6,20 +7,16 @@
/* The functions in this file are only meant to support Dhrystone on an
* embedded RV32 system and are obviously incorrect in general. */
long time(void)
{
return get_timer_value();
}
long time(void) { return get_timer_value(); }
// set the number of dhrystone iterations
void __wrap_scanf(const char* fmt, int* n)
{
*n = ITERATIONS;
}
void __wrap_scanf(const char *fmt, int *n) { *n = ITERATIONS; }
extern volatile uint32_t tohost;
// extern volatile uint64_t tohost;
void exit(int n){
tohost = 0x1;
for (;;);
void exit(int n) {
// tohost = 0x1;
write_hex(STDERR_FILENO, 1);
for (;;)
;
}

View File

@ -1,2 +1,3 @@
/hello
/hello.dis
build/

View File

@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.21)
project(hello-world C)
set(TARGET hello)
option(HAVE_NO_INIT_FINI "Enable NO_INIT_FINI" OFF)
if(HAVE_NO_INIT_FINI)
#if HAVE_NO_INIT_FINI is ON
add_definitions(-DHAVE_NO_INIT_FINI)
endif()
add_executable(${TARGET} hello.c)
set(BOARD "iss" CACHE STRING "Target board")
message(" BOARD = ${BOARD}")
add_subdirectory(../bare-metal-bsp bsp)
target_link_libraries(${TARGET} PRIVATE bsp)
target_link_options(${TARGET} PRIVATE -Wl,-Map=${TARGET}.map)
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -S ${TARGET}.elf > ${TARGET}.dis
COMMENT "Creating disassembly for ${TARGET}")

View File

@ -0,0 +1,70 @@
{
"version": 3,
"vendor": {
"conan": {}
},
"cmakeMinimumRequired": {
"major": 3,
"minor": 24,
"patch": 0
},
"configurePresets": [
{
"name": "debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
},
{
"name": "debug_64",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_moon",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "moonlight",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "debug_64_tgc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"BOARD": "tgc_vp",
"HAVE_NO_INIT_FINI": "ON",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv64gc.cmake"
}
},
{
"name": "release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "../../bare-metal-bsp/cmake/rv32imc.cmake"
}
}
]
}

View File

@ -1,24 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "platform.h"
#include "encoding.h"
#include "platform.h"
#include <string.h>
int factorial(int i){
int factorial(int i) {
volatile int result = 1;
for (int ii = 1; ii <= i; ii++) {
result = result * ii;
}
return result;
volatile int result = 1;
for (int ii = 1; ii <= i; ii++) {
result = result * ii;
}
return result;
}
extern volatile uintptr_t tohost;
void write_tohost(char *string) {
volatile uint64_t payload[4] = {64, 0, (uintptr_t)string,
(strlen(string) + 1)};
tohost = (uintptr_t)payload;
}
int main()
{
volatile int result = factorial (10);
printf("Factorial is %d\n", result);
printf("End of execution");
return 0;
int main() {
char string[] = "hello world with write in hello";
write_tohost(string);
write(STDOUT_FILENO, string, sizeof(string));
int result = factorial(10);
printf("Factorial is %d", result);
return 0;
}

36
lwc/Makefile Normal file
View File

@ -0,0 +1,36 @@
# Copyright (C) 2021 SCARV project <info@scarv.org>
#
# Use of this source code is restricted per the MIT license, a copy of which
# can be found at https://opensource.org/licenses/MIT (or should be included
# as LICENSE.txt within the associated archive or repository).
export REPO_HOME = ${PWD}
# =============================================================================
export ALG ?= ascon
export API ?= aead
export ARCH ?= generic
export IMP ?= nist
export ISE ?= xalu
export CONF ?=
# -----------------------------------------------------------------------------
sw-build :
@make --directory="${REPO_HOME}/src" build
sw-run :
@make --directory="${REPO_HOME}/src" run
sw-scan :
@make --directory="${REPO_HOME}/src" scan
sw-clean :
@make --directory="${REPO_HOME}/src" clean
# -----------------------------------------------------------------------------
clean :
@rm --force --recursive ${REPO_HOME}/build/*
# =============================================================================

110
lwc/src/Makefile Normal file
View File

@ -0,0 +1,110 @@
# Copyright (C) 2021 SCARV project <info@scarv.org>
#
# Use of this source code is restricted per the MIT license, a copy of which
# can be found at https://opensource.org/licenses/MIT (or should be included
# as LICENSE.txt within the associated archive or repository).
ifndef REPO_HOME
$(error "execute 'source ./bin/conf.sh' to configure environment")
endif
ifndef REPO_VERSION
$(error "execute 'source ./bin/conf.sh' to configure environment")
endif
export API ?= aead
# =============================================================================
# include build-related content for algorithm
include ./${ALG}/Makefile.in
# include build-related content for architecture
include ./share/arch/${ARCH}/Makefile.in
# parameterise source code using environment variables
ifeq "${API}" "aead"
GCC_FLAGS += -DAPI_AEAD
endif
ifeq "${API}" "hash"
GCC_FLAGS += -DAPI_HASH
endif
ifeq "${IMP}" "nist"
GCC_FLAGS += -DALG="\"${ALG}\"" -DAPI="\"${API}\"" ${CONF} -DARCH="\"${ARCH}\"" -DIMP="\"${IMP}\""
else
GCC_FLAGS += -DALG="\"${ALG}\"" -DAPI="\"${API}\"" ${CONF} -DARCH="\"${ARCH}\"" -DIMP="\"${IMP}\"" -DLWISE
endif
# -----------------------------------------------------------------------------
ifeq "${IMP}" "nist"
export LWISE_INCLUDES += ${REPO_HOME}/build/${ALG} ./share ./share/nist ./share/arch/${ARCH}
else
export LWISE_INCLUDES += ${REPO_HOME}/build/${ALG} ./share ./share/nist ./share/arch/${ARCH} ./${ALG}/arch/${ARCH} ./${ALG}/imp/${IMP} ./${ALG}/imp/share
endif
export LWISE_SOURCES += $(wildcard $(addsuffix /*.c, ${LWISE_INCLUDES}))
export LWISE_SOURCES += $(wildcard $(addsuffix /*.cpp, ${LWISE_INCLUDES}))
export LWISE_SOURCES += $(wildcard $(addsuffix /*.s, ${LWISE_INCLUDES}))
export LWISE_SOURCES += $(wildcard $(addsuffix /*.S, ${LWISE_INCLUDES}))
export LWISE_HEADERS += $(wildcard $(addsuffix /*.h, ${LWISE_INCLUDES}))
export INCLUDES := ${LWISE_INCLUDES} ${NIST_INCLUDES}
export SOURCES := ${LWISE_SOURCES} ${NIST_SOURCES} ${REPO_HOME}/build/${ALG}/kat_${API}.c
export HEADERS := ${LWISE_HEADERS} ${NIST_HEADERS} ${REPO_HOME}/build/${ALG}/kat_${API}.h
export TARGETS += ${REPO_HOME}/build/${ALG}
export TARGETS += ${REPO_HOME}/build/${ALG}/kat_${API}.h
export TARGETS += ${REPO_HOME}/build/${ALG}/kat_${API}.c
export TARGETS += ${REPO_HOME}/build/${ALG}/driver-${API}_${ARCH}_${IMP}.elf
export TARGETS += ${REPO_HOME}/build/${ALG}/driver-${API}_${ARCH}_${IMP}.asm
# -----------------------------------------------------------------------------
${REPO_HOME}/build/${ALG} :
@mkdir --parents ${@}
${REPO_HOME}/build/${ALG}/kat_${API}.h : ${NIST_KAT}
@python3 ./share/kat.py --api="${API}" --header < ${<} > ${@}
${REPO_HOME}/build/${ALG}/kat_${API}.c : ${NIST_KAT}
@python3 ./share/kat.py --api="${API}" --source < ${<} > ${@}
${REPO_HOME}/build/${ALG}/driver-${API}_${ARCH}_${IMP}.elf : ${SOURCES}
@${GCC_PREFIX}-gcc ${GCC_FLAGS} ${GCC_PATHS} $(addprefix -I ,${INCLUDES}) -std='gnu99' -O3 -o ${@} $(filter %.c, ${^}) $(filter %.cpp, ${^}) $(filter %.S, ${^}) ${GCC_LIBS}
${REPO_HOME}/build/${ALG}/driver-${API}_${ARCH}_${IMP}.asm : ${REPO_HOME}/build/${ALG}/driver-${API}_${ARCH}_${IMP}.elf
@${GCC_PREFIX}-objdump --disassemble-all ${<} > ${@}
# -----------------------------------------------------------------------------
.PHONY : run debug scan
dump :
@echo "ALG = ${ALG}"
@echo "API = ${API}"
@echo "ARCH = ${ARCH}"
@echo "IMP = ${IMP}"
@echo "CONF = ${CONF}"
@echo "NIST_HOME = ${NIST_HOME}"
@echo "NIST_IMP = ${NIST_IMP}"
@echo "NIST_KAT = ${NIST_KAT}"
@echo "GCC_PREFIX = ${GCC_PREFIX}"
@echo "GCC_PATHS = ${GCC_PATHS}"
@echo "GCC_FLAGS = ${GCC_FLAGS}"
@echo "GCC_LIBS = ${GCC_LIBS}"
@echo "INCLUDES = ${INCLUDES}"
@echo "SOURCES = ${SOURCES}"
@echo "HEADERS = ${HEADERS}"
@echo "TARGETS = ${TARGETS}"
build : ${TARGETS}
clean :
@rm --force --recursive ${TARGETS}
# =============================================================================

39
lwc/src/ascon/Makefile.in Normal file
View File

@ -0,0 +1,39 @@
# Copyright (C) 2021 SCARV project <info@scarv.org>
#
# Use of this source code is restricted per the MIT license, a copy of which
# can be found at https://opensource.org/licenses/MIT (or should be included
# as LICENSE.txt within the associated archive or repository).
# =============================================================================
ifeq "${API}" "aead"
export NIST_HOME ?= ${REPO_HOME}/src/ascon/nist/Implementations/crypto_aead/ascon128v12
export NIST_IMP ?= ref
export NIST_KAT ?= ${NIST_HOME}/LWC_AEAD_KAT_128_128.txt
export NIST_INCLUDES = ${NIST_HOME}/${NIST_IMP}
export NIST_SOURCES = $(wildcard ${NIST_HOME}/${NIST_IMP}/*.c )
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.cpp)
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.s )
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.S )
export NIST_HEADERS = $(wildcard ${NIST_HOME}/${NIST_IMP}/*.h )
endif
# -----------------------------------------------------------------------------
ifeq "${API}" "hash"
export NIST_HOME ?= ${REPO_HOME}/src/ascon/nist/Implementations/crypto_hash/asconhashv12
export NIST_IMP ?= ref
export NIST_KAT ?= ${NIST_HOME}/LWC_HASH_KAT_256.txt
export NIST_INCLUDES = ${NIST_HOME}/${NIST_IMP}
export NIST_SOURCES = $(wildcard ${NIST_HOME}/${NIST_IMP}/*.c )
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.cpp)
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.s )
export NIST_SOURCES += $(wildcard ${NIST_HOME}/${NIST_IMP}/*.S )
export NIST_HEADERS = $(wildcard ${NIST_HOME}/${NIST_IMP}/*.h )
endif
# =============================================================================

View File

@ -0,0 +1,18 @@
// Copyright (C) 2021 SCARV project <info@scarv.org>
//
// Use of this source code is restricted per the MIT license, a copy of which
// can be found at https://opensource.org/licenses/MIT (or should be included
// as LICENSE.txt within the associated archive or repository).
// ============================================================================
#if ( ASCON_RV32_TYPE2 )
.macro ascon.sigma.lo rd, rs1, rs2, imm
.insn r CUSTOM_1, 7, \imm+( 0*32), \rd, \rs1, \rs2
.endm
.macro ascon.sigma.hi rd, rs1, rs2, imm
.insn r CUSTOM_1, 7, \imm+( 1*32), \rd, \rs1, \rs2
.endm
#endif
// ============================================================================

View File

@ -0,0 +1,15 @@
// Copyright (C) 2021 SCARV project <info@scarv.org>
//
// Use of this source code is restricted per the MIT license, a copy of which
// can be found at https://opensource.org/licenses/MIT (or should be included
// as LICENSE.txt within the associated archive or repository).
// ============================================================================
#if ( ASCON_RV64_TYPE2 )
.macro ascon.sigma rd, rs1, imm
.insn r CUSTOM_1, 6, \imm+( 2*32), \rd, \rs1, x0
.endm
#endif
// ============================================================================

View File

@ -0,0 +1,35 @@
# Copyright (C) 2021 SCARV project <info@scarv.org>
#
# Use of this source code is restricted per the MIT license, a copy of which
# can be found at https://opensource.org/licenses/MIT (or should be included
# as LICENSE.txt within the associated archive or repository).
import driver, itertools
# =============================================================================
def rv32( args ) :
if ( args.prog ) :
driver.program_fpga( args, 'ascon', 'rv32', 'xalu' )
if ( args.nist ) :
CONF = ['DRIVER_BYPASS_TEST']
driver.run( args, 'ascon', CONF, 'rv32', 'nist', NIST_IMP = 'ref' )
for TYPE in [ 'ASCON_RV32_TYPE1', 'ASCON_RV32_TYPE2' ] :
CONF = [ TYPE ]
# there is only unrolled implementation for Ascon on rv32
CONF += ['ASCON_RV32_UNROLL']
CONF += ['DRIVER_BYPASS_TEST']
driver.run( args, 'ascon', CONF, 'rv32', 'rv32' )
# -----------------------------------------------------------------------------
def rv64( args ) :
pass
# -----------------------------------------------------------------------------
if ( __name__ == '__main__' ) :
driver.main( rv32, rv64 )
# =============================================================================

View File

@ -0,0 +1,272 @@
#include "zbkb.h"
#include "zbkx.h"
#include "ise.h"
// ----------------------------------------------------------------------------
// Register Allocation
// (use caller-saved registers to save push/pop instructions)
//
// a0: the address of state
// a2-a7, t2-t5: state
// t0-t1, t6: temp registers
//
// Comments:
// Excluding resigers storing the state, this implementation needs only three
// additional registers for temp use, which might be useful for other platforms
// with smaller register space (e.g., AVR, ARM Cortex-M).
// ----------------------------------------------------------------------------
// prologue + epilogue
.macro ASCON_PROLOGUE
.endm
.macro ASCON_EPILOGUE
ret
.endm
// load state + store state
.macro ASCON_LDSTATE x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h
lw \x0l, 0(a0)
lw \x0h, 4(a0)
lw \x1l, 8(a0)
lw \x1h, 12(a0)
lw \x2l, 16(a0)
lw \x2h, 20(a0)
lw \x3l, 24(a0)
lw \x3h, 28(a0)
lw \x4l, 32(a0)
lw \x4h, 36(a0)
.endm
.macro ASCON_STSTATE x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h
sw \x0l, 0(a0)
sw \x0h, 4(a0)
sw \x1l, 8(a0)
sw \x1h, 12(a0)
sw \x2l, 16(a0)
sw \x2h, 20(a0)
sw \x3l, 24(a0)
sw \x3h, 28(a0)
sw \x4l, 32(a0)
sw \x4h, 36(a0)
.endm
// layers: PC + PS + PL
// PC: addition of constants
.macro ASCON_PC x2l, rci
xori \x2l, \x2l, \rci
.endm
// PS: SBox x0 x1 x2 x3 x4 -> x3 x1 x2 x0 x4
.macro ASCON_PS x0, x1, x2, x3, x4, t0, t1, t2, t3
xor \t2, \x1, \x2 // t2 = x1 ^ x2
xor \t0, \x0, \x4 // t0 = x0 ^ x4
xor \t1, \x3, \x4 // t1 = x3 ^ x4
orn \x2, \x3, \x4 // x2 = x3 | ~x4
xor \x2, \x2, \t2 // x2 = x1 ^ x2 ^ (x3 | ~x4)
andn \x4, \x1, \t0 // x4 = x1 & ~(x0 ^ x4)
xor \x4, \x4, \t1 // x4 = x3 ^ x4 ^ (x1 & ~(x0 ^ x4))
or \x0, \x0, \t1 // x0 = x0 | (x3 ^ x4)
xor \x3, \x1, \x3 // x3 = x1 ^ x3
xor \x0, \x0, \t2 // x0 = x1 ^ x2 ^ (x0 | (x3 ^ x4))
or \x3, \x3, \t2 // x3 = (x1 ^ x3) | (x1 ^ x2)
xor \t2, \t2, \t0 // t2 = x0 ^ x4 ^ x1 ^ x2
or \t2, \t2, \x1 // t2 = x1 | (x0 ^ x4 ^ x1 ^ x2)
xor \x1, \t0, \x3 // x1 = x0 ^ x4 ^ ((x1 ^ x3) | (x1 ^ x2))
xor \x3, \t1, \t2 // x3 = x3 ^ x4 ^ (x1 | (x0 ^ x4 ^ x1 ^ x2))
.endm
// PL: linear diffusion
#if (ASCON_RV32_TYPE1)
// 64-bit rotate right (immediate)
.macro ASCON_RORI64L dl, sl, sh, imm, t0
srli \t0, \sl, \imm
slli \dl, \sh, 32-\imm
xor \dl, \t0, \dl
.endm
.macro ASCON_RORI64H_0 dh, sl, sh, imm, t0
slli \t0, \sl, 32-\imm
srli \dh, \sh, \imm
xor \dh, \t0, \dh
.endm
.macro ASCON_RORI64H_1 dh, sl, sh, imm, t0, t1
slli \t0, \sl, 32-\imm
xor \sl, \sl, \t1
srli \t1, \sh, \imm
xor \dh, \t0, \t1
.endm
// 64-bit rotate left (immediate)
.macro ASCON_ROLI64L dl, sl, sh, imm, t0
slli \t0, \sl, \imm
srli \dl, \sh, 32-\imm
xor \dl, \t0, \dl
.endm
.macro ASCON_ROLI64H_0 dh, sl, sh, imm, t0
srli \t0, \sl, 32-\imm
slli \dh, \sh, \imm
xor \dh, \t0, \dh
.endm
.macro ASCON_ROLI64H_1 dh, sl, sh, imm, t0, t1
srli \t0, \sl, 32-\imm
xor \sl, \sl, \t1
slli \t1, \sh, \imm
xor \dh, \t0, \t1
.endm
.macro ASCON_PL_STEP_0 xl, xh, imm0, imm1, t0, t1, t2
ASCON_RORI64L \t1, \xl, \xh, \imm0, \t0
ASCON_RORI64L \t2, \xl, \xh, \imm1, \t0
xor \t1, \t1, \t2
ASCON_RORI64H_0 \t2, \xl, \xh, \imm0, \t0
ASCON_RORI64H_1 \t1, \xl, \xh, \imm1, \t0, \t1
xor \t1, \t2, \t1
xor \xh, \xh, \t1
.endm
.macro ASCON_PL_STEP_1 xl, xh, imm0, imm1, t0, t1, t2
ASCON_ROLI64L \t1, \xl, \xh, \imm0, \t0
ASCON_ROLI64L \t2, \xl, \xh, \imm1, \t0
xor \t1, \t1, \t2
ASCON_ROLI64H_0 \t2, \xl, \xh, \imm0, \t0
ASCON_ROLI64H_1 \t1, \xl, \xh, \imm1, \t0, \t1
xor \t1, \t2, \t1
xor \xh, \xh, \t1
.endm
.macro ASCON_PL_STEP_2 xl, xh, imm0, imm1, t0, t1, t2
ASCON_RORI64L \t1, \xl, \xh, \imm0, \t0
ASCON_ROLI64L \t2, \xl, \xh, \imm1, \t0
xor \t1, \t1, \t2
ASCON_RORI64H_0 \t2, \xl, \xh, \imm0, \t0
ASCON_ROLI64H_1 \t1, \xl, \xh, \imm1, \t0, \t1
xor \t1, \t2, \t1
xor \xh, \xh, \t1
.endm
.macro ASCON_PL x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h, t0, t1, t2
ASCON_PL_STEP_0 \x0l, \x0h, 19, 28, \t0, \t1, \t2
ASCON_PL_STEP_1 \x1l, \x1h, 3, 25, \t0, \t1, \t2
ASCON_PL_STEP_0 \x2l, \x2h, 1, 6, \t0, \t1, \t2
ASCON_PL_STEP_0 \x3l, \x3h, 10, 17, \t0, \t1, \t2
ASCON_PL_STEP_2 \x4l, \x4h, 7, 23, \t0, \t1, \t2
.endm
#elif (ASCON_RV32_TYPE2)
// x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h ->
// t0l, t0h, x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h
.macro ASCON_PL x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h, t0l, t0h, t2
ascon.sigma.lo \t0l, \x0l, \x0h, 0
ascon.sigma.hi \t0h, \x0l, \x0h, 0
ascon.sigma.lo \x0l, \x1l, \x1h, 1
ascon.sigma.hi \x0h, \x1l, \x1h, 1
ascon.sigma.lo \x1l, \x2l, \x2h, 2
ascon.sigma.hi \x1h, \x2l, \x2h, 2
ascon.sigma.lo \x2l, \x3l, \x3h, 3
ascon.sigma.hi \x2h, \x3l, \x3h, 3
ascon.sigma.lo \x3l, \x4l, \x4h, 4
ascon.sigma.hi \x3h, \x4l, \x4h, 4
.endm
#endif
// operations in each round
.macro ASCON_ROUND x0l, x0h, x1l, x1h, x2l, x2h, x3l, x3h, x4l, x4h, rci, t0, t1, t2
ASCON_PC \x2l, \rci
ASCON_PS \x0l, \x1l, \x2l, \x3l, \x4l, \t0, \t1, \t2
ASCON_PS \x0h, \x1h, \x2h, \x3h, \x4h, \t0, \t1, \t2
ASCON_PL \x3l, \x3h, \x1l, \x1h, \x2l, \x2h, \x0l, \x0h, \x4l, \x4h, \t0, \t1, \t2
.endm
// Ascon permutation
.section .text
.global P6
P6:
ASCON_PROLOGUE
ASCON_LDSTATE a2, a3, a4, a5, a6, a7, t2, t3, t4, t5
//
#if (ASCON_RV32_TYPE1)
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x96, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x87, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x78, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x69, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x5A, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x4B, t0, t1, t6
#elif (ASCON_RV32_TYPE2)
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x96, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0x87, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0x78, a2, a3, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x69, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0x5A, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0x4B, a2, a3, t6
#endif
//
ASCON_STSTATE a2, a3, a4, a5, a6, a7, t2, t3, t4, t5
ASCON_EPILOGUE
.section .text
.global P12
P12:
ASCON_PROLOGUE
ASCON_LDSTATE a2, a3, a4, a5, a6, a7, t2, t3, t4, t5
//
#if (ASCON_RV32_TYPE1)
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0xF0, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0xE1, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0xD2, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0xC3, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0xB4, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0xA5, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x96, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x87, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x78, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x69, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x5A, t0, t1, t6
ASCON_ROUND t2, t3, a4, a5, a6, a7, a2, a3, t4, t5, 0x4B, t0, t1, t6
#elif (ASCON_RV32_TYPE2)
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0xF0, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0xE1, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0xD2, a2, a3, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0xC3, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0xB4, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0xA5, a2, a3, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x96, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0x87, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0x78, a2, a3, t6
ASCON_ROUND a2, a3, a4, a5, a6, a7, t2, t3, t4, t5, 0x69, t0, t1, t6
ASCON_ROUND t0, t1, t2, t3, a4, a5, a6, a7, a2, a3, 0x5A, t4, t5, t6
ASCON_ROUND t4, t5, a6, a7, t2, t3, a4, a5, t0, t1, 0x4B, a2, a3, t6
#endif
//
ASCON_STSTATE a2, a3, a4, a5, a6, a7, t2, t3, t4, t5
ASCON_EPILOGUE

View File

@ -0,0 +1,158 @@
#include "zbkb.h"
#include "zbkx.h"
#include "ise.h"
// ----------------------------------------------------------------------------
// Register Allocation
// (use caller-saved registers to save push/pop instructions)
//
// a0: the address of state
// a2-a6: state
// t0-t1, t6: temp registers
// ----------------------------------------------------------------------------
// prologue + epilogue
.macro ASCON_PROLOGUE
.endm
.macro ASCON_EPILOGUE
ret
.endm
// load state + store state
.macro ASCON_LDSTATE x0, x1, x2, x3, x4
ld \x0, 0(a0)
ld \x1, 8(a0)
ld \x2, 16(a0)
ld \x3, 24(a0)
ld \x4, 32(a0)
.endm
.macro ASCON_STSTATE x0, x1, x2, x3, x4
sd \x0, 0(a0)
sd \x1, 8(a0)
sd \x2, 16(a0)
sd \x3, 24(a0)
sd \x4, 32(a0)
.endm
// layers: PC + PS + PL
// PC: addition of constants
.macro ASCON_PC x2, rci
xori \x2, \x2, \rci
.endm
// PS: SBox x0 x1 x2 x3 x4 -> x3 x1 x2 x0 x4
.macro ASCON_PS x0, x1, x2, x3, x4, t0, t1, t2
xor \t2, \x1, \x2 // t2 = x1 ^ x2
xor \t0, \x0, \x4 // t0 = x0 ^ x4
xor \t1, \x3, \x4 // t1 = x3 ^ x4
orn \x2, \x3, \x4 // x2 = x3 | ~x4
xor \x2, \x2, \t2 // x2 = x1 ^ x2 ^ (x3 | ~x4)
andn \x4, \x1, \t0 // x4 = x1 & ~(x0 ^ x4)
xor \x4, \x4, \t1 // x4 = x3 ^ x4 ^ (x1 & ~(x0 ^ x4))
or \x0, \x0, \t1 // x0 = x0 | (x3 ^ x4)
xor \x3, \x1, \x3 // x3 = x1 ^ x3
xor \x0, \x0, \t2 // x0 = x1 ^ x2 ^ (x0 | (x3 ^ x4))
or \x3, \x3, \t2 // x3 = (x1 ^ x3) | (x1 ^ x2)
xor \t2, \t2, \t0 // t2 = x0 ^ x4 ^ x1 ^ x2
or \t2, \t2, \x1 // t2 = x1 | (x0 ^ x4 ^ x1 ^ x2)
xor \x1, \t0, \x3 // x1 = x0 ^ x4 ^ ((x1 ^ x3) | (x1 ^ x2))
xor \x3, \t1, \t2 // x3 = x3 ^ x4 ^ (x1 | (x0 ^ x4 ^ x1 ^ x2))
.endm
// PL: linear diffusion
#if (ASCON_RV64_TYPE1)
.macro ASCON_PL_STEP x0, imm0, imm1, t0
rori \t0, \x0, \imm0
xor \t0, \x0, \t0
rori \x0, \x0, \imm1
xor \x0, \t0, \x0
.endm
.macro ASCON_PL x0, x1, x2, x3, x4, t0
ASCON_PL_STEP \x0, 19, 28, \t0
ASCON_PL_STEP \x1, 61, 39, \t0
ASCON_PL_STEP \x2, 1, 6, \t0
ASCON_PL_STEP \x3, 10, 17, \t0
ASCON_PL_STEP \x4, 7, 41, \t0
.endm
#elif (ASCON_RV64_TYPE2)
.macro ASCON_PL x0, x1, x2, x3, x4, t0
ascon.sigma \x0, \x0, 0
ascon.sigma \x1, \x1, 1
ascon.sigma \x2, \x2, 2
ascon.sigma \x3, \x3, 3
ascon.sigma \x4, \x4, 4
.endm
#endif
// operations in each round
.macro ASCON_ROUND x0, x1, x2, x3, x4, rci, t0, t1, t2
ASCON_PC \x2, \rci
ASCON_PS \x0, \x1, \x2, \x3, \x4, \t0, \t1, \t2
ASCON_PL \x3, \x1, \x2, \x0, \x4, \t0
.endm
// Ascon permutation
.section .text
.global P6
P6:
ASCON_PROLOGUE
ASCON_LDSTATE a2, a3, a4, a5, a6
//
ASCON_ROUND a2, a3, a4, a5, a6, 0x96, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x87, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0x78, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x69, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0x5A, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x4B, t0, t1, t6
//
ASCON_STSTATE a2, a3, a4, a5, a6
ASCON_EPILOGUE
.section .text
.global P12
P12:
ASCON_PROLOGUE
ASCON_LDSTATE a2, a3, a4, a5, a6
//
ASCON_ROUND a2, a3, a4, a5, a6, 0xF0, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0xE1, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0xD2, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0xC3, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0xB4, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0xA5, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0x96, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x87, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0x78, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x69, t0, t1, t6
ASCON_ROUND a2, a3, a4, a5, a6, 0x5A, t0, t1, t6
ASCON_ROUND a5, a3, a4, a2, a6, 0x4B, t0, t1, t6
//
ASCON_STSTATE a2, a3, a4, a5, a6
ASCON_EPILOGUE

1
lwc/src/ascon/nist.url Normal file
View File

@ -0,0 +1 @@
https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-submissions/ascon.zip

3
lwc/src/ascon/nist.zip Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:07a2bc8432612d260cef0945e6a16ff9aa94c9279a2e83b76ae984fdbe8b1a5d
size 2032754

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:49403e24b9cd05a234d27c5a7f37e3f28de52c8f8db07ac744515be225bd7aa6
size 485542

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:68eb5de5bbe2c1d19a212827f9daaec22b49777e93f4fed6300764bbbd5aa480
size 153824

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ffbefd2edd8d997de9157c2bf6ea6bfaa53e03e8ce26f1ee136108ae924b127e
size 164033

View File

@ -0,0 +1,237 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
#define AVX512_SHUFFLE_U64BIG \
_mm512_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, /* word 7 */ \
-1, -1, -1, -1, -1, -1, -1, -1, /* word 6 */ \
-1, -1, -1, -1, -1, -1, -1, -1, /* word 5 */ \
-1, -1, -1, -1, -1, -1, -1, -1, /* word 4 */ \
-1, -1, -1, -1, -1, -1, -1, -1, /* word 3 */ \
-1, -1, -1, -1, -1, -1, -1, -1, /* word 2 */ \
8, 9, 10, 11, 12, 13, 14, 15, /* word 1 */ \
0, 1, 2, 3, 4, 5, 6, 7) /* word 0 */
#if !ASCON_INLINE_MODE
#undef forceinline
#define forceinline
#endif
forceinline void ascon_loadkey(word_t* K0, word_t* K1, word_t* K2,
const uint8_t* k) {
KINIT(K0, K1, K2);
if (CRYPTO_KEYBYTES == 16) {
*K1 = XOR(*K1, LOAD(k, 8));
*K2 = XOR(*K2, LOAD(k + 8, 8));
}
if (CRYPTO_KEYBYTES == 20) {
*K0 = XOR(*K0, KEYROT(WORD_T(0), LOADBYTES(k, 4)));
*K1 = XOR(*K1, LOADBYTES(k + 4, 8));
*K2 = XOR(*K2, LOADBYTES(k + 12, 8));
}
}
forceinline void ascon_aeadinit(state_t* s, const uint8_t* npub,
const uint8_t* k) {
/* load nonce */
word_t N0 = LOAD(npub, 8);
word_t N1 = LOAD(npub + 8, 8);
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* initialize */
PINIT(s);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8)
s->x0 = XOR(s->x0, ASCON_128_IV);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16)
s->x0 = XOR(s->x0, ASCON_128A_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, ASCON_80PQ_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, K0);
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
s->x3 = XOR(s->x3, N0);
s->x4 = XOR(s->x4, N1);
P(s, 12);
if (CRYPTO_KEYBYTES == 20) s->x2 = XOR(s->x2, K0);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("initialization", s);
}
forceinline void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen) {
const __m512i u64big = AVX512_SHUFFLE_U64BIG;
const int mask = (ASCON_AEAD_RATE == 8) ? 0xff : 0xffff;
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
state_t r = *s, t;
if (adlen) {
/* full associated data blocks */
while (adlen >= ASCON_AEAD_RATE) {
t.z = _mm512_maskz_loadu_epi8(mask, ad);
t.z = _mm512_maskz_shuffle_epi8(mask, t.z, u64big);
r.z = _mm512_xor_epi64(r.z, t.z);
P(&r, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
*s = r;
/* final associated data block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
px = &s->x1;
ad += 8;
adlen -= 8;
}
*px = XOR(*px, PAD(adlen));
if (adlen) *px = XOR(*px, LOAD(ad, adlen));
P(s, nr);
}
/* domain separation */
s->x4 = XOR(s->x4, WORD_T(1));
printstate("process associated data", s);
}
forceinline void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m,
uint64_t mlen) {
const __m512i u64big = AVX512_SHUFFLE_U64BIG;
const int mask = (ASCON_AEAD_RATE == 8) ? 0xff : 0xffff;
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
state_t r = *s, t;
/* full plaintext blocks */
while (mlen >= ASCON_AEAD_RATE) {
t.z = _mm512_maskz_loadu_epi8(mask, m);
t.z = _mm512_maskz_shuffle_epi8(mask, t.z, u64big);
r.z = _mm512_xor_epi64(r.z, t.z);
t.z = _mm512_maskz_shuffle_epi8(mask, r.z, u64big);
_mm512_mask_storeu_epi8(c, mask, t.z);
P(&r, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
*s = r;
/* final plaintext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
px = &s->x1;
m += 8;
c += 8;
mlen -= 8;
}
*px = XOR(*px, PAD(mlen));
if (mlen) {
*px = XOR(*px, LOAD(m, mlen));
STORE(c, *px, mlen);
}
printstate("process plaintext", s);
}
forceinline void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c,
uint64_t clen) {
const __m512i u64big = AVX512_SHUFFLE_U64BIG;
const int mask = (ASCON_AEAD_RATE == 8) ? 0xff : 0xffff;
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
state_t r = *s, t, u;
/* full ciphertext blocks */
while (clen >= ASCON_AEAD_RATE) {
t.z = _mm512_maskz_loadu_epi8(mask, c);
t.z = _mm512_maskz_shuffle_epi8(mask, t.z, u64big);
r.z = _mm512_xor_epi64(r.z, t.z);
u.z = _mm512_maskz_shuffle_epi8(mask, r.z, u64big);
r.z = _mm512_mask_blend_epi8(mask, r.z, t.z);
_mm512_mask_storeu_epi8(m, mask, u.z);
P(&r, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
*s = r;
/* final ciphertext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
px = &s->x1;
m += 8;
c += 8;
clen -= 8;
}
*px = XOR(*px, PAD(clen));
if (clen) {
word_t cx = LOAD(c, clen);
*px = XOR(*px, cx);
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px = XOR(*px, cx);
}
printstate("process ciphertext", s);
}
forceinline void ascon_final(state_t* s, const uint8_t* k) {
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* finalize */
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) {
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
}
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) {
s->x2 = XOR(s->x2, K1);
s->x3 = XOR(s->x3, K2);
}
if (CRYPTO_KEYBYTES == 20) {
s->x1 = XOR(s->x1, KEYROT(K0, K1));
s->x2 = XOR(s->x2, KEYROT(K1, K2));
s->x3 = XOR(s->x3, KEYROT(K2, WORD_T(0)));
}
P(s, 12);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("finalization", s);
}
int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
*clen = mlen + CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, k);
/* set tag */
STOREBYTES(c + mlen, s.x3, 8);
STOREBYTES(c + mlen + 8, s.x4, 8);
return 0;
}
int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen,
unsigned char* nsec, const unsigned char* c,
unsigned long long clen, const unsigned char* ad,
unsigned long long adlen, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
if (clen < CRYPTO_ABYTES) return -1;
*mlen = clen = clen - CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, k);
/* verify tag (should be constant time, check compiler output) */
s.x3 = XOR(s.x3, LOADBYTES(c + clen, 8));
s.x4 = XOR(s.x4, LOADBYTES(c + clen + 8, 8));
return NOTZERO(s.x3, s.x4);
}

View File

@ -0,0 +1,7 @@
#define CRYPTO_VERSION "1.2.5"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define ASCON_AEAD_RATE 16

View File

@ -0,0 +1,22 @@
#ifndef ASCON_H_
#define ASCON_H_
#include <immintrin.h>
#include <stdint.h>
#include "word.h"
typedef union {
__m512i z;
struct {
word_t x0, x1, x2, x3, x4, x5, x6, x7;
};
} state_t;
void ascon_aeadinit(state_t* s, const uint8_t* npub, const uint8_t* k);
void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen);
void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m, uint64_t mlen);
void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c, uint64_t clen);
void ascon_final(state_t* s, const uint8_t* k);
#endif /* ASCON_H */

View File

@ -0,0 +1,19 @@
#ifndef CONFIG_H_
#define CONFIG_H_
/* inline the ascon mode */
#ifndef ASCON_INLINE_MODE
#define ASCON_INLINE_MODE 1
#endif
/* inline all permutations */
#ifndef ASCON_INLINE_PERM
#define ASCON_INLINE_PERM 1
#endif
/* unroll permutation loops */
#ifndef ASCON_UNROLL_LOOPS
#define ASCON_UNROLL_LOOPS 1
#endif
#endif /* CONFIG_H_ */

View File

@ -0,0 +1,39 @@
#ifndef ENDIAN_H_
#define ENDIAN_H_
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* macros for big endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for big endian machines")
#endif
#define U64BIG(x) (x)
#define U32BIG(x) (x)
#define U16BIG(x) (x)
#elif defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
/* macros for little endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for little endian machines")
#endif
#define U64BIG(x) \
(((0x00000000000000FFULL & (x)) << 56) | \
((0x000000000000FF00ULL & (x)) << 40) | \
((0x0000000000FF0000ULL & (x)) << 24) | \
((0x00000000FF000000ULL & (x)) << 8) | \
((0x000000FF00000000ULL & (x)) >> 8) | \
((0x0000FF0000000000ULL & (x)) >> 24) | \
((0x00FF000000000000ULL & (x)) >> 40) | \
((0xFF00000000000000ULL & (x)) >> 56))
#define U32BIG(x) \
(((0x000000FF & (x)) << 24) | ((0x0000FF00 & (x)) << 8) | \
((0x00FF0000 & (x)) >> 8) | ((0xFF000000 & (x)) >> 24))
#define U16BIG(x) (((0x00FF & (x)) << 8) | ((0xFF00 & (x)) >> 8))
#else
#error "Ascon byte order macros not defined in endian.h"
#endif
#endif /* ENDIAN_H_ */

View File

@ -0,0 +1,19 @@
#ifndef FORCEINLINE_H_
#define FORCEINLINE_H_
/* define forceinline macro */
#ifdef _MSC_VER
#define forceinline __forceinline
#elif defined(__GNUC__)
#define forceinline inline __attribute__((__always_inline__))
#elif defined(__CLANG__)
#if __has_attribute(__always_inline__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#endif
#else
#define forceinline inline
#endif
#endif /* FORCEINLINE_H_ */

View File

@ -0,0 +1 @@
Branches reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1 @@
Addresses reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1,2 @@
Christoph Dobraunig
Martin Schläffer

View File

@ -0,0 +1,15 @@
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
void P8(state_t* s) { P8ROUNDS(s); }
void P6(state_t* s) { P6ROUNDS(s); }
#endif
#if !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
void P(state_t* s, int nr) { PROUNDS(s, nr); }
#endif

View File

@ -0,0 +1,138 @@
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "printstate.h"
#include "round.h"
#define ASCON_128_KEYBYTES 16
#define ASCON_128A_KEYBYTES 16
#define ASCON_80PQ_KEYBYTES 20
#define ASCON_128_RATE 8
#define ASCON_128A_RATE 16
#define ASCON_HASH_RATE 8
#define ASCON_128_PA_ROUNDS 12
#define ASCON_128_PB_ROUNDS 6
#define ASCON_128A_PA_ROUNDS 12
#define ASCON_128A_PB_ROUNDS 8
#define ASCON_HASH_PA_ROUNDS 12
#define ASCON_HASH_PB_ROUNDS 12
#define ASCON_HASHA_PA_ROUNDS 12
#define ASCON_HASHA_PB_ROUNDS 8
#define ASCON_HASH_BYTES 32
#define ASCON_128_IV WORD_T(0x80400c0600000000ull)
#define ASCON_128A_IV WORD_T(0x80800c0800000000ull)
#define ASCON_80PQ_IV WORD_T(0xa0400c0600000000ull)
#define ASCON_HASH_IV WORD_T(0x00400c0000000100ull)
#define ASCON_HASHA_IV WORD_T(0x00400c0400000100ull)
#define ASCON_XOF_IV WORD_T(0x00400c0000000000ull)
#define ASCON_XOFA_IV WORD_T(0x00400c0400000000ull)
#define ASCON_HASH_IV0 WORD_T(0xee9398aadb67f03dull)
#define ASCON_HASH_IV1 WORD_T(0x8bb21831c60f1002ull)
#define ASCON_HASH_IV2 WORD_T(0xb48a92db98d5da62ull)
#define ASCON_HASH_IV3 WORD_T(0x43189921b8f8e3e8ull)
#define ASCON_HASH_IV4 WORD_T(0x348fa5c9d525e140ull)
#define ASCON_HASHA_IV0 WORD_T(0x01470194fc6528a6ull)
#define ASCON_HASHA_IV1 WORD_T(0x738ec38ac0adffa7ull)
#define ASCON_HASHA_IV2 WORD_T(0x2ec8e3296c76384cull)
#define ASCON_HASHA_IV3 WORD_T(0xd6f6a54d7f52377dull)
#define ASCON_HASHA_IV4 WORD_T(0xa13c42a223be8d87ull)
#define ASCON_XOF_IV0 WORD_T(0xb57e273b814cd416ull)
#define ASCON_XOF_IV1 WORD_T(0x2b51042562ae2420ull)
#define ASCON_XOF_IV2 WORD_T(0x66a3a7768ddf2218ull)
#define ASCON_XOF_IV3 WORD_T(0x5aad0a7a8153650cull)
#define ASCON_XOF_IV4 WORD_T(0x4f3e0e32539493b6ull)
#define ASCON_XOFA_IV0 WORD_T(0x44906568b77b9832ull)
#define ASCON_XOFA_IV1 WORD_T(0xcd8d6cae53455532ull)
#define ASCON_XOFA_IV2 WORD_T(0xf7b5212756422129ull)
#define ASCON_XOFA_IV3 WORD_T(0x246885e1de0d225bull)
#define ASCON_XOFA_IV4 WORD_T(0xa8cb5ce33449973full)
#define START(n) ((3 + (n)) << 4 | (12 - (n)))
#define RC(c) WORD_T(c)
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC(0xf0));
ROUND(s, RC(0xe1));
ROUND(s, RC(0xd2));
ROUND(s, RC(0xc3));
ROUND(s, RC(0xb4));
ROUND(s, RC(0xa5));
ROUND(s, RC(0x96));
ROUND(s, RC(0x87));
ROUND(s, RC(0x78));
ROUND(s, RC(0x69));
ROUND(s, RC(0x5a));
ROUND(s, RC(0x4b));
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC(0xb4));
ROUND(s, RC(0xa5));
ROUND(s, RC(0x96));
ROUND(s, RC(0x87));
ROUND(s, RC(0x78));
ROUND(s, RC(0x69));
ROUND(s, RC(0x5a));
ROUND(s, RC(0x4b));
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC(0x96));
ROUND(s, RC(0x87));
ROUND(s, RC(0x78));
ROUND(s, RC(0x69));
ROUND(s, RC(0x5a));
ROUND(s, RC(0x4b));
}
forceinline void PROUNDS(state_t* s, int nr) {
for (int i = START(nr); i > 0x4a; i -= 0x0f) ROUND(s, RC(i));
}
#if ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12ROUNDS(s);
if (nr == 8) P8ROUNDS(s);
if (nr == 6) P6ROUNDS(s);
}
#elif !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s);
void P8(state_t* s);
void P6(state_t* s);
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12(s);
if (nr == 8) P8(s);
if (nr == 6) P6(s);
}
#elif ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) { PROUNDS(s, nr); }
#else /* !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS */
void P(state_t* s, int nr);
#endif
#endif /* PERMUTATIONS_H_ */

View File

@ -0,0 +1,21 @@
#ifdef ASCON_PRINTSTATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
void printword(const char* text, const word_t x) {
printf("%s=%016" PRIx64 "\n", text, WORDTOU64(x));
}
void printstate(const char* text, const state_t* s) {
printf("%s:\n", text);
printword(" x0", s->x0);
printword(" x1", s->x1);
printword(" x2", s->x2);
printword(" x3", s->x3);
printword(" x4", s->x4);
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINTSTATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const word_t x);
void printstate(const char* text, const state_t* s);
#else
#define printword(text, w) \
do { \
} while (0)
#define printstate(text, s) \
do { \
} while (0)
#endif
#endif /* PRINTSTATE_H_ */

View File

@ -0,0 +1,51 @@
#ifndef ROUND_H_
#define ROUND_H_
#include "ascon.h"
#include "printstate.h"
forceinline void KINIT(word_t* K0, word_t* K1, word_t* K2) {
*K0 = WORD_T(0);
*K1 = WORD_T(0);
*K2 = WORD_T(0);
}
forceinline void PINIT(state_t* s) {
s->x0 = WORD_T(0);
s->x1 = WORD_T(0);
s->x2 = WORD_T(0);
s->x3 = WORD_T(0);
s->x4 = WORD_T(0);
}
forceinline void ROUND(state_t* s, word_t C) {
uint64_t x = 0;
__mmask8 mxor1 = 0x15;
__mmask8 mxor2 = 0x0b;
__m512i pxor1 = _mm512_set_epi64(x, x, x, 3, x, 1, x, 4);
__m512i pxor2 = _mm512_set_epi64(x, x, x, x, 2, x, 0, 4);
__m512i c = _mm512_set_epi64(x, x, x, 0, 0, C, 0, 0);
__m512i n = _mm512_set_epi64(x, x, x, 0, 0, ~0ull, 0, 0);
__m512i pchi1 = _mm512_set_epi64(x, x, x, 0, 4, 3, 2, 1);
__m512i pchi2 = _mm512_set_epi64(x, x, x, 1, 0, 4, 3, 2);
__m512i rot1 = _mm512_set_epi64(x, x, x, 7, 10, 1, 61, 19);
__m512i rot2 = _mm512_set_epi64(x, x, x, 41, 17, 6, 39, 28);
__m512i t0, t1, t2;
/* round constant + s-box layer */
t0 = _mm512_maskz_permutexvar_epi64(mxor1, pxor1, s->z);
t0 = _mm512_ternarylogic_epi64(s->z, t0, c, 0x96);
/* keccak s-box start */
t1 = _mm512_permutexvar_epi64(pchi1, t0);
t2 = _mm512_permutexvar_epi64(pchi2, t0);
t0 = _mm512_ternarylogic_epi64(t0, t1, t2, 0xd2);
/* keccak s-box end */
t1 = _mm512_maskz_permutexvar_epi64(mxor2, pxor2, t0);
t0 = _mm512_ternarylogic_epi64(t0, t1, n, 0x96);
/* linear layer */
t1 = _mm512_rorv_epi64(t0, rot1);
t2 = _mm512_rorv_epi64(t0, rot2);
s->z = _mm512_ternarylogic_epi64(t0, t1, t2, 0x96);
printstate(" round output", s);
}
#endif /* ROUND_H_ */

View File

@ -0,0 +1,69 @@
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include "endian.h"
#include "forceinline.h"
typedef uint64_t word_t;
#define WORD_T
#define UINT64_T
#define U64TOWORD
#define WORDTOU64
forceinline word_t ROR(word_t x, int n) { return x >> n | x << (64 - n); }
forceinline word_t NOT(word_t a) { return ~a; }
forceinline word_t XOR(word_t a, word_t b) { return a ^ b; }
forceinline word_t AND(word_t a, word_t b) { return a & b; }
forceinline word_t KEYROT(word_t lo2hi, word_t hi2lo) {
return lo2hi << 32 | hi2lo >> 32;
}
forceinline int NOTZERO(word_t a, word_t b) {
uint64_t result = a | b;
result |= result >> 32;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
forceinline word_t PAD(int i) { return 0x80ull << (56 - 8 * i); }
forceinline word_t CLEAR(word_t w, int n) {
/* undefined for n == 0 */
uint64_t mask = 0x00ffffffffffffffull >> (n * 8 - 8);
return w & mask;
}
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline word_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64BIG(x);
}
forceinline void STORE(uint8_t* bytes, word_t w, int n) {
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= U64BIG(w);
}
forceinline word_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
for (int i = 0; i < n; ++i) ((uint8_t*)&x)[7 - i] = bytes[i];
return x;
}
forceinline void STOREBYTES(uint8_t* bytes, word_t w, int n) {
for (int i = 0; i < n; ++i) bytes[i] = ((uint8_t*)&w)[7 - i];
}
#endif /* WORD_H_ */

View File

@ -0,0 +1,219 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
#if !ASCON_INLINE_MODE
#undef forceinline
#define forceinline
#endif
forceinline void ascon_loadkey(word_t* K0, word_t* K1, word_t* K2,
const uint8_t* k) {
KINIT(K0, K1, K2);
if (CRYPTO_KEYBYTES == 16) {
*K1 = XOR(*K1, LOAD(k, 8));
*K2 = XOR(*K2, LOAD(k + 8, 8));
}
if (CRYPTO_KEYBYTES == 20) {
*K0 = XOR(*K0, KEYROT(WORD_T(0), LOADBYTES(k, 4)));
*K1 = XOR(*K1, LOADBYTES(k + 4, 8));
*K2 = XOR(*K2, LOADBYTES(k + 12, 8));
}
}
forceinline void ascon_aeadinit(state_t* s, const uint8_t* npub,
const uint8_t* k) {
/* load nonce */
word_t N0 = LOAD(npub, 8);
word_t N1 = LOAD(npub + 8, 8);
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* initialize */
PINIT(s);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8)
s->x0 = XOR(s->x0, ASCON_128_IV);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16)
s->x0 = XOR(s->x0, ASCON_128A_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, ASCON_80PQ_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, K0);
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
s->x3 = XOR(s->x3, N0);
s->x4 = XOR(s->x4, N1);
P(s, 12);
if (CRYPTO_KEYBYTES == 20) s->x2 = XOR(s->x2, K0);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("initialization", s);
}
forceinline void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
if (adlen) {
/* full associated data blocks */
while (adlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
if (ASCON_AEAD_RATE == 16) s->x1 = XOR(s->x1, LOAD(ad + 8, 8));
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
px = &s->x1;
ad += 8;
adlen -= 8;
}
*px = XOR(*px, PAD(adlen));
if (adlen) *px = XOR(*px, LOAD(ad, adlen));
P(s, nr);
}
/* domain separation */
s->x4 = XOR(s->x4, WORD_T(1));
printstate("process associated data", s);
}
forceinline void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m,
uint64_t mlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full plaintext blocks */
while (mlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
if (ASCON_AEAD_RATE == 16) {
s->x1 = XOR(s->x1, LOAD(m + 8, 8));
STORE(c + 8, s->x1, 8);
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
px = &s->x1;
m += 8;
c += 8;
mlen -= 8;
}
*px = XOR(*px, PAD(mlen));
if (mlen) {
*px = XOR(*px, LOAD(m, mlen));
STORE(c, *px, mlen);
}
printstate("process plaintext", s);
}
forceinline void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c,
uint64_t clen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full ciphertext blocks */
while (clen >= ASCON_AEAD_RATE) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x1 = XOR(s->x1, cx);
STORE(m + 8, s->x1, 8);
s->x1 = cx;
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
px = &s->x1;
m += 8;
c += 8;
clen -= 8;
}
*px = XOR(*px, PAD(clen));
if (clen) {
word_t cx = LOAD(c, clen);
*px = XOR(*px, cx);
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px = XOR(*px, cx);
}
printstate("process ciphertext", s);
}
forceinline void ascon_final(state_t* s, const uint8_t* k) {
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* finalize */
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) {
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
}
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) {
s->x2 = XOR(s->x2, K1);
s->x3 = XOR(s->x3, K2);
}
if (CRYPTO_KEYBYTES == 20) {
s->x1 = XOR(s->x1, KEYROT(K0, K1));
s->x2 = XOR(s->x2, KEYROT(K1, K2));
s->x3 = XOR(s->x3, KEYROT(K2, WORD_T(0)));
}
P(s, 12);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("finalization", s);
}
int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
*clen = mlen + CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, k);
/* set tag */
STOREBYTES(c + mlen, s.x3, 8);
STOREBYTES(c + mlen + 8, s.x4, 8);
return 0;
}
int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen,
unsigned char* nsec, const unsigned char* c,
unsigned long long clen, const unsigned char* ad,
unsigned long long adlen, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
if (clen < CRYPTO_ABYTES) return -1;
*mlen = clen = clen - CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, k);
/* verify tag (should be constant time, check compiler output) */
s.x3 = XOR(s.x3, LOADBYTES(c + clen, 8));
s.x4 = XOR(s.x4, LOADBYTES(c + clen + 8, 8));
return NOTZERO(s.x3, s.x4);
}

View File

@ -0,0 +1,7 @@
#define CRYPTO_VERSION "1.2.5"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define ASCON_AEAD_RATE 16

View File

@ -0,0 +1,18 @@
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef struct {
word_t x0, x1, x2, x3, x4;
} state_t;
void ascon_aeadinit(state_t* s, const uint8_t* npub, const uint8_t* k);
void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen);
void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m, uint64_t mlen);
void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c, uint64_t clen);
void ascon_final(state_t* s, const uint8_t* k);
#endif /* ASCON_H */

View File

@ -0,0 +1,19 @@
#ifndef CONFIG_H_
#define CONFIG_H_
/* inline the ascon mode */
#ifndef ASCON_INLINE_MODE
#define ASCON_INLINE_MODE 1
#endif
/* inline all permutations */
#ifndef ASCON_INLINE_PERM
#define ASCON_INLINE_PERM 0
#endif
/* unroll permutation loops */
#ifndef ASCON_UNROLL_LOOPS
#define ASCON_UNROLL_LOOPS 1
#endif
#endif /* CONFIG_H_ */

View File

@ -0,0 +1,39 @@
#ifndef ENDIAN_H_
#define ENDIAN_H_
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* macros for big endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for big endian machines")
#endif
#define U64BIG(x) (x)
#define U32BIG(x) (x)
#define U16BIG(x) (x)
#elif defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
/* macros for little endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for little endian machines")
#endif
#define U64BIG(x) \
(((0x00000000000000FFULL & (x)) << 56) | \
((0x000000000000FF00ULL & (x)) << 40) | \
((0x0000000000FF0000ULL & (x)) << 24) | \
((0x00000000FF000000ULL & (x)) << 8) | \
((0x000000FF00000000ULL & (x)) >> 8) | \
((0x0000FF0000000000ULL & (x)) >> 24) | \
((0x00FF000000000000ULL & (x)) >> 40) | \
((0xFF00000000000000ULL & (x)) >> 56))
#define U32BIG(x) \
(((0x000000FF & (x)) << 24) | ((0x0000FF00 & (x)) << 8) | \
((0x00FF0000 & (x)) >> 8) | ((0xFF000000 & (x)) >> 24))
#define U16BIG(x) (((0x00FF & (x)) << 8) | ((0xFF00 & (x)) >> 8))
#else
#error "Ascon byte order macros not defined in endian.h"
#endif
#endif /* ENDIAN_H_ */

View File

@ -0,0 +1,19 @@
#ifndef FORCEINLINE_H_
#define FORCEINLINE_H_
/* define forceinline macro */
#ifdef _MSC_VER
#define forceinline __forceinline
#elif defined(__GNUC__)
#define forceinline inline __attribute__((__always_inline__))
#elif defined(__CLANG__)
#if __has_attribute(__always_inline__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#endif
#else
#define forceinline inline
#endif
#endif /* FORCEINLINE_H_ */

View File

@ -0,0 +1 @@
Branches reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1 @@
Addresses reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1,2 @@
Christoph Dobraunig
Martin Schläffer

View File

@ -0,0 +1,49 @@
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "forceinline.h"
forceinline uint32_t deinterleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t r0, r1;
lo = deinterleave_uint32(lo);
hi = deinterleave_uint32(hi);
r0 = (lo & 0x0000FFFF) | (hi << 16);
r1 = (lo >> 16) | (hi & 0xFFFF0000);
return (uint64_t)r1 << 32 | r0;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t r0 = in;
uint32_t r1 = in >> 32;
uint32_t lo = (r0 & 0x0000FFFF) | (r1 << 16);
uint32_t hi = (r0 >> 16) | (r1 & 0xFFFF0000);
lo = interleave_uint32(lo);
hi = interleave_uint32(hi);
return (uint64_t)hi << 32 | lo;
}
#endif /* INTERLEAVE_H_ */

View File

@ -0,0 +1,23 @@
#include "permutations.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[][2] = {{0xc, 0xc}, {0x9, 0xc}, {0xc, 0x9}, {0x9, 0x9},
{0x6, 0xc}, {0x3, 0xc}, {0x6, 0x9}, {0x3, 0x9},
{0xc, 0x6}, {0x9, 0x6}, {0xc, 0x3}, {0x9, 0x3}};
#endif
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
void P8(state_t* s) { P8ROUNDS(s); }
void P6(state_t* s) { P6ROUNDS(s); }
#endif
#if !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
void P(state_t* s, int nr) { PROUNDS(s, nr); }
#endif

View File

@ -0,0 +1,139 @@
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "printstate.h"
#include "round.h"
#define ASCON_128_KEYBYTES 16
#define ASCON_128A_KEYBYTES 16
#define ASCON_80PQ_KEYBYTES 20
#define ASCON_128_RATE 8
#define ASCON_128A_RATE 16
#define ASCON_HASH_RATE 8
#define ASCON_128_PA_ROUNDS 12
#define ASCON_128_PB_ROUNDS 6
#define ASCON_128A_PA_ROUNDS 12
#define ASCON_128A_PB_ROUNDS 8
#define ASCON_HASH_PA_ROUNDS 12
#define ASCON_HASH_PB_ROUNDS 12
#define ASCON_HASHA_PA_ROUNDS 12
#define ASCON_HASHA_PB_ROUNDS 8
#define ASCON_HASH_BYTES 32
#define ASCON_128_IV WORD_T(0x8021000008220000ull)
#define ASCON_128A_IV WORD_T(0x8822000000200000ull)
#define ASCON_80PQ_IV WORD_T(0xc021000008220000ull)
#define ASCON_HASH_IV WORD_T(0x0020000008020010ull)
#define ASCON_XOF_IV WORD_T(0x0020000008020000ull)
#define ASCON_HASH_IV0 WORD_T(0xf9afb5c6a540dbc7ull)
#define ASCON_HASH_IV1 WORD_T(0xbd2493011445a340ull)
#define ASCON_HASH_IV2 WORD_T(0xcb9ba8b5604d4fc8ull)
#define ASCON_HASH_IV3 WORD_T(0x12a4eede94514c98ull)
#define ASCON_HASH_IV4 WORD_T(0x4bca84c06339f398ull)
#define ASCON_HASHA_IV0 WORD_T(0x0108e46d1b16eb02ull)
#define ASCON_HASHA_IV1 WORD_T(0x5b9b8efdd29083f3ull)
#define ASCON_HASHA_IV2 WORD_T(0x7ad665622891ae4aull)
#define ASCON_HASHA_IV3 WORD_T(0x9dc27156ee3bfc7full)
#define ASCON_HASHA_IV4 WORD_T(0xc61d5fa916801633ull)
#define ASCON_XOF_IV0 WORD_T(0xc75782817e351ae6ull)
#define ASCON_XOF_IV1 WORD_T(0x70045f441d238220ull)
#define ASCON_XOF_IV2 WORD_T(0x5dd5ab52a13e3f04ull)
#define ASCON_XOF_IV3 WORD_T(0x3e378142c30c1db2ull)
#define ASCON_XOF_IV4 WORD_T(0x3735189db624d656ull)
#define ASCON_XOFA_IV0 WORD_T(0x0846d7a5a4b87d44ull)
#define ASCON_XOFA_IV1 WORD_T(0xaa6f1005b3a2dbf4ull)
#define ASCON_XOFA_IV2 WORD_T(0xdc451146f713e811ull)
#define ASCON_XOFA_IV3 WORD_T(0x468cb2532839e30dull)
#define ASCON_XOFA_IV4 WORD_T(0xeb2d429709e96977ull)
#define START(n) (12 - n)
#define RC(e, o) WORD_T((uint64_t)o << 32 | e)
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC(0xc, 0xc));
ROUND(s, RC(0x9, 0xc));
ROUND(s, RC(0xc, 0x9));
ROUND(s, RC(0x9, 0x9));
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
extern const uint8_t constants[][2];
forceinline void PROUNDS(state_t* s, int nr) {
for (int i = START(nr); i < 12; i++)
ROUND(s, RC(constants[i][0], constants[i][1]));
}
#if ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12ROUNDS(s);
if (nr == 8) P8ROUNDS(s);
if (nr == 6) P6ROUNDS(s);
}
#elif !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s);
void P8(state_t* s);
void P6(state_t* s);
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12(s);
if (nr == 8) P8(s);
if (nr == 6) P6(s);
}
#elif ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) { PROUNDS(s, nr); }
#else /* !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS */
void P(state_t* s, int nr);
#endif
#endif /* PERMUTATIONS_H_ */

View File

@ -0,0 +1,21 @@
#ifdef ASCON_PRINTSTATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
void printword(const char* text, const word_t x) {
printf("%s=%016" PRIx64 "\n", text, WORDTOU64(x));
}
void printstate(const char* text, const state_t* s) {
printf("%s:\n", text);
printword(" x0", s->x0);
printword(" x1", s->x1);
printword(" x2", s->x2);
printword(" x3", s->x3);
printword(" x4", s->x4);
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINTSTATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const word_t x);
void printstate(const char* text, const state_t* s);
#else
#define printword(text, w) \
do { \
} while (0)
#define printstate(text, s) \
do { \
} while (0)
#endif
#endif /* PRINTSTATE_H_ */

View File

@ -0,0 +1,52 @@
#ifndef ROUND_H_
#define ROUND_H_
#include "ascon.h"
#include "printstate.h"
forceinline void KINIT(word_t* K0, word_t* K1, word_t* K2) {
*K0 = WORD_T(0);
*K1 = WORD_T(0);
*K2 = WORD_T(0);
}
forceinline void PINIT(state_t* s) {
s->x0 = WORD_T(0);
s->x1 = WORD_T(0);
s->x2 = WORD_T(0);
s->x3 = WORD_T(0);
s->x4 = WORD_T(0);
}
forceinline void ROUND(state_t* s, word_t C) {
state_t t;
/* round constant */
s->x2 = XOR(s->x2, C);
/* s-box layer */
s->x0 = XOR(s->x0, s->x4);
s->x4 = XOR(s->x4, s->x3);
s->x2 = XOR(s->x2, s->x1);
t.x0 = XOR(s->x0, AND(NOT(s->x1), s->x2));
t.x2 = XOR(s->x2, AND(NOT(s->x3), s->x4));
t.x4 = XOR(s->x4, AND(NOT(s->x0), s->x1));
t.x1 = XOR(s->x1, AND(NOT(s->x2), s->x3));
t.x3 = XOR(s->x3, AND(NOT(s->x4), s->x0));
t.x1 = XOR(t.x1, t.x0);
t.x3 = XOR(t.x3, t.x2);
t.x0 = XOR(t.x0, t.x4);
/* linear layer */
s->x2 = XOR(t.x2, ROR(t.x2, 6 - 1));
s->x3 = XOR(t.x3, ROR(t.x3, 17 - 10));
s->x4 = XOR(t.x4, ROR(t.x4, 41 - 7));
s->x0 = XOR(t.x0, ROR(t.x0, 28 - 19));
s->x1 = XOR(t.x1, ROR(t.x1, 61 - 39));
s->x2 = XOR(t.x2, ROR(s->x2, 1));
s->x3 = XOR(t.x3, ROR(s->x3, 10));
s->x4 = XOR(t.x4, ROR(s->x4, 7));
s->x0 = XOR(t.x0, ROR(s->x0, 19));
s->x1 = XOR(t.x1, ROR(s->x1, 39));
s->x2 = NOT(s->x2);
printstate(" round output", s);
}
#endif /* ROUND_H_ */

View File

@ -0,0 +1,105 @@
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
typedef struct {
uint32_t e;
uint32_t o;
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return (n == 0) ? x : x >> n | x << (32 - n);
}
forceinline word_t ROR(word_t x, int n) {
word_t r;
r.e = (n % 2) ? ROR32(x.o, (n - 1) / 2) : ROR32(x.e, n / 2);
r.o = (n % 2) ? ROR32(x.e, (n + 1) / 2) : ROR32(x.o, n / 2);
return r;
}
forceinline word_t WORD_T(uint64_t x) { return (word_t){.o = x >> 32, .e = x}; }
forceinline uint64_t UINT64_T(word_t x) { return (uint64_t)x.o << 32 | x.e; }
forceinline word_t U64TOWORD(uint64_t x) { return WORD_T(deinterleave32(x)); }
forceinline uint64_t WORDTOU64(word_t w) { return interleave32(UINT64_T(w)); }
forceinline word_t NOT(word_t a) {
a.e = ~a.e;
a.o = ~a.o;
return a;
}
forceinline word_t XOR(word_t a, word_t b) {
a.e ^= b.e;
a.o ^= b.o;
return a;
}
forceinline word_t AND(word_t a, word_t b) {
a.e &= b.e;
a.o &= b.o;
return a;
}
forceinline word_t KEYROT(word_t lo2hi, word_t hi2lo) {
word_t r;
r.e = lo2hi.e << 16 | hi2lo.e >> 16;
r.o = lo2hi.o << 16 | hi2lo.o >> 16;
return r;
}
forceinline int NOTZERO(word_t a, word_t b) {
uint32_t result = a.e | a.o | b.e | b.o;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
forceinline word_t PAD(int i) {
return WORD_T((uint64_t)(0x8ul << (28 - 4 * i)) << 32);
}
forceinline word_t CLEAR(word_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0x0fffffff >> (n * 4 - 4);
w.e &= mask;
w.o &= mask;
return w;
}
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline word_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(U64BIG(x));
}
forceinline void STORE(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= U64BIG(x);
}
forceinline word_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
for (int i = 0; i < n; ++i) ((uint8_t*)&x)[7 - i] = bytes[i];
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
for (int i = 0; i < n; ++i) bytes[i] = ((uint8_t*)&x)[7 - i];
}
#endif /* WORD_H_ */

View File

@ -0,0 +1,219 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
#if !ASCON_INLINE_MODE
#undef forceinline
#define forceinline
#endif
forceinline void ascon_loadkey(word_t* K0, word_t* K1, word_t* K2,
const uint8_t* k) {
KINIT(K0, K1, K2);
if (CRYPTO_KEYBYTES == 16) {
*K1 = XOR(*K1, LOAD(k, 8));
*K2 = XOR(*K2, LOAD(k + 8, 8));
}
if (CRYPTO_KEYBYTES == 20) {
*K0 = XOR(*K0, KEYROT(WORD_T(0), LOADBYTES(k, 4)));
*K1 = XOR(*K1, LOADBYTES(k + 4, 8));
*K2 = XOR(*K2, LOADBYTES(k + 12, 8));
}
}
forceinline void ascon_aeadinit(state_t* s, const uint8_t* npub,
const uint8_t* k) {
/* load nonce */
word_t N0 = LOAD(npub, 8);
word_t N1 = LOAD(npub + 8, 8);
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* initialize */
PINIT(s);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8)
s->x0 = XOR(s->x0, ASCON_128_IV);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16)
s->x0 = XOR(s->x0, ASCON_128A_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, ASCON_80PQ_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, K0);
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
s->x3 = XOR(s->x3, N0);
s->x4 = XOR(s->x4, N1);
P(s, 12);
if (CRYPTO_KEYBYTES == 20) s->x2 = XOR(s->x2, K0);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("initialization", s);
}
forceinline void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
if (adlen) {
/* full associated data blocks */
while (adlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
if (ASCON_AEAD_RATE == 16) s->x1 = XOR(s->x1, LOAD(ad + 8, 8));
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
px = &s->x1;
ad += 8;
adlen -= 8;
}
*px = XOR(*px, PAD(adlen));
if (adlen) *px = XOR(*px, LOAD(ad, adlen));
P(s, nr);
}
/* domain separation */
s->x4 = XOR(s->x4, WORD_T(1));
printstate("process associated data", s);
}
forceinline void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m,
uint64_t mlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full plaintext blocks */
while (mlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
if (ASCON_AEAD_RATE == 16) {
s->x1 = XOR(s->x1, LOAD(m + 8, 8));
STORE(c + 8, s->x1, 8);
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
px = &s->x1;
m += 8;
c += 8;
mlen -= 8;
}
*px = XOR(*px, PAD(mlen));
if (mlen) {
*px = XOR(*px, LOAD(m, mlen));
STORE(c, *px, mlen);
}
printstate("process plaintext", s);
}
forceinline void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c,
uint64_t clen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full ciphertext blocks */
while (clen >= ASCON_AEAD_RATE) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x1 = XOR(s->x1, cx);
STORE(m + 8, s->x1, 8);
s->x1 = cx;
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
px = &s->x1;
m += 8;
c += 8;
clen -= 8;
}
*px = XOR(*px, PAD(clen));
if (clen) {
word_t cx = LOAD(c, clen);
*px = XOR(*px, cx);
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px = XOR(*px, cx);
}
printstate("process ciphertext", s);
}
forceinline void ascon_final(state_t* s, const uint8_t* k) {
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* finalize */
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) {
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
}
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) {
s->x2 = XOR(s->x2, K1);
s->x3 = XOR(s->x3, K2);
}
if (CRYPTO_KEYBYTES == 20) {
s->x1 = XOR(s->x1, KEYROT(K0, K1));
s->x2 = XOR(s->x2, KEYROT(K1, K2));
s->x3 = XOR(s->x3, KEYROT(K2, WORD_T(0)));
}
P(s, 12);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("finalization", s);
}
int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
*clen = mlen + CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, k);
/* set tag */
STOREBYTES(c + mlen, s.x3, 8);
STOREBYTES(c + mlen + 8, s.x4, 8);
return 0;
}
int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen,
unsigned char* nsec, const unsigned char* c,
unsigned long long clen, const unsigned char* ad,
unsigned long long adlen, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
if (clen < CRYPTO_ABYTES) return -1;
*mlen = clen = clen - CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, k);
/* verify tag (should be constant time, check compiler output) */
s.x3 = XOR(s.x3, LOADBYTES(c + clen, 8));
s.x4 = XOR(s.x4, LOADBYTES(c + clen + 8, 8));
return NOTZERO(s.x3, s.x4);
}

View File

@ -0,0 +1,7 @@
#define CRYPTO_VERSION "1.2.5"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define ASCON_AEAD_RATE 16

View File

@ -0,0 +1,3 @@
aarch64
armeabi
arm

View File

@ -0,0 +1,18 @@
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef struct {
word_t x0, x1, x2, x3, x4;
} state_t;
void ascon_aeadinit(state_t* s, const uint8_t* npub, const uint8_t* k);
void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen);
void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m, uint64_t mlen);
void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c, uint64_t clen);
void ascon_final(state_t* s, const uint8_t* k);
#endif /* ASCON_H */

View File

@ -0,0 +1,19 @@
#ifndef CONFIG_H_
#define CONFIG_H_
/* inline the ascon mode */
#ifndef ASCON_INLINE_MODE
#define ASCON_INLINE_MODE 0
#endif
/* inline all permutations */
#ifndef ASCON_INLINE_PERM
#define ASCON_INLINE_PERM 0
#endif
/* unroll permutation loops */
#ifndef ASCON_UNROLL_LOOPS
#define ASCON_UNROLL_LOOPS 1
#endif
#endif /* CONFIG_H_ */

View File

@ -0,0 +1,39 @@
#ifndef ENDIAN_H_
#define ENDIAN_H_
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* macros for big endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for big endian machines")
#endif
#define U64BIG(x) (x)
#define U32BIG(x) (x)
#define U16BIG(x) (x)
#elif defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
/* macros for little endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for little endian machines")
#endif
#define U64BIG(x) \
(((0x00000000000000FFULL & (x)) << 56) | \
((0x000000000000FF00ULL & (x)) << 40) | \
((0x0000000000FF0000ULL & (x)) << 24) | \
((0x00000000FF000000ULL & (x)) << 8) | \
((0x000000FF00000000ULL & (x)) >> 8) | \
((0x0000FF0000000000ULL & (x)) >> 24) | \
((0x00FF000000000000ULL & (x)) >> 40) | \
((0xFF00000000000000ULL & (x)) >> 56))
#define U32BIG(x) \
(((0x000000FF & (x)) << 24) | ((0x0000FF00 & (x)) << 8) | \
((0x00FF0000 & (x)) >> 8) | ((0xFF000000 & (x)) >> 24))
#define U16BIG(x) (((0x00FF & (x)) << 8) | ((0xFF00 & (x)) >> 8))
#else
#error "Ascon byte order macros not defined in endian.h"
#endif
#endif /* ENDIAN_H_ */

View File

@ -0,0 +1,19 @@
#ifndef FORCEINLINE_H_
#define FORCEINLINE_H_
/* define forceinline macro */
#ifdef _MSC_VER
#define forceinline __forceinline
#elif defined(__GNUC__)
#define forceinline inline __attribute__((__always_inline__))
#elif defined(__CLANG__)
#if __has_attribute(__always_inline__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#endif
#else
#define forceinline inline
#endif
#endif /* FORCEINLINE_H_ */

View File

@ -0,0 +1 @@
Branches reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1 @@
Addresses reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1,2 @@
Christoph Dobraunig
Martin Schläffer

View File

@ -0,0 +1,49 @@
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "forceinline.h"
forceinline uint32_t deinterleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t r0, r1;
lo = deinterleave_uint32(lo);
hi = deinterleave_uint32(hi);
r0 = (lo & 0x0000FFFF) | (hi << 16);
r1 = (lo >> 16) | (hi & 0xFFFF0000);
return (uint64_t)r1 << 32 | r0;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t r0 = in;
uint32_t r1 = in >> 32;
uint32_t lo = (r0 & 0x0000FFFF) | (r1 << 16);
uint32_t hi = (r0 >> 16) | (r1 & 0xFFFF0000);
lo = interleave_uint32(lo);
hi = interleave_uint32(hi);
return (uint64_t)hi << 32 | lo;
}
#endif /* INTERLEAVE_H_ */

View File

@ -0,0 +1,23 @@
#include "permutations.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[][2] = {{0xc, 0xc}, {0x9, 0xc}, {0xc, 0x9}, {0x9, 0x9},
{0x6, 0xc}, {0x3, 0xc}, {0x6, 0x9}, {0x3, 0x9},
{0xc, 0x6}, {0x9, 0x6}, {0xc, 0x3}, {0x9, 0x3}};
#endif
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
void P8(state_t* s) { P8ROUNDS(s); }
void P6(state_t* s) { P6ROUNDS(s); }
#endif
#if !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
void P(state_t* s, int nr) { PROUNDS(s, nr); }
#endif

View File

@ -0,0 +1,139 @@
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "printstate.h"
#include "round.h"
#define ASCON_128_KEYBYTES 16
#define ASCON_128A_KEYBYTES 16
#define ASCON_80PQ_KEYBYTES 20
#define ASCON_128_RATE 8
#define ASCON_128A_RATE 16
#define ASCON_HASH_RATE 8
#define ASCON_128_PA_ROUNDS 12
#define ASCON_128_PB_ROUNDS 6
#define ASCON_128A_PA_ROUNDS 12
#define ASCON_128A_PB_ROUNDS 8
#define ASCON_HASH_PA_ROUNDS 12
#define ASCON_HASH_PB_ROUNDS 12
#define ASCON_HASHA_PA_ROUNDS 12
#define ASCON_HASHA_PB_ROUNDS 8
#define ASCON_HASH_BYTES 32
#define ASCON_128_IV WORD_T(0x8021000008220000ull)
#define ASCON_128A_IV WORD_T(0x8822000000200000ull)
#define ASCON_80PQ_IV WORD_T(0xc021000008220000ull)
#define ASCON_HASH_IV WORD_T(0x0020000008020010ull)
#define ASCON_XOF_IV WORD_T(0x0020000008020000ull)
#define ASCON_HASH_IV0 WORD_T(0xf9afb5c6a540dbc7ull)
#define ASCON_HASH_IV1 WORD_T(0xbd2493011445a340ull)
#define ASCON_HASH_IV2 WORD_T(0xcb9ba8b5604d4fc8ull)
#define ASCON_HASH_IV3 WORD_T(0x12a4eede94514c98ull)
#define ASCON_HASH_IV4 WORD_T(0x4bca84c06339f398ull)
#define ASCON_HASHA_IV0 WORD_T(0x0108e46d1b16eb02ull)
#define ASCON_HASHA_IV1 WORD_T(0x5b9b8efdd29083f3ull)
#define ASCON_HASHA_IV2 WORD_T(0x7ad665622891ae4aull)
#define ASCON_HASHA_IV3 WORD_T(0x9dc27156ee3bfc7full)
#define ASCON_HASHA_IV4 WORD_T(0xc61d5fa916801633ull)
#define ASCON_XOF_IV0 WORD_T(0xc75782817e351ae6ull)
#define ASCON_XOF_IV1 WORD_T(0x70045f441d238220ull)
#define ASCON_XOF_IV2 WORD_T(0x5dd5ab52a13e3f04ull)
#define ASCON_XOF_IV3 WORD_T(0x3e378142c30c1db2ull)
#define ASCON_XOF_IV4 WORD_T(0x3735189db624d656ull)
#define ASCON_XOFA_IV0 WORD_T(0x0846d7a5a4b87d44ull)
#define ASCON_XOFA_IV1 WORD_T(0xaa6f1005b3a2dbf4ull)
#define ASCON_XOFA_IV2 WORD_T(0xdc451146f713e811ull)
#define ASCON_XOFA_IV3 WORD_T(0x468cb2532839e30dull)
#define ASCON_XOFA_IV4 WORD_T(0xeb2d429709e96977ull)
#define START(n) (12 - n)
#define RC(e, o) WORD_T((uint64_t)o << 32 | e)
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC(0xc, 0xc));
ROUND(s, RC(0x9, 0xc));
ROUND(s, RC(0xc, 0x9));
ROUND(s, RC(0x9, 0x9));
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
extern const uint8_t constants[][2];
forceinline void PROUNDS(state_t* s, int nr) {
for (int i = START(nr); i < 12; i++)
ROUND(s, RC(constants[i][0], constants[i][1]));
}
#if ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12ROUNDS(s);
if (nr == 8) P8ROUNDS(s);
if (nr == 6) P6ROUNDS(s);
}
#elif !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s);
void P8(state_t* s);
void P6(state_t* s);
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12(s);
if (nr == 8) P8(s);
if (nr == 6) P6(s);
}
#elif ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) { PROUNDS(s, nr); }
#else /* !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS */
void P(state_t* s, int nr);
#endif
#endif /* PERMUTATIONS_H_ */

View File

@ -0,0 +1,21 @@
#ifdef ASCON_PRINTSTATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
void printword(const char* text, const word_t x) {
printf("%s=%016" PRIx64 "\n", text, WORDTOU64(x));
}
void printstate(const char* text, const state_t* s) {
printf("%s:\n", text);
printword(" x0", s->x0);
printword(" x1", s->x1);
printword(" x2", s->x2);
printword(" x3", s->x3);
printword(" x4", s->x4);
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINTSTATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const word_t x);
void printstate(const char* text, const state_t* s);
#else
#define printword(text, w) \
do { \
} while (0)
#define printstate(text, s) \
do { \
} while (0)
#endif
#endif /* PRINTSTATE_H_ */

View File

@ -0,0 +1,102 @@
#ifndef ROUND_H_
#define ROUND_H_
#include "ascon.h"
#include "printstate.h"
forceinline void KINIT(word_t* K0, word_t* K1, word_t* K2) {
*K0 = WORD_T(0);
*K1 = WORD_T(0);
*K2 = WORD_T(0);
}
forceinline void PINIT(state_t* s) {
s->x0 = WORD_T(0);
s->x1 = WORD_T(0);
s->x2 = WORD_T(0);
s->x3 = WORD_T(0);
s->x4 = WORD_T(0);
}
forceinline void ROUND(state_t* s, word_t C) {
uint32_t tmp0, tmp1, tmp2, tmp3;
/* clang-format off */
__asm__ __volatile__( \
"eor %[x2_e], %[x2_e], %[C_e]\n\t" \
"eor %[x2_o], %[x2_o], %[C_o]\n\t" \
"eor %[x0_e], %[x0_e], %[x4_e]\n\t" \
"eor %[x0_o], %[x0_o], %[x4_o]\n\t" \
"eor %[x4_e], %[x4_e], %[x3_e]\n\t" \
"eor %[x4_o], %[x4_o], %[x3_o]\n\t" \
"eor %[x2_e], %[x2_e], %[x1_e]\n\t" \
"eor %[x2_o], %[x2_o], %[x1_o]\n\t" \
"bic %[tmp0], %[x0_e], %[x4_e]\n\t" \
"bic %[tmp1], %[x4_e], %[x3_e]\n\t" \
"bic %[tmp2], %[x2_e], %[x1_e]\n\t" \
"bic %[tmp3], %[x1_e], %[x0_e]\n\t" \
"eor %[x2_e], %[x2_e], %[tmp1]\n\t" \
"eor %[x0_e], %[x0_e], %[tmp2]\n\t" \
"eor %[x4_e], %[x4_e], %[tmp3]\n\t" \
"bic %[tmp3], %[x3_e], %[x2_e]\n\t" \
"eor %[x3_e], %[x3_e], %[tmp0]\n\t" \
"bic %[tmp2], %[x0_o], %[x4_o]\n\t" \
"bic %[tmp0], %[x2_o], %[x1_o]\n\t" \
"bic %[tmp1], %[x4_o], %[x3_o]\n\t" \
"eor %[x1_e], %[x1_e], %[tmp3]\n\t" \
"eor %[x0_o], %[x0_o], %[tmp0]\n\t" \
"eor %[x2_o], %[x2_o], %[tmp1]\n\t" \
"bic %[tmp3], %[x1_o], %[x0_o]\n\t" \
"bic %[tmp0], %[x3_o], %[x2_o]\n\t" \
"eor %[x3_o], %[x3_o], %[tmp2]\n\t" \
"eor %[x3_o], %[x3_o], %[x2_o]\n\t" \
"eor %[x4_o], %[x4_o], %[tmp3]\n\t" \
"eor %[x1_o], %[x1_o], %[tmp0]\n\t" \
"eor %[x3_e], %[x3_e], %[x2_e]\n\t" \
"eor %[x1_e], %[x1_e], %[x0_e]\n\t" \
"eor %[x1_o], %[x1_o], %[x0_o]\n\t" \
"eor %[x0_e], %[x0_e], %[x4_e]\n\t" \
"eor %[x0_o], %[x0_o], %[x4_o]\n\t" \
"mvn %[x2_e], %[x2_e]\n\t" \
"mvn %[x2_o], %[x2_o]\n\t" \
"eor %[tmp0], %[x0_e], %[x0_o], ror #4\n\t" \
"eor %[tmp1], %[x0_o], %[x0_e], ror #5\n\t" \
"eor %[tmp2], %[x1_e], %[x1_e], ror #11\n\t" \
"eor %[tmp3], %[x1_o], %[x1_o], ror #11\n\t" \
"eor %[x0_e], %[x0_e], %[tmp1], ror #9\n\t" \
"eor %[x0_o], %[x0_o], %[tmp0], ror #10\n\t" \
"eor %[x1_e], %[x1_e], %[tmp3], ror #19\n\t" \
"eor %[x1_o], %[x1_o], %[tmp2], ror #20\n\t" \
"eor %[tmp0], %[x2_e], %[x2_o], ror #2\n\t" \
"eor %[tmp1], %[x2_o], %[x2_e], ror #3\n\t" \
"eor %[tmp2], %[x3_e], %[x3_o], ror #3\n\t" \
"eor %[tmp3], %[x3_o], %[x3_e], ror #4\n\t" \
"eor %[x2_e], %[x2_e], %[tmp1]\n\t" \
"eor %[x2_o], %[x2_o], %[tmp0], ror #1\n\t" \
"eor %[x3_e], %[x3_e], %[tmp2], ror #5\n\t" \
"eor %[x3_o], %[x3_o], %[tmp3], ror #5\n\t" \
"eor %[tmp0], %[x4_e], %[x4_e], ror #17\n\t" \
"eor %[tmp1], %[x4_o], %[x4_o], ror #17\n\t" \
"eor %[x4_e], %[x4_e], %[tmp1], ror #3\n\t" \
"eor %[x4_o], %[x4_o], %[tmp0], ror #4\n\t" \
: [ x0_e ] "+r"(s->x0.e), \
[ x1_e ] "+r"(s->x1.e), \
[ x2_e ] "+r"(s->x2.e), \
[ x3_e ] "+r"(s->x3.e), \
[ x4_e ] "+r"(s->x4.e), \
[ x0_o ] "+r"(s->x0.o), \
[ x1_o ] "+r"(s->x1.o), \
[ x2_o ] "+r"(s->x2.o), \
[ x3_o ] "+r"(s->x3.o), \
[ x4_o ] "+r"(s->x4.o), \
[ tmp0 ] "=r"(tmp0), \
[ tmp1 ] "=r"(tmp1), \
[ tmp2 ] "=r"(tmp2), \
[ tmp3 ] "=r"(tmp3) \
: [ C_e ] "ri"(C.e), \
[ C_o ] "ri"(C.o) \
: );
/* clang-format on */
printstate(" round output", s);
}
#endif /* ROUND_H_ */

View File

@ -0,0 +1,105 @@
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
typedef struct {
uint32_t e;
uint32_t o;
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return (n == 0) ? x : x >> n | x << (32 - n);
}
forceinline word_t ROR(word_t x, int n) {
word_t r;
r.e = (n % 2) ? ROR32(x.o, (n - 1) / 2) : ROR32(x.e, n / 2);
r.o = (n % 2) ? ROR32(x.e, (n + 1) / 2) : ROR32(x.o, n / 2);
return r;
}
forceinline word_t WORD_T(uint64_t x) { return (word_t){.o = x >> 32, .e = x}; }
forceinline uint64_t UINT64_T(word_t x) { return (uint64_t)x.o << 32 | x.e; }
forceinline word_t U64TOWORD(uint64_t x) { return WORD_T(deinterleave32(x)); }
forceinline uint64_t WORDTOU64(word_t w) { return interleave32(UINT64_T(w)); }
forceinline word_t NOT(word_t a) {
a.e = ~a.e;
a.o = ~a.o;
return a;
}
forceinline word_t XOR(word_t a, word_t b) {
a.e ^= b.e;
a.o ^= b.o;
return a;
}
forceinline word_t AND(word_t a, word_t b) {
a.e &= b.e;
a.o &= b.o;
return a;
}
forceinline word_t KEYROT(word_t lo2hi, word_t hi2lo) {
word_t r;
r.e = lo2hi.e << 16 | hi2lo.e >> 16;
r.o = lo2hi.o << 16 | hi2lo.o >> 16;
return r;
}
forceinline int NOTZERO(word_t a, word_t b) {
uint32_t result = a.e | a.o | b.e | b.o;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
forceinline word_t PAD(int i) {
return WORD_T((uint64_t)(0x8ul << (28 - 4 * i)) << 32);
}
forceinline word_t CLEAR(word_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0x0fffffff >> (n * 4 - 4);
w.e &= mask;
w.o &= mask;
return w;
}
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline word_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(U64BIG(x));
}
forceinline void STORE(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= U64BIG(x);
}
forceinline word_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
for (int i = 0; i < n; ++i) ((uint8_t*)&x)[7 - i] = bytes[i];
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
for (int i = 0; i < n; ++i) bytes[i] = ((uint8_t*)&x)[7 - i];
}
#endif /* WORD_H_ */

View File

@ -0,0 +1,219 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
#if !ASCON_INLINE_MODE
#undef forceinline
#define forceinline
#endif
forceinline void ascon_loadkey(word_t* K0, word_t* K1, word_t* K2,
const uint8_t* k) {
KINIT(K0, K1, K2);
if (CRYPTO_KEYBYTES == 16) {
*K1 = XOR(*K1, LOAD(k, 8));
*K2 = XOR(*K2, LOAD(k + 8, 8));
}
if (CRYPTO_KEYBYTES == 20) {
*K0 = XOR(*K0, KEYROT(WORD_T(0), LOADBYTES(k, 4)));
*K1 = XOR(*K1, LOADBYTES(k + 4, 8));
*K2 = XOR(*K2, LOADBYTES(k + 12, 8));
}
}
forceinline void ascon_aeadinit(state_t* s, const uint8_t* npub,
const uint8_t* k) {
/* load nonce */
word_t N0 = LOAD(npub, 8);
word_t N1 = LOAD(npub + 8, 8);
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* initialize */
PINIT(s);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8)
s->x0 = XOR(s->x0, ASCON_128_IV);
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16)
s->x0 = XOR(s->x0, ASCON_128A_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, ASCON_80PQ_IV);
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, K0);
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
s->x3 = XOR(s->x3, N0);
s->x4 = XOR(s->x4, N1);
P(s, 12);
if (CRYPTO_KEYBYTES == 20) s->x2 = XOR(s->x2, K0);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("initialization", s);
}
forceinline void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
if (adlen) {
/* full associated data blocks */
while (adlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
if (ASCON_AEAD_RATE == 16) s->x1 = XOR(s->x1, LOAD(ad + 8, 8));
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x0 = XOR(s->x0, LOAD(ad, 8));
px = &s->x1;
ad += 8;
adlen -= 8;
}
*px = XOR(*px, PAD(adlen));
if (adlen) *px = XOR(*px, LOAD(ad, adlen));
P(s, nr);
}
/* domain separation */
s->x4 = XOR(s->x4, WORD_T(1));
printstate("process associated data", s);
}
forceinline void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m,
uint64_t mlen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full plaintext blocks */
while (mlen >= ASCON_AEAD_RATE) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
if (ASCON_AEAD_RATE == 16) {
s->x1 = XOR(s->x1, LOAD(m + 8, 8));
STORE(c + 8, s->x1, 8);
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x0 = XOR(s->x0, LOAD(m, 8));
STORE(c, s->x0, 8);
px = &s->x1;
m += 8;
c += 8;
mlen -= 8;
}
*px = XOR(*px, PAD(mlen));
if (mlen) {
*px = XOR(*px, LOAD(m, mlen));
STORE(c, *px, mlen);
}
printstate("process plaintext", s);
}
forceinline void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c,
uint64_t clen) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
/* full ciphertext blocks */
while (clen >= ASCON_AEAD_RATE) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x1 = XOR(s->x1, cx);
STORE(m + 8, s->x1, 8);
s->x1 = cx;
}
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
word_t* px = &s->x0;
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
word_t cx = LOAD(c, 8);
s->x0 = XOR(s->x0, cx);
STORE(m, s->x0, 8);
s->x0 = cx;
px = &s->x1;
m += 8;
c += 8;
clen -= 8;
}
*px = XOR(*px, PAD(clen));
if (clen) {
word_t cx = LOAD(c, clen);
*px = XOR(*px, cx);
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px = XOR(*px, cx);
}
printstate("process ciphertext", s);
}
forceinline void ascon_final(state_t* s, const uint8_t* k) {
/* load key */
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* finalize */
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) {
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
}
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) {
s->x2 = XOR(s->x2, K1);
s->x3 = XOR(s->x3, K2);
}
if (CRYPTO_KEYBYTES == 20) {
s->x1 = XOR(s->x1, KEYROT(K0, K1));
s->x2 = XOR(s->x2, KEYROT(K1, K2));
s->x3 = XOR(s->x3, KEYROT(K2, WORD_T(0)));
}
P(s, 12);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("finalization", s);
}
int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
*clen = mlen + CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, k);
/* set tag */
STOREBYTES(c + mlen, s.x3, 8);
STOREBYTES(c + mlen + 8, s.x4, 8);
return 0;
}
int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen,
unsigned char* nsec, const unsigned char* c,
unsigned long long clen, const unsigned char* ad,
unsigned long long adlen, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
if (clen < CRYPTO_ABYTES) return -1;
*mlen = clen = clen - CRYPTO_ABYTES;
/* perform ascon computation */
ascon_aeadinit(&s, npub, k);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, k);
/* verify tag (should be constant time, check compiler output) */
s.x3 = XOR(s.x3, LOADBYTES(c + clen, 8));
s.x4 = XOR(s.x4, LOADBYTES(c + clen + 8, 8));
return NOTZERO(s.x3, s.x4);
}

View File

@ -0,0 +1,7 @@
#define CRYPTO_VERSION "1.2.5"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define ASCON_AEAD_RATE 16

View File

@ -0,0 +1,18 @@
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef struct {
word_t x0, x1, x2, x3, x4;
} state_t;
void ascon_aeadinit(state_t* s, const uint8_t* npub, const uint8_t* k);
void ascon_adata(state_t* s, const uint8_t* ad, uint64_t adlen);
void ascon_encrypt(state_t* s, uint8_t* c, const uint8_t* m, uint64_t mlen);
void ascon_decrypt(state_t* s, uint8_t* m, const uint8_t* c, uint64_t clen);
void ascon_final(state_t* s, const uint8_t* k);
#endif /* ASCON_H */

View File

@ -0,0 +1,19 @@
#ifndef CONFIG_H_
#define CONFIG_H_
/* inline the ascon mode */
#ifndef ASCON_INLINE_MODE
#define ASCON_INLINE_MODE 0
#endif
/* inline all permutations */
#ifndef ASCON_INLINE_PERM
#define ASCON_INLINE_PERM 1
#endif
/* unroll permutation loops */
#ifndef ASCON_UNROLL_LOOPS
#define ASCON_UNROLL_LOOPS 0
#endif
#endif /* CONFIG_H_ */

View File

@ -0,0 +1,39 @@
#ifndef ENDIAN_H_
#define ENDIAN_H_
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
/* macros for big endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for big endian machines")
#endif
#define U64BIG(x) (x)
#define U32BIG(x) (x)
#define U16BIG(x) (x)
#elif defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
/* macros for little endian machines */
#ifdef PRAGMA_ENDIAN
#pragma message("Using macros for little endian machines")
#endif
#define U64BIG(x) \
(((0x00000000000000FFULL & (x)) << 56) | \
((0x000000000000FF00ULL & (x)) << 40) | \
((0x0000000000FF0000ULL & (x)) << 24) | \
((0x00000000FF000000ULL & (x)) << 8) | \
((0x000000FF00000000ULL & (x)) >> 8) | \
((0x0000FF0000000000ULL & (x)) >> 24) | \
((0x00FF000000000000ULL & (x)) >> 40) | \
((0xFF00000000000000ULL & (x)) >> 56))
#define U32BIG(x) \
(((0x000000FF & (x)) << 24) | ((0x0000FF00 & (x)) << 8) | \
((0x00FF0000 & (x)) >> 8) | ((0xFF000000 & (x)) >> 24))
#define U16BIG(x) (((0x00FF & (x)) << 8) | ((0xFF00 & (x)) >> 8))
#else
#error "Ascon byte order macros not defined in endian.h"
#endif
#endif /* ENDIAN_H_ */

View File

@ -0,0 +1,19 @@
#ifndef FORCEINLINE_H_
#define FORCEINLINE_H_
/* define forceinline macro */
#ifdef _MSC_VER
#define forceinline __forceinline
#elif defined(__GNUC__)
#define forceinline inline __attribute__((__always_inline__))
#elif defined(__CLANG__)
#if __has_attribute(__always_inline__)
#define forceinline inline __attribute__((__always_inline__))
#else
#define forceinline inline
#endif
#else
#define forceinline inline
#endif
#endif /* FORCEINLINE_H_ */

View File

@ -0,0 +1 @@
Branches reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1 @@
Addresses reviewed 2020-11-13 by Martin Schläffer.

View File

@ -0,0 +1,2 @@
Christoph Dobraunig
Martin Schläffer

View File

@ -0,0 +1,49 @@
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "forceinline.h"
forceinline uint32_t deinterleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave_uint32(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0x0000FF00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & 0x00F000F0, x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & 0x0C0C0C0C, x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & 0x22222222, x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t r0, r1;
lo = deinterleave_uint32(lo);
hi = deinterleave_uint32(hi);
r0 = (lo & 0x0000FFFF) | (hi << 16);
r1 = (lo >> 16) | (hi & 0xFFFF0000);
return (uint64_t)r1 << 32 | r0;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t r0 = in;
uint32_t r1 = in >> 32;
uint32_t lo = (r0 & 0x0000FFFF) | (r1 << 16);
uint32_t hi = (r0 >> 16) | (r1 & 0xFFFF0000);
lo = interleave_uint32(lo);
hi = interleave_uint32(hi);
return (uint64_t)hi << 32 | lo;
}
#endif /* INTERLEAVE_H_ */

View File

@ -0,0 +1,23 @@
#include "permutations.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[][2] = {{0xc, 0xc}, {0x9, 0xc}, {0xc, 0x9}, {0x9, 0x9},
{0x6, 0xc}, {0x3, 0xc}, {0x6, 0x9}, {0x3, 0x9},
{0xc, 0x6}, {0x9, 0x6}, {0xc, 0x3}, {0x9, 0x3}};
#endif
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
void P8(state_t* s) { P8ROUNDS(s); }
void P6(state_t* s) { P6ROUNDS(s); }
#endif
#if !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
void P(state_t* s, int nr) { PROUNDS(s, nr); }
#endif

View File

@ -0,0 +1,139 @@
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "printstate.h"
#include "round.h"
#define ASCON_128_KEYBYTES 16
#define ASCON_128A_KEYBYTES 16
#define ASCON_80PQ_KEYBYTES 20
#define ASCON_128_RATE 8
#define ASCON_128A_RATE 16
#define ASCON_HASH_RATE 8
#define ASCON_128_PA_ROUNDS 12
#define ASCON_128_PB_ROUNDS 6
#define ASCON_128A_PA_ROUNDS 12
#define ASCON_128A_PB_ROUNDS 8
#define ASCON_HASH_PA_ROUNDS 12
#define ASCON_HASH_PB_ROUNDS 12
#define ASCON_HASHA_PA_ROUNDS 12
#define ASCON_HASHA_PB_ROUNDS 8
#define ASCON_HASH_BYTES 32
#define ASCON_128_IV WORD_T(0x8021000008220000ull)
#define ASCON_128A_IV WORD_T(0x8822000000200000ull)
#define ASCON_80PQ_IV WORD_T(0xc021000008220000ull)
#define ASCON_HASH_IV WORD_T(0x0020000008020010ull)
#define ASCON_XOF_IV WORD_T(0x0020000008020000ull)
#define ASCON_HASH_IV0 WORD_T(0xf9afb5c6a540dbc7ull)
#define ASCON_HASH_IV1 WORD_T(0xbd2493011445a340ull)
#define ASCON_HASH_IV2 WORD_T(0xcb9ba8b5604d4fc8ull)
#define ASCON_HASH_IV3 WORD_T(0x12a4eede94514c98ull)
#define ASCON_HASH_IV4 WORD_T(0x4bca84c06339f398ull)
#define ASCON_HASHA_IV0 WORD_T(0x0108e46d1b16eb02ull)
#define ASCON_HASHA_IV1 WORD_T(0x5b9b8efdd29083f3ull)
#define ASCON_HASHA_IV2 WORD_T(0x7ad665622891ae4aull)
#define ASCON_HASHA_IV3 WORD_T(0x9dc27156ee3bfc7full)
#define ASCON_HASHA_IV4 WORD_T(0xc61d5fa916801633ull)
#define ASCON_XOF_IV0 WORD_T(0xc75782817e351ae6ull)
#define ASCON_XOF_IV1 WORD_T(0x70045f441d238220ull)
#define ASCON_XOF_IV2 WORD_T(0x5dd5ab52a13e3f04ull)
#define ASCON_XOF_IV3 WORD_T(0x3e378142c30c1db2ull)
#define ASCON_XOF_IV4 WORD_T(0x3735189db624d656ull)
#define ASCON_XOFA_IV0 WORD_T(0x0846d7a5a4b87d44ull)
#define ASCON_XOFA_IV1 WORD_T(0xaa6f1005b3a2dbf4ull)
#define ASCON_XOFA_IV2 WORD_T(0xdc451146f713e811ull)
#define ASCON_XOFA_IV3 WORD_T(0x468cb2532839e30dull)
#define ASCON_XOFA_IV4 WORD_T(0xeb2d429709e96977ull)
#define START(n) (12 - n)
#define RC(e, o) WORD_T((uint64_t)o << 32 | e)
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC(0xc, 0xc));
ROUND(s, RC(0x9, 0xc));
ROUND(s, RC(0xc, 0x9));
ROUND(s, RC(0x9, 0x9));
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0xc));
ROUND(s, RC(0x3, 0xc));
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC(0x6, 0x9));
ROUND(s, RC(0x3, 0x9));
ROUND(s, RC(0xc, 0x6));
ROUND(s, RC(0x9, 0x6));
ROUND(s, RC(0xc, 0x3));
ROUND(s, RC(0x9, 0x3));
}
extern const uint8_t constants[][2];
forceinline void PROUNDS(state_t* s, int nr) {
for (int i = START(nr); i < 12; i++)
ROUND(s, RC(constants[i][0], constants[i][1]));
}
#if ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12ROUNDS(s);
if (nr == 8) P8ROUNDS(s);
if (nr == 6) P6ROUNDS(s);
}
#elif !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s);
void P8(state_t* s);
void P6(state_t* s);
forceinline void P(state_t* s, int nr) {
if (nr == 12) P12(s);
if (nr == 8) P8(s);
if (nr == 6) P6(s);
}
#elif ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS
forceinline void P(state_t* s, int nr) { PROUNDS(s, nr); }
#else /* !ASCON_INLINE_PERM && !ASCON_UNROLL_LOOPS */
void P(state_t* s, int nr);
#endif
#endif /* PERMUTATIONS_H_ */

View File

@ -0,0 +1,21 @@
#ifdef ASCON_PRINTSTATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
void printword(const char* text, const word_t x) {
printf("%s=%016" PRIx64 "\n", text, WORDTOU64(x));
}
void printstate(const char* text, const state_t* s) {
printf("%s:\n", text);
printword(" x0", s->x0);
printword(" x1", s->x1);
printword(" x2", s->x2);
printword(" x3", s->x3);
printword(" x4", s->x4);
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINTSTATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const word_t x);
void printstate(const char* text, const state_t* s);
#else
#define printword(text, w) \
do { \
} while (0)
#define printstate(text, s) \
do { \
} while (0)
#endif
#endif /* PRINTSTATE_H_ */

View File

@ -0,0 +1,53 @@
#ifndef ROUND_H_
#define ROUND_H_
#include "ascon.h"
#include "printstate.h"
forceinline void KINIT(word_t* K0, word_t* K1, word_t* K2) {
*K0 = WORD_T(0);
*K1 = WORD_T(0);
*K2 = WORD_T(0);
}
forceinline void PINIT(state_t* s) {
s->x0 = WORD_T(0);
s->x1 = WORD_T(0);
s->x2 = WORD_T(0);
s->x3 = WORD_T(0);
s->x4 = WORD_T(0);
}
forceinline void ROUND(state_t* s, word_t C) {
word_t xtemp;
/* round constant */
s->x2 = XOR(s->x2, C);
/* s-box layer */
s->x0 = XOR(s->x0, s->x4);
s->x4 = XOR(s->x4, s->x3);
s->x2 = XOR(s->x2, s->x1);
xtemp = AND(s->x0, NOT(s->x4));
s->x0 = XOR(s->x0, AND(s->x2, NOT(s->x1)));
s->x2 = XOR(s->x2, AND(s->x4, NOT(s->x3)));
s->x4 = XOR(s->x4, AND(s->x1, NOT(s->x0)));
s->x1 = XOR(s->x1, AND(s->x3, NOT(s->x2)));
s->x3 = XOR(s->x3, xtemp);
s->x1 = XOR(s->x1, s->x0);
s->x3 = XOR(s->x3, s->x2);
s->x0 = XOR(s->x0, s->x4);
/* linear layer */
xtemp = XOR(s->x0, ROR(s->x0, 28 - 19));
s->x0 = XOR(s->x0, ROR(xtemp, 19));
xtemp = XOR(s->x1, ROR(s->x1, 61 - 39));
s->x1 = XOR(s->x1, ROR(xtemp, 39));
xtemp = XOR(s->x2, ROR(s->x2, 6 - 1));
s->x2 = XOR(s->x2, ROR(xtemp, 1));
xtemp = XOR(s->x3, ROR(s->x3, 17 - 10));
s->x3 = XOR(s->x3, ROR(xtemp, 10));
xtemp = XOR(s->x4, ROR(s->x4, 41 - 7));
s->x4 = XOR(s->x4, ROR(xtemp, 7));
s->x2 = NOT(s->x2);
printstate(" round output", s);
}
#endif /* ROUND_H_ */

View File

@ -0,0 +1,105 @@
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
typedef struct {
uint32_t e;
uint32_t o;
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return (n == 0) ? x : x >> n | x << (32 - n);
}
forceinline word_t ROR(word_t x, int n) {
word_t r;
r.e = (n % 2) ? ROR32(x.o, (n - 1) / 2) : ROR32(x.e, n / 2);
r.o = (n % 2) ? ROR32(x.e, (n + 1) / 2) : ROR32(x.o, n / 2);
return r;
}
forceinline word_t WORD_T(uint64_t x) { return (word_t){.o = x >> 32, .e = x}; }
forceinline uint64_t UINT64_T(word_t x) { return (uint64_t)x.o << 32 | x.e; }
forceinline word_t U64TOWORD(uint64_t x) { return WORD_T(deinterleave32(x)); }
forceinline uint64_t WORDTOU64(word_t w) { return interleave32(UINT64_T(w)); }
forceinline word_t NOT(word_t a) {
a.e = ~a.e;
a.o = ~a.o;
return a;
}
forceinline word_t XOR(word_t a, word_t b) {
a.e ^= b.e;
a.o ^= b.o;
return a;
}
forceinline word_t AND(word_t a, word_t b) {
a.e &= b.e;
a.o &= b.o;
return a;
}
forceinline word_t KEYROT(word_t lo2hi, word_t hi2lo) {
word_t r;
r.e = lo2hi.e << 16 | hi2lo.e >> 16;
r.o = lo2hi.o << 16 | hi2lo.o >> 16;
return r;
}
forceinline int NOTZERO(word_t a, word_t b) {
uint32_t result = a.e | a.o | b.e | b.o;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
forceinline word_t PAD(int i) {
return WORD_T((uint64_t)(0x8ul << (28 - 4 * i)) << 32);
}
forceinline word_t CLEAR(word_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0x0fffffff >> (n * 4 - 4);
w.e &= mask;
w.o &= mask;
return w;
}
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline word_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(U64BIG(x));
}
forceinline void STORE(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= U64BIG(x);
}
forceinline word_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
for (int i = 0; i < n; ++i) ((uint8_t*)&x)[7 - i] = bytes[i];
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, word_t w, int n) {
uint64_t x = WORDTOU64(w);
for (int i = 0; i < n; ++i) bytes[i] = ((uint8_t*)&x)[7 - i];
}
#endif /* WORD_H_ */

View File

@ -0,0 +1,79 @@
#include "api.h"
#include "ascon.h"
#include "permutations.h"
#include "printstate.h"
forceinline void ascon_loadkey(word_t* K0, word_t* K1, word_t* K2,
const uint8_t* k) {
KINIT(K0, K1, K2);
if (CRYPTO_KEYBYTES == 16) {
*K1 = XOR(*K1, LOAD(k, 8));
*K2 = XOR(*K2, LOAD(k + 8, 8));
}
if (CRYPTO_KEYBYTES == 20) {
*K0 = XOR(*K0, KEYROT(WORD_T(0), LOADBYTES(k, 4)));
*K1 = XOR(*K1, LOADBYTES(k + 4, 8));
*K2 = XOR(*K2, LOADBYTES(k + 12, 8));
}
}
forceinline void ascon_aeadinit(state_t* s, const uint8_t* npub, word_t K0,
word_t K1, word_t K2) {
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) s->x0 = ASCON_128_IV;
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) s->x0 = ASCON_128A_IV;
if (CRYPTO_KEYBYTES == 20) s->x0 = ASCON_80PQ_IV;
if (CRYPTO_KEYBYTES == 20) s->x0 = XOR(s->x0, K0);
s->x1 = K1;
s->x2 = K2;
s->x3 = LOAD(npub, 8);
s->x4 = LOAD(npub + 8, 8);
P(s, 12);
if (CRYPTO_KEYBYTES == 20) s->x2 = XOR(s->x2, K0);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("initialization", s);
}
forceinline void ascon_final(state_t* s, word_t K0, word_t K1, word_t K2) {
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 8) {
s->x1 = XOR(s->x1, K1);
s->x2 = XOR(s->x2, K2);
}
if (CRYPTO_KEYBYTES == 16 && ASCON_AEAD_RATE == 16) {
s->x2 = XOR(s->x2, K1);
s->x3 = XOR(s->x3, K2);
}
if (CRYPTO_KEYBYTES == 20) {
s->x1 = XOR(s->x1, KEYROT(K0, K1));
s->x2 = XOR(s->x2, KEYROT(K1, K2));
s->x3 = XOR(s->x3, KEYROT(K2, WORD_T(0)));
}
P(s, 12);
s->x3 = XOR(s->x3, K1);
s->x4 = XOR(s->x4, K2);
printstate("finalization", s);
}
void ascon_aead(state_t* s, uint8_t* out, const uint8_t* in, uint64_t tlen,
const uint8_t* ad, uint64_t adlen, const uint8_t* npub,
const uint8_t* k, uint8_t mode) {
const int nr = (ASCON_AEAD_RATE == 8) ? 6 : 8;
word_t K0, K1, K2;
ascon_loadkey(&K0, &K1, &K2, k);
/* initialize */
ascon_aeadinit(s, npub, K0, K1, K2);
/* process associated data */
if (adlen) {
ascon_update(s, (void*)0, ad, adlen, ASCON_ABSORB);
P(s, nr);
}
/* domain separation */
s->x4 = XOR(s->x4, WORD_T(1));
printstate("process associated data", s);
/* process plaintext/ciphertext */
ascon_update(s, out, in, tlen, mode);
if (mode == ASCON_ENCRYPT) printstate("process plaintext", s);
if (mode == ASCON_DECRYPT) printstate("process ciphertext", s);
/* finalize */
ascon_final(s, K0, K1, K2);
}

View File

@ -0,0 +1,7 @@
#define CRYPTO_VERSION "1.2.5"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#define ASCON_AEAD_RATE 16

View File

@ -0,0 +1,26 @@
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef struct {
word_t x0, x1, x2, x3, x4;
} state_t;
#define ASCON_ABSORB 0x1
#define ASCON_SQUEEZE 0x2
#define ASCON_INSERT 0x4
#define ASCON_HASH 0x8
#define ASCON_ENCRYPT (ASCON_ABSORB | ASCON_SQUEEZE)
#define ASCON_DECRYPT (ASCON_ABSORB | ASCON_SQUEEZE | ASCON_INSERT)
void ascon_update(state_t* s, uint8_t* out, const uint8_t* in, uint64_t len,
uint8_t mode);
void ascon_aead(state_t* s, uint8_t* out, const uint8_t* in, uint64_t tlen,
const uint8_t* ad, uint64_t adlen, const uint8_t* npub,
const uint8_t* k, uint8_t mode);
#endif /* ASCON_H */

View File

@ -0,0 +1,19 @@
#ifndef CONFIG_H_
#define CONFIG_H_
/* inline the ascon mode */
#ifndef ASCON_INLINE_MODE
#define ASCON_INLINE_MODE 0
#endif
/* inline all permutations */
#ifndef ASCON_INLINE_PERM
#define ASCON_INLINE_PERM 0
#endif
/* unroll permutation loops */
#ifndef ASCON_UNROLL_LOOPS
#define ASCON_UNROLL_LOOPS 0
#endif
#endif /* CONFIG_H_ */

View File

@ -0,0 +1,27 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
void ascon_aead(state_t* s, uint8_t* out, const uint8_t* in, uint64_t tlen,
const uint8_t* ad, uint64_t adlen, const uint8_t* npub,
const uint8_t* k, uint8_t mode);
int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen,
unsigned char* nsec, const unsigned char* c,
unsigned long long clen, const unsigned char* ad,
unsigned long long adlen, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
if (clen < CRYPTO_ABYTES) return -1;
/* set plaintext size */
*mlen = clen - CRYPTO_ABYTES;
/* ascon decryption */
ascon_aead(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DECRYPT);
/* verify tag (should be constant time, check compiler output) */
s.x3 = XOR(s.x3, LOADBYTES(c + *mlen, 8));
s.x4 = XOR(s.x4, LOADBYTES(c + *mlen + 8, 8));
return NOTZERO(s.x3, s.x4);
}

View File

@ -0,0 +1,26 @@
#include "api.h"
#include "ascon.h"
#include "crypto_aead.h"
#include "permutations.h"
#include "printstate.h"
void ascon_aead(state_t* s, uint8_t* out, const uint8_t* in, uint64_t tlen,
const uint8_t* ad, uint64_t adlen, const uint8_t* npub,
const uint8_t* k, uint8_t mode);
int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen,
const unsigned char* m, unsigned long long mlen,
const unsigned char* ad, unsigned long long adlen,
const unsigned char* nsec, const unsigned char* npub,
const unsigned char* k) {
state_t s;
(void)nsec;
/* set ciphertext size */
*clen = mlen + CRYPTO_ABYTES;
/* ascon encryption */
ascon_aead(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENCRYPT);
/* set tag */
STOREBYTES(c + mlen, s.x3, 8);
STOREBYTES(c + mlen + 8, s.x4, 8);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More