adds initial version of lwc
This commit is contained in:
parent
bccfc67926
commit
6c48a29db1
36
lwc/Makefile
Normal file
36
lwc/Makefile
Normal 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
110
lwc/src/Makefile
Normal 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
39
lwc/src/ascon/Makefile.in
Normal 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
|
||||
|
||||
# =============================================================================
|
18
lwc/src/ascon/arch/rv32/ise.h
Normal file
18
lwc/src/ascon/arch/rv32/ise.h
Normal 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
|
||||
|
||||
// ============================================================================
|
15
lwc/src/ascon/arch/rv64/ise.h
Normal file
15
lwc/src/ascon/arch/rv64/ise.h
Normal 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
|
||||
|
||||
// ============================================================================
|
35
lwc/src/ascon/fpga-scan.py
Normal file
35
lwc/src/ascon/fpga-scan.py
Normal 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 )
|
||||
|
||||
# =============================================================================
|
272
lwc/src/ascon/imp/rv32/ascon_imp.S
Normal file
272
lwc/src/ascon/imp/rv32/ascon_imp.S
Normal 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
|
||||
|
158
lwc/src/ascon/imp/rv64/ascon_imp.S
Normal file
158
lwc/src/ascon/imp/rv64/ascon_imp.S
Normal 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
1
lwc/src/ascon/nist.url
Normal 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
3
lwc/src/ascon/nist.zip
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:07a2bc8432612d260cef0945e6a16ff9aa94c9279a2e83b76ae984fdbe8b1a5d
|
||||
size 2032754
|
3
lwc/src/ascon/nist/Documents/asconv12.pdf
Normal file
3
lwc/src/ascon/nist/Documents/asconv12.pdf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:49403e24b9cd05a234d27c5a7f37e3f28de52c8f8db07ac744515be225bd7aa6
|
||||
size 485542
|
3
lwc/src/ascon/nist/Documents/changelog.pdf
Normal file
3
lwc/src/ascon/nist/Documents/changelog.pdf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:68eb5de5bbe2c1d19a212827f9daaec22b49777e93f4fed6300764bbbd5aa480
|
||||
size 153824
|
3
lwc/src/ascon/nist/Documents/coversheet.pdf
Normal file
3
lwc/src/ascon/nist/Documents/coversheet.pdf
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ffbefd2edd8d997de9157c2bf6ea6bfaa53e03e8ce26f1ee136108ae924b127e
|
||||
size 164033
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
@ -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
|
@ -0,0 +1,2 @@
|
||||
amd64
|
||||
x86
|
@ -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 */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1 @@
|
||||
Branches reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1 @@
|
||||
Addresses reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1,2 @@
|
||||
Christoph Dobraunig
|
||||
Martin Schläffer
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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
|
@ -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 */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1 @@
|
||||
Branches reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1 @@
|
||||
Addresses reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1,2 @@
|
||||
Christoph Dobraunig
|
||||
Martin Schläffer
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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
|
@ -0,0 +1,3 @@
|
||||
aarch64
|
||||
armeabi
|
||||
arm
|
@ -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 */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1 @@
|
||||
Branches reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1 @@
|
||||
Addresses reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1,2 @@
|
||||
Christoph Dobraunig
|
||||
Martin Schläffer
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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
|
@ -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 */
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1 @@
|
||||
Branches reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1 @@
|
||||
Addresses reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1,2 @@
|
||||
Christoph Dobraunig
|
||||
Martin Schläffer
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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
|
@ -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 */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1 @@
|
||||
Branches reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1 @@
|
||||
Addresses reviewed 2020-11-13 by Martin Schläffer.
|
@ -0,0 +1,2 @@
|
||||
Christoph Dobraunig
|
||||
Martin Schläffer
|
@ -0,0 +1,42 @@
|
||||
#include "interleave.h"
|
||||
|
||||
static inline 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;
|
||||
}
|
||||
|
||||
static inline 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 */
|
||||
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 */
|
||||
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;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#ifndef INTERLEAVE_H_
|
||||
#define INTERLEAVE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "forceinline.h"
|
||||
|
||||
uint64_t deinterleave32(uint64_t in);
|
||||
uint64_t interleave32(uint64_t in);
|
||||
|
||||
#endif /* INTERLEAVE_H_ */
|
@ -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
|
@ -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_ */
|
@ -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
|
@ -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_ */
|
@ -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_ */
|
@ -0,0 +1,44 @@
|
||||
#include "api.h"
|
||||
#include "ascon.h"
|
||||
#include "permutations.h"
|
||||
#include "printstate.h"
|
||||
|
||||
void ascon_update(state_t* s, uint8_t* out, const uint8_t* in, uint64_t len,
|
||||
uint8_t mode) {
|
||||
const int rate = 16;
|
||||
const int nr = 8;
|
||||
word_t tmp0, tmp1;
|
||||
int n = 0, n0 = 0, n1 = 0;
|
||||
while (len) {
|
||||
/* determine block size */
|
||||
n0 = len < 8 ? len : 8;
|
||||
n1 = len < 8 ? 0 : (len < 16 ? len - 8 : 8);
|
||||
n = n0 + n1;
|
||||
/* absorb data */
|
||||
tmp0 = LOAD(in, n0);
|
||||
s->x0 = XOR(s->x0, tmp0);
|
||||
if (n1) tmp1 = LOAD(in + 8, n1);
|
||||
if (n1) s->x1 = XOR(s->x1, tmp1);
|
||||
/* extract data */
|
||||
if (mode & ASCON_SQUEEZE) {
|
||||
STORE(out, s->x0, n0);
|
||||
if (n1) STORE(out + 8, s->x1, n1);
|
||||
}
|
||||
/* insert data */
|
||||
if (mode & ASCON_INSERT) {
|
||||
s->x0 = CLEAR(s->x0, n0);
|
||||
s->x0 = XOR(s->x0, tmp0);
|
||||
if (n1) s->x1 = CLEAR(s->x1, n1);
|
||||
if (n1) s->x1 = XOR(s->x1, tmp1);
|
||||
}
|
||||
/* compute permutation for full blocks */
|
||||
if (n == rate) P(s, nr);
|
||||
in += n;
|
||||
out += n;
|
||||
len -= n;
|
||||
}
|
||||
if (n % rate < 8)
|
||||
s->x0 = XOR(s->x0, PAD(n0 % 8));
|
||||
else
|
||||
s->x1 = XOR(s->x1, PAD(n1 % 8));
|
||||
}
|
@ -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_ */
|
@ -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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user