Commit 1640476b by Martin Schläffer Committed by Sebastian Renner

latest ascon release

parent 2f8aa5e2

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
- Regex: '^<.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
...
cmake_minimum_required(VERSION 3.9)
project(ascon LANGUAGES C ASM)
enable_testing()
# set the default version, algorithms, implementations, tests, flags, defs
set(DEFAULT_VERSIONS v12)
set(DEFAULT_ALGS ascon128 ascon128a ascon80pq asconhash asconhasha
asconxof asconxofa asconprf asconmac asconprfs ascon ascona)
# default to all C implementations:
set(DEFAULT_IMPLS ref opt64 opt64_lowsize opt32 opt32_lowsize bi32 bi32_lowsize bi32_lowreg esp32 opt8 bi8)
# tests: genkat, getcycles
set(DEFAULT_TESTS genkat)
set(DEFAULT_COMPILE_DEFS)
set(DEFAULT_EMULATOR)
if(MSVC)
set(DEFAULT_REL_FLAGS /O2)
set(DEFAULT_DBG_FLAGS /Od)
else()
set(DEFAULT_REL_FLAGS -std=c99 -O2 -fomit-frame-pointer -march=native -mtune=native)
set(DEFAULT_DBG_FLAGS -std=c99 -O2 -Wall -Wextra -Wshadow)
endif()
# set cmake variables for version, algorithms, implementations, tests, flags, defs
set(VERSION_LIST ${DEFAULT_VERSIONS} CACHE STRING "Choose the ascon versions to include.")
set(ALG_LIST ${DEFAULT_ALGS} CACHE STRING "Choose the list of algorithms to include.")
set(IMPL_LIST ${DEFAULT_IMPLS} CACHE STRING "Choose the list of implementations to include.")
set(TEST_LIST ${DEFAULT_TESTS} CACHE STRING "Choose the list of tests to include.")
set(REL_FLAGS ${DEFAULT_REL_FLAGS} CACHE STRING "Define custom Release (performance) flags.")
set(DBG_FLAGS ${DEFAULT_DBG_FLAGS} CACHE STRING "Define custom Debug (NIST) flags.")
set(COMPILE_DEFS ${DEFAULT_COMPILE_DEFS} CACHE STRING "Define custom compile definitions.")
set(EMULATOR ${DEFAULT_EMULATOR} CACHE STRING "Define custom emulator command.")
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0" AND NOT WIN32 AND NOT CYGWIN AND NOT MSYS)
# use sanitizer in Debug build (not on windows and only of target_link_option is available)
set(DBG_FLAGS ${DBG_FLAGS} -fsanitize=address,undefined)
endif()
# set the default build type for single-config generators if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
endif()
# add platform specific implementations
message(STATUS "cmake host system name: ${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "cmake host system processor: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
set(KAT_PATH KAT)
set(TEST_PATH tests)
foreach(CRYPTO aead hash auth)
foreach(VER ${VERSION_LIST})
foreach(ALG ${ALG_LIST})
foreach(IMPL ${IMPL_LIST})
set(IMPL_PATH crypto_${CRYPTO}/${ALG}${VER}/${IMPL})
if((NOT ${CRYPTO} STREQUAL auth) AND
NOT EXISTS ${CMAKE_SOURCE_DIR}/${IMPL_PATH})
set(IMPL_PATH crypto_aead_hash/${ALG}${VER}/${IMPL})
endif()
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/${IMPL_PATH})
continue()
endif()
message("Adding implementation ${IMPL_PATH}")
set(IMPL_NAME crypto_${CRYPTO}_${ALG}${VER}_${IMPL})
file(GLOB IMPL_FILES RELATIVE ${CMAKE_SOURCE_DIR} "${IMPL_PATH}/*.[ch]")
if(${IMPL} MATCHES protected.*)
set(IMPL_FILES ${IMPL_FILES} ${TEST_PATH}/randombytes.h)
endif()
add_library(${IMPL_NAME} ${IMPL_FILES})
target_include_directories(${IMPL_NAME} PUBLIC ${IMPL_PATH} ${TEST_PATH})
target_compile_definitions(${IMPL_NAME} PRIVATE ${COMPILE_DEFS})
#target_compile_features(${IMPL_NAME} PUBLIC c_std_99) # cmake >= 3.8.2
target_compile_options(${IMPL_NAME} PUBLIC $<$<CONFIG:RELEASE>:${REL_FLAGS}>)
target_compile_options(${IMPL_NAME} PUBLIC $<$<CONFIG:DEBUG>:${DBG_FLAGS}>)
foreach(TEST_NAME ${TEST_LIST})
if(${TEST_NAME} STREQUAL genkat)
set(TEST_FILES ${TEST_PATH}/crypto_${CRYPTO}.h ${TEST_PATH}/genkat_${CRYPTO}.c)
else()
set(TEST_FILES ${TEST_PATH}/crypto_${CRYPTO}.h ${TEST_PATH}/getcycles.c)
endif()
string(TOUPPER CRYPTO_${CRYPTO} DEFINE_CRYPTO)
if(${IMPL} MATCHES protected.*)
set(DEFINE_CRYPTO ${DEFINE_CRYPTO}_SHARED)
endif()
if(${ALG} STREQUAL asconprfs)
set(DEFINE_MAXMSGLEN "MAX_DATA_LENGTH=16")
else()
set(DEFINE_MAXMSGLEN "MAX_DATA_LENGTH=1024")
endif()
set(EXE_NAME ${TEST_NAME}_${IMPL_NAME})
add_executable(${EXE_NAME} ${TEST_FILES})
target_compile_definitions(${EXE_NAME} PRIVATE ${DEFINE_CRYPTO} ${DEFINE_MAXMSGLEN})
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
target_link_options(${EXE_NAME} PRIVATE $<$<CONFIG:DEBUG>:${DBG_FLAGS}>)
endif()
target_link_libraries(${EXE_NAME} PRIVATE ${IMPL_NAME})
string(REPLACE ";" " " EMULATOR_STRING "${EMULATOR}")
if(${TEST_NAME} STREQUAL genkat)
add_test(NAME ${EXE_NAME} COMMAND ${CMAKE_COMMAND}
-DEXE_NAME=${EXE_NAME} -DALG=${ALG}${VER} -DCRYPTO=${CRYPTO}
-DSRC_DIR=${CMAKE_SOURCE_DIR} -DBIN_DIR=${CMAKE_BINARY_DIR}
-DEMULATOR=${EMULATOR_STRING} -DCONFIG=$<CONFIGURATION>
-P ${CMAKE_SOURCE_DIR}/genkat.cmake)
else()
add_test(${EXE_NAME} ${EXE_NAME})
endif()
endforeach()
endforeach()
endforeach()
endforeach()
endforeach()
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CRYPTO_VERSION "1.2.6"
#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
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef union {
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
typedef struct {
#if (CRYPTO_KEYBYTES == 20)
uint64_t k0;
#endif
uint64_t k1;
uint64_t k2;
} key_t;
void ascon_initaead(state_t* s, const uint8_t* npub, const key_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 key_t* k);
void ascon_inithash(state_t* s);
void ascon_absorb(state_t* s, const uint8_t* in, uint64_t inlen);
void ascon_squeeze(state_t* s, uint8_t* out, uint64_t outlen);
#endif /* ASCON_H_ */
#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
/* inline bitinterleaving */
#ifndef ASCON_INLINE_BI
#define ASCON_INLINE_BI 1
#endif
/* extern bitinterleaving */
#ifndef ASCON_EXTERN_BI
#define ASCON_EXTERN_BI 1
#endif
#endif /* CONFIG_H_ */
#include "constants.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[] = {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
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#include <stdint.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_PRF_IN_RATE 32
#define ASCON_PRF_OUT_RATE 16
#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_PRF_PA_ROUNDS 12
#define ASCON_PRF_PB_ROUNDS 12
#define ASCON_128_IV 0x8021000008220000ull
#define ASCON_128A_IV 0x8822000000200000ull
#define ASCON_80PQ_IV 0xc021000008220000ull
#define ASCON_HASH_IV 0x0020000008200010ull
#define ASCON_HASHA_IV 0x0020000008220010ull
#define ASCON_XOF_IV 0x0020000008200000ull
#define ASCON_XOFA_IV 0x0020000008220000ull
#define ASCON_PRF_IV 0x88a0000000200000ull
#define ASCON_MAC_IV 0x88a0000800200000ull
#define ASCON_PRFS_IV 0x8028000000a00000ull
#define ASCON_HASH_IV0 0xf9afb5c6a540dbc7ull
#define ASCON_HASH_IV1 0xbd2493011445a340ull
#define ASCON_HASH_IV2 0xcb9ba8b5604d4fc8ull
#define ASCON_HASH_IV3 0x12a4eede94514c98ull
#define ASCON_HASH_IV4 0x4bca84c06339f398ull
#define ASCON_HASHA_IV0 0x0108e46d1b16eb02ull
#define ASCON_HASHA_IV1 0x5b9b8efdd29083f3ull
#define ASCON_HASHA_IV2 0x7ad665622891ae4aull
#define ASCON_HASHA_IV3 0x9dc27156ee3bfc7full
#define ASCON_HASHA_IV4 0xc61d5fa916801633ull
#define ASCON_XOF_IV0 0xc75782817e351ae6ull
#define ASCON_XOF_IV1 0x70045f441d238220ull
#define ASCON_XOF_IV2 0x5dd5ab52a13e3f04ull
#define ASCON_XOF_IV3 0x3e378142c30c1db2ull
#define ASCON_XOF_IV4 0x3735189db624d656ull
#define ASCON_XOFA_IV0 0x0846d7a5a4b87d44ull
#define ASCON_XOFA_IV1 0xaa6f1005b3a2dbf4ull
#define ASCON_XOFA_IV2 0xdc451146f713e811ull
#define ASCON_XOFA_IV3 0x468cb2532839e30dull
#define ASCON_XOFA_IV4 0xeb2d429709e96977ull
#define RC0 0x0000000c0000000cull
#define RC1 0x0000000c00000009ull
#define RC2 0x000000090000000cull
#define RC3 0x0000000900000009ull
#define RC4 0x0000000c00000006ull
#define RC5 0x0000000c00000003ull
#define RC6 0x0000000900000006ull
#define RC7 0x0000000900000003ull
#define RC8 0x000000060000000cull
#define RC9 0x0000000600000009ull
#define RCa 0x000000030000000cull
#define RCb 0x0000000300000009ull
#define RC(i) ((uint64_t)constants[i + 1] << 32 | constants[i])
#define START(n) (24 - 2 * (n))
#define INC 2
#define END 24
extern const uint8_t constants[];
#endif /* CONSTANTS_H_ */
#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
#ifdef ASCON_AEAD_RATE
forceinline void ascon_loadkey(key_t* key, const uint8_t* k) {
#if CRYPTO_KEYBYTES == 16
key->k1 = LOAD(k, 8);
key->k2 = LOAD(k + 8, 8);
#else /* CRYPTO_KEYBYTES == 20 */
key->k0 = KEYROT(0, LOADBYTES(k, 4));
key->k1 = LOADBYTES(k + 4, 8);
key->k2 = LOADBYTES(k + 12, 8);
#endif
}
forceinline void ascon_initaead(state_t* s, const uint8_t* npub,
const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV;
if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV;
#else /* CRYPTO_KEYBYTES == 20 */
s->x[0] = ASCON_80PQ_IV ^ key->k0;
#endif
s->x[1] = key->k1;
s->x[2] = key->k2;
s->x[3] = LOAD(npub, 8);
s->x[4] = LOAD(npub + 8, 8);
printstate("init 1st key xor", s);
P(s, 12);
#if CRYPTO_KEYBYTES == 20
s->x[2] ^= key->k0;
#endif
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("init 2nd key xor", 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->x[0] ^= LOAD(ad, 8);
if (ASCON_AEAD_RATE == 16) s->x[1] ^= LOAD(ad + 8, 8);
printstate("absorb adata", s);
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x[0] ^= LOAD(ad, 8);
px = &s->x[1];
ad += 8;
adlen -= 8;
}
*px ^= PAD(adlen);
if (adlen) *px ^= LOAD(ad, adlen);
printstate("pad adata", s);
P(s, nr);
}
/* domain separation */
s->x[4] ^= 1;
printstate("domain separation", 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->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
if (ASCON_AEAD_RATE == 16) {
s->x[1] ^= LOAD(m + 8, 8);
STORE(c + 8, s->x[1], 8);
}
printstate("absorb plaintext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
px = &s->x[1];
m += 8;
c += 8;
mlen -= 8;
}
*px ^= PAD(mlen);
if (mlen) {
*px ^= LOAD(m, mlen);
STORE(c, *px, mlen);
}
printstate("pad 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) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x[1] ^= cx;
STORE(m + 8, s->x[1], 8);
s->x[1] = cx;
}
printstate("insert ciphertext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
px = &s->x[1];
m += 8;
c += 8;
clen -= 8;
}
*px ^= PAD(clen);
if (clen) {
uint64_t cx = LOAD(c, clen);
*px ^= cx;
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px ^= cx;
}
printstate("pad ciphertext", s);
}
forceinline void ascon_final(state_t* s, const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) {
s->x[1] ^= key->k1;
s->x[2] ^= key->k2;
} else {
s->x[2] ^= key->k1;
s->x[3] ^= key->k2;
}
#else /* CRYPTO_KEYBYTES == 20 */
s->x[1] ^= KEYROT(key->k0, key->k1);
s->x[2] ^= KEYROT(key->k1, key->k2);
s->x[3] ^= KEYROT(key->k2, 0);
#endif
printstate("final 1st key xor", s);
P(s, 12);
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("final 2nd key xor", 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, &key);
/* set tag */
STOREBYTES(c + mlen, s.x[3], 8);
STOREBYTES(c + mlen + 8, s.x[4], 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, &key);
/* verify tag (should be constant time, check compiler output) */
s.x[3] ^= LOADBYTES(c + clen, 8);
s.x[4] ^= LOADBYTES(c + clen + 8, 8);
return NOTZERO(s.x[3], s.x[4]);
}
#endif
#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_ */
#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_ */
Branches reviewed 2020-11-13 by Martin Schläffer.
Addresses reviewed 2020-11-13 by Martin Schläffer.
#include "interleave.h"
#if !ASCON_EXTERN_BI
const uint32_t B[3] = {0x22222222, 0x0c0c0c0c, 0x00f000f0};
#if !ASCON_INLINE_BI
uint64_t TOBI(uint64_t in) { return deinterleave32(in); }
uint64_t FROMBI(uint64_t in) { return interleave32(in); }
#endif
#endif
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#if ASCON_INLINE_BI
#define TOBI deinterleave32
#define FROMBI interleave32
#else
uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);
#endif
extern const uint32_t B[3];
forceinline uint32_t deinterleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
in = U64BIG(in);
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t t0, t1, e, o;
t0 = deinterleave16(lo);
t1 = deinterleave16(hi);
e = (t1 << 16) | (t0 & 0x0000FFFF);
o = (t1 & 0xFFFF0000) | (t0 >> 16);
return (uint64_t)o << 32 | e;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t e = in;
uint32_t o = in >> 32;
uint32_t t0, t1, lo, hi;
t0 = (o << 16) | (e & 0x0000FFFF);
t1 = (o & 0xFFFF0000) | (e >> 16);
lo = interleave16(t0);
hi = interleave16(t1);
return U64BIG((uint64_t)hi << 32 | lo);
}
#endif /* INTERLEAVE_H_ */
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
#endif
#if ((defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 16) || \
(defined(ASCON_HASH_ROUNDS) && ASCON_HASH_ROUNDS == 8)) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P8(state_t* s) { P8ROUNDS(s); }
#endif
#if (defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 8) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "constants.h"
#include "printstate.h"
#include "round.h"
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC0);
ROUND(s, RC1);
ROUND(s, RC2);
ROUND(s, RC3);
ROUND(s, RC4);
ROUND(s, RC5);
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC4);
ROUND(s, RC5);
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
#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_ */
#ifdef ASCON_PRINT_STATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#ifndef WORDTOU64
#define WORDTOU64
#endif
#ifndef U64BIG
#define U64BIG
#endif
void printword(const char* text, const uint64_t x) {
printf("%s=%016" PRIx64, text, U64BIG(WORDTOU64(x)));
}
void printstate(const char* text, const state_t* s) {
printf("%s:", text);
for (int i = strlen(text); i < 17; ++i) printf(" ");
printword(" x0", s->x[0]);
printword(" x1", s->x[1]);
printword(" x2", s->x[2]);
printword(" x3", s->x[3]);
printword(" x4", s->x[4]);
#ifdef ASCON_PRINT_BI
printf(" ");
printf(" x0=%08x_%08x", s->w[0][1], s->w[0][0]);
printf(" x1=%08x_%08x", s->w[1][1], s->w[1][0]);
printf(" x2=%08x_%08x", s->w[2][1], s->w[2][0]);
printf(" x3=%08x_%08x", s->w[3][1], s->w[3][0]);
printf(" x4=%08x_%08x", s->w[4][1], s->w[4][0]);
#endif
printf("\n");
}
#endif
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINT_STATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const uint64_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_ */
#ifndef ROUND_H_
#define ROUND_H_
#include "ascon.h"
#include "printstate.h"
forceinline void ROUND(state_t* s, uint64_t C) {
state_t t;
/* round constant */
s->x[2] ^= C;
/* s-box layer */
s->x[0] ^= s->x[4];
s->x[4] ^= s->x[3];
s->x[2] ^= s->x[1];
t.x[0] = s->x[0] ^ (~s->x[1] & s->x[2]);
t.x[2] = s->x[2] ^ (~s->x[3] & s->x[4]);
t.x[4] = s->x[4] ^ (~s->x[0] & s->x[1]);
t.x[1] = s->x[1] ^ (~s->x[2] & s->x[3]);
t.x[3] = s->x[3] ^ (~s->x[4] & s->x[0]);
t.x[1] ^= t.x[0];
t.x[3] ^= t.x[2];
t.x[0] ^= t.x[4];
/* linear layer */
s->x[2] = t.x[2] ^ ROR(t.x[2], 6 - 1);
s->x[3] = t.x[3] ^ ROR(t.x[3], 17 - 10);
s->x[4] = t.x[4] ^ ROR(t.x[4], 41 - 7);
s->x[0] = t.x[0] ^ ROR(t.x[0], 28 - 19);
s->x[1] = t.x[1] ^ ROR(t.x[1], 61 - 39);
s->x[2] = t.x[2] ^ ROR(s->x[2], 1);
s->x[3] = t.x[3] ^ ROR(s->x[3], 10);
s->x[4] = t.x[4] ^ ROR(s->x[4], 7);
s->x[0] = t.x[0] ^ ROR(s->x[0], 19);
s->x[1] = t.x[1] ^ ROR(s->x[1], 39);
s->x[2] = ~s->x[2];
printstate(" round output", s);
}
forceinline void PROUNDS(state_t* s, int nr) {
int i = START(nr);
do {
ROUND(s, RC(i));
i += INC;
} while (i != END);
}
#endif /* ROUND_H_ */
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
#if ASCON_EXTERN_BI
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
#else
#define U64TOWORD(x) TOBI(x)
#define WORDTOU64(x) FROMBI(x)
#endif
typedef union {
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return x >> n | x << (-n & 31);
}
forceinline uint64_t ROR(uint64_t x, int n) {
word_t b, a = {.x = x};
b.w[0] = (n % 2) ? ROR32(a.w[1], (n - 1) / 2) : ROR32(a.w[0], n / 2);
b.w[1] = (n % 2) ? ROR32(a.w[0], (n + 1) / 2) : ROR32(a.w[1], n / 2);
return b.x;
}
forceinline uint64_t KEYROT(uint64_t a, uint64_t b) {
word_t w, lo2hi = {.x = a}, hi2lo = {.x = b};
w.w[0] = lo2hi.w[0] << 16 | hi2lo.w[0] >> 16;
w.w[1] = lo2hi.w[1] << 16 | hi2lo.w[1] >> 16;
return w.x;
}
forceinline int NOTZERO(uint64_t a, uint64_t b) {
uint64_t result = a | b;
result |= result >> 32;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
#if ASCON_EXTERN_BI
forceinline uint64_t PAD(int i) { return 0x80ull << (56 - 8 * i); }
forceinline uint64_t PRFS_MLEN(uint64_t len) { return len << 51; }
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint64_t mask = ~0ull >> (8 * n);
return w & mask;
}
#else
forceinline uint64_t PAD(int i) {
return ((uint64_t)((uint32_t)0x08 << (28 - 4 * i)) << 32);
}
forceinline uint64_t PRFS_MLEN(uint64_t len) {
return ((len & 0x01) << 57) | /* 0000x */
((len & 0x02) << 25) | /* 000x0 */
((len & 0x04) << 56) | /* 00x00 */
((len & 0x08) << 24) | /* 0x000 */
((len & 0x10) << 55); /* x0000 */
}
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0xffffffffull >> (4 * n);
return w & ((uint64_t)mask << 32 | mask);
}
#endif
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline uint64_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(x);
}
forceinline void STORE(uint8_t* bytes, uint64_t w, int n) {
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= WORDTOU64(w);
}
forceinline uint64_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
memcpy(&x, bytes, n);
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, uint64_t w, int n) {
uint64_t x = WORDTOU64(w);
memcpy(bytes, &x, n);
}
#endif /* WORD_H_ */
#define CRYPTO_VERSION "1.2.6"
#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
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef union {
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
typedef struct {
#if (CRYPTO_KEYBYTES == 20)
uint64_t k0;
#endif
uint64_t k1;
uint64_t k2;
} key_t;
void ascon_initaead(state_t* s, const uint8_t* npub, const key_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 key_t* k);
void ascon_inithash(state_t* s);
void ascon_absorb(state_t* s, const uint8_t* in, uint64_t inlen);
void ascon_squeeze(state_t* s, uint8_t* out, uint64_t outlen);
#endif /* ASCON_H_ */
#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
/* inline bitinterleaving */
#ifndef ASCON_INLINE_BI
#define ASCON_INLINE_BI 1
#endif
/* extern bitinterleaving */
#ifndef ASCON_EXTERN_BI
#define ASCON_EXTERN_BI 1
#endif
#endif /* CONFIG_H_ */
#include "constants.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[] = {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
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#include <stdint.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_PRF_IN_RATE 32
#define ASCON_PRF_OUT_RATE 16
#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_PRF_PA_ROUNDS 12
#define ASCON_PRF_PB_ROUNDS 12
#define ASCON_128_IV 0x8021000008220000ull
#define ASCON_128A_IV 0x8822000000200000ull
#define ASCON_80PQ_IV 0xc021000008220000ull
#define ASCON_HASH_IV 0x0020000008200010ull
#define ASCON_HASHA_IV 0x0020000008220010ull
#define ASCON_XOF_IV 0x0020000008200000ull
#define ASCON_XOFA_IV 0x0020000008220000ull
#define ASCON_PRF_IV 0x88a0000000200000ull
#define ASCON_MAC_IV 0x88a0000800200000ull
#define ASCON_PRFS_IV 0x8028000000a00000ull
#define ASCON_HASH_IV0 0xf9afb5c6a540dbc7ull
#define ASCON_HASH_IV1 0xbd2493011445a340ull
#define ASCON_HASH_IV2 0xcb9ba8b5604d4fc8ull
#define ASCON_HASH_IV3 0x12a4eede94514c98ull
#define ASCON_HASH_IV4 0x4bca84c06339f398ull
#define ASCON_HASHA_IV0 0x0108e46d1b16eb02ull
#define ASCON_HASHA_IV1 0x5b9b8efdd29083f3ull
#define ASCON_HASHA_IV2 0x7ad665622891ae4aull
#define ASCON_HASHA_IV3 0x9dc27156ee3bfc7full
#define ASCON_HASHA_IV4 0xc61d5fa916801633ull
#define ASCON_XOF_IV0 0xc75782817e351ae6ull
#define ASCON_XOF_IV1 0x70045f441d238220ull
#define ASCON_XOF_IV2 0x5dd5ab52a13e3f04ull
#define ASCON_XOF_IV3 0x3e378142c30c1db2ull
#define ASCON_XOF_IV4 0x3735189db624d656ull
#define ASCON_XOFA_IV0 0x0846d7a5a4b87d44ull
#define ASCON_XOFA_IV1 0xaa6f1005b3a2dbf4ull
#define ASCON_XOFA_IV2 0xdc451146f713e811ull
#define ASCON_XOFA_IV3 0x468cb2532839e30dull
#define ASCON_XOFA_IV4 0xeb2d429709e96977ull
#define RC0 0x0000000c0000000cull
#define RC1 0x0000000c00000009ull
#define RC2 0x000000090000000cull
#define RC3 0x0000000900000009ull
#define RC4 0x0000000c00000006ull
#define RC5 0x0000000c00000003ull
#define RC6 0x0000000900000006ull
#define RC7 0x0000000900000003ull
#define RC8 0x000000060000000cull
#define RC9 0x0000000600000009ull
#define RCa 0x000000030000000cull
#define RCb 0x0000000300000009ull
#define RC(i) ((uint64_t)constants[i + 1] << 32 | constants[i])
#define START(n) (24 - 2 * (n))
#define INC 2
#define END 24
extern const uint8_t constants[];
#endif /* CONSTANTS_H_ */
#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
#ifdef ASCON_AEAD_RATE
forceinline void ascon_loadkey(key_t* key, const uint8_t* k) {
#if CRYPTO_KEYBYTES == 16
key->k1 = LOAD(k, 8);
key->k2 = LOAD(k + 8, 8);
#else /* CRYPTO_KEYBYTES == 20 */
key->k0 = KEYROT(0, LOADBYTES(k, 4));
key->k1 = LOADBYTES(k + 4, 8);
key->k2 = LOADBYTES(k + 12, 8);
#endif
}
forceinline void ascon_initaead(state_t* s, const uint8_t* npub,
const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV;
if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV;
#else /* CRYPTO_KEYBYTES == 20 */
s->x[0] = ASCON_80PQ_IV ^ key->k0;
#endif
s->x[1] = key->k1;
s->x[2] = key->k2;
s->x[3] = LOAD(npub, 8);
s->x[4] = LOAD(npub + 8, 8);
printstate("init 1st key xor", s);
P(s, 12);
#if CRYPTO_KEYBYTES == 20
s->x[2] ^= key->k0;
#endif
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("init 2nd key xor", 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->x[0] ^= LOAD(ad, 8);
if (ASCON_AEAD_RATE == 16) s->x[1] ^= LOAD(ad + 8, 8);
printstate("absorb adata", s);
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x[0] ^= LOAD(ad, 8);
px = &s->x[1];
ad += 8;
adlen -= 8;
}
*px ^= PAD(adlen);
if (adlen) *px ^= LOAD(ad, adlen);
printstate("pad adata", s);
P(s, nr);
}
/* domain separation */
s->x[4] ^= 1;
printstate("domain separation", 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->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
if (ASCON_AEAD_RATE == 16) {
s->x[1] ^= LOAD(m + 8, 8);
STORE(c + 8, s->x[1], 8);
}
printstate("absorb plaintext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
px = &s->x[1];
m += 8;
c += 8;
mlen -= 8;
}
*px ^= PAD(mlen);
if (mlen) {
*px ^= LOAD(m, mlen);
STORE(c, *px, mlen);
}
printstate("pad 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) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x[1] ^= cx;
STORE(m + 8, s->x[1], 8);
s->x[1] = cx;
}
printstate("insert ciphertext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
px = &s->x[1];
m += 8;
c += 8;
clen -= 8;
}
*px ^= PAD(clen);
if (clen) {
uint64_t cx = LOAD(c, clen);
*px ^= cx;
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px ^= cx;
}
printstate("pad ciphertext", s);
}
forceinline void ascon_final(state_t* s, const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) {
s->x[1] ^= key->k1;
s->x[2] ^= key->k2;
} else {
s->x[2] ^= key->k1;
s->x[3] ^= key->k2;
}
#else /* CRYPTO_KEYBYTES == 20 */
s->x[1] ^= KEYROT(key->k0, key->k1);
s->x[2] ^= KEYROT(key->k1, key->k2);
s->x[3] ^= KEYROT(key->k2, 0);
#endif
printstate("final 1st key xor", s);
P(s, 12);
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("final 2nd key xor", 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, &key);
/* set tag */
STOREBYTES(c + mlen, s.x[3], 8);
STOREBYTES(c + mlen + 8, s.x[4], 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, &key);
/* verify tag (should be constant time, check compiler output) */
s.x[3] ^= LOADBYTES(c + clen, 8);
s.x[4] ^= LOADBYTES(c + clen + 8, 8);
return NOTZERO(s.x[3], s.x[4]);
}
#endif
#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_ */
#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_ */
#include "interleave.h"
#if !ASCON_EXTERN_BI
const uint32_t B[3] = {0x22222222, 0x0c0c0c0c, 0x00f000f0};
#if !ASCON_INLINE_BI
uint64_t TOBI(uint64_t in) { return deinterleave32(in); }
uint64_t FROMBI(uint64_t in) { return interleave32(in); }
#endif
#endif
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#if ASCON_INLINE_BI
#define TOBI deinterleave32
#define FROMBI interleave32
#else
uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);
#endif
extern const uint32_t B[3];
forceinline uint32_t deinterleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
in = U64BIG(in);
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t t0, t1, e, o;
t0 = deinterleave16(lo);
t1 = deinterleave16(hi);
e = (t1 << 16) | (t0 & 0x0000FFFF);
o = (t1 & 0xFFFF0000) | (t0 >> 16);
return (uint64_t)o << 32 | e;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t e = in;
uint32_t o = in >> 32;
uint32_t t0, t1, lo, hi;
t0 = (o << 16) | (e & 0x0000FFFF);
t1 = (o & 0xFFFF0000) | (e >> 16);
lo = interleave16(t0);
hi = interleave16(t1);
return U64BIG((uint64_t)hi << 32 | lo);
}
#endif /* INTERLEAVE_H_ */
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
#endif
#if ((defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 16) || \
(defined(ASCON_HASH_ROUNDS) && ASCON_HASH_ROUNDS == 8)) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P8(state_t* s) { P8ROUNDS(s); }
#endif
#if (defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 8) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "constants.h"
#include "printstate.h"
#include "round.h"
#define LOADSTATE(s, a, b, c, d, e) \
do { \
a.x = s->x[0]; \
b.x = s->x[1]; \
c.x = s->x[2]; \
d.x = s->x[3]; \
e.x = s->x[4]; \
} while (0)
#define STORESTATE(s, a, b, c, d, e) \
do { \
s->x[0] = a.x; \
s->x[1] = b.x; \
s->x[2] = c.x; \
s->x[3] = d.x; \
s->x[4] = e.x; \
} while (0)
forceinline void P12ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC0);
ROUND5(x2, x3, x4, x0, x1, RC1);
ROUND5(x4, x0, x1, x2, x3, RC2);
ROUND5(x1, x2, x3, x4, x0, RC3);
ROUND5(x3, x4, x0, x1, x2, RC4);
ROUND5(x0, x1, x2, x3, x4, RC5);
ROUND5(x2, x3, x4, x0, x1, RC6);
ROUND5(x4, x0, x1, x2, x3, RC7);
ROUND5(x1, x2, x3, x4, x0, RC8);
ROUND5(x3, x4, x0, x1, x2, RC9);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCa);
ROUND5(x2, x3, x4, x0, x1, RCb);
STORESTATE(s, x4, x0, x1, x2, x3);
#else
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P8ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC4);
ROUND5(x2, x3, x4, x0, x1, RC5);
ROUND5(x4, x0, x1, x2, x3, RC6);
ROUND5(x1, x2, x3, x4, x0, RC7);
ROUND5(x3, x4, x0, x1, x2, RC8);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RC9);
ROUND5(x2, x3, x4, x0, x1, RCa);
ROUND5(x4, x0, x1, x2, x3, RCb);
STORESTATE(s, x1, x2, x3, x4, x0);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P6ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC6);
ROUND5(x2, x3, x4, x0, x1, RC7);
ROUND5(x4, x0, x1, x2, x3, RC8);
ROUND5(x1, x2, x3, x4, x0, RC9);
ROUND5(x3, x4, x0, x1, x2, RCa);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCb);
STORESTATE(s, x2, x3, x4, x0, x1);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCb);
#endif
}
#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_ */
#ifdef ASCON_PRINT_STATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#ifndef WORDTOU64
#define WORDTOU64
#endif
#ifndef U64BIG
#define U64BIG
#endif
void printword(const char* text, const uint64_t x) {
printf("%s=%016" PRIx64, text, U64BIG(WORDTOU64(x)));
}
void printstate(const char* text, const state_t* s) {
printf("%s:", text);
for (int i = strlen(text); i < 17; ++i) printf(" ");
printword(" x0", s->x[0]);
printword(" x1", s->x[1]);
printword(" x2", s->x[2]);
printword(" x3", s->x[3]);
printword(" x4", s->x[4]);
#ifdef ASCON_PRINT_BI
printf(" ");
printf(" x0=%08x_%08x", s->w[0][1], s->w[0][0]);
printf(" x1=%08x_%08x", s->w[1][1], s->w[1][0]);
printf(" x2=%08x_%08x", s->w[2][1], s->w[2][0]);
printf(" x3=%08x_%08x", s->w[3][1], s->w[3][0]);
printf(" x4=%08x_%08x", s->w[4][1], s->w[4][0]);
#endif
printf("\n");
}
#endif
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINT_STATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const uint64_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_ */
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
#if ASCON_EXTERN_BI
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
#else
#define U64TOWORD(x) TOBI(x)
#define WORDTOU64(x) FROMBI(x)
#endif
typedef union {
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return x >> n | x << (-n & 31);
}
forceinline uint64_t ROR(uint64_t x, int n) {
word_t b, a = {.x = x};
b.w[0] = (n % 2) ? ROR32(a.w[1], (n - 1) / 2) : ROR32(a.w[0], n / 2);
b.w[1] = (n % 2) ? ROR32(a.w[0], (n + 1) / 2) : ROR32(a.w[1], n / 2);
return b.x;
}
forceinline uint64_t KEYROT(uint64_t a, uint64_t b) {
word_t w, lo2hi = {.x = a}, hi2lo = {.x = b};
w.w[0] = lo2hi.w[0] << 16 | hi2lo.w[0] >> 16;
w.w[1] = lo2hi.w[1] << 16 | hi2lo.w[1] >> 16;
return w.x;
}
forceinline int NOTZERO(uint64_t a, uint64_t b) {
uint64_t result = a | b;
result |= result >> 32;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
#if ASCON_EXTERN_BI
forceinline uint64_t PAD(int i) { return 0x80ull << (56 - 8 * i); }
forceinline uint64_t PRFS_MLEN(uint64_t len) { return len << 51; }
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint64_t mask = ~0ull >> (8 * n);
return w & mask;
}
#else
forceinline uint64_t PAD(int i) {
return ((uint64_t)((uint32_t)0x08 << (28 - 4 * i)) << 32);
}
forceinline uint64_t PRFS_MLEN(uint64_t len) {
return ((len & 0x01) << 57) | /* 0000x */
((len & 0x02) << 25) | /* 000x0 */
((len & 0x04) << 56) | /* 00x00 */
((len & 0x08) << 24) | /* 0x000 */
((len & 0x10) << 55); /* x0000 */
}
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0xffffffffull >> (4 * n);
return w & ((uint64_t)mask << 32 | mask);
}
#endif
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline uint64_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(x);
}
forceinline void STORE(uint8_t* bytes, uint64_t w, int n) {
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= WORDTOU64(w);
}
forceinline uint64_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
memcpy(&x, bytes, n);
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, uint64_t w, int n) {
uint64_t x = WORDTOU64(w);
memcpy(bytes, &x, n);
}
#endif /* WORD_H_ */
#define CRYPTO_VERSION "1.2.6"
#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
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef union {
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
typedef struct {
#if (CRYPTO_KEYBYTES == 20)
uint64_t k0;
#endif
uint64_t k1;
uint64_t k2;
} key_t;
void ascon_initaead(state_t* s, const uint8_t* npub, const key_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 key_t* k);
void ascon_inithash(state_t* s);
void ascon_absorb(state_t* s, const uint8_t* in, uint64_t inlen);
void ascon_squeeze(state_t* s, uint8_t* out, uint64_t outlen);
#endif /* ASCON_H_ */
#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 0
#endif
/* inline bitinterleaving */
#ifndef ASCON_INLINE_BI
#define ASCON_INLINE_BI 1
#endif
/* extern bitinterleaving */
#ifndef ASCON_EXTERN_BI
#define ASCON_EXTERN_BI 1
#endif
#endif /* CONFIG_H_ */
#include "constants.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[] = {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
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#include <stdint.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_PRF_IN_RATE 32
#define ASCON_PRF_OUT_RATE 16
#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_PRF_PA_ROUNDS 12
#define ASCON_PRF_PB_ROUNDS 12
#define ASCON_128_IV 0x8021000008220000ull
#define ASCON_128A_IV 0x8822000000200000ull
#define ASCON_80PQ_IV 0xc021000008220000ull
#define ASCON_HASH_IV 0x0020000008200010ull
#define ASCON_HASHA_IV 0x0020000008220010ull
#define ASCON_XOF_IV 0x0020000008200000ull
#define ASCON_XOFA_IV 0x0020000008220000ull
#define ASCON_PRF_IV 0x88a0000000200000ull
#define ASCON_MAC_IV 0x88a0000800200000ull
#define ASCON_PRFS_IV 0x8028000000a00000ull
#define ASCON_HASH_IV0 0xf9afb5c6a540dbc7ull
#define ASCON_HASH_IV1 0xbd2493011445a340ull
#define ASCON_HASH_IV2 0xcb9ba8b5604d4fc8ull
#define ASCON_HASH_IV3 0x12a4eede94514c98ull
#define ASCON_HASH_IV4 0x4bca84c06339f398ull
#define ASCON_HASHA_IV0 0x0108e46d1b16eb02ull
#define ASCON_HASHA_IV1 0x5b9b8efdd29083f3ull
#define ASCON_HASHA_IV2 0x7ad665622891ae4aull
#define ASCON_HASHA_IV3 0x9dc27156ee3bfc7full
#define ASCON_HASHA_IV4 0xc61d5fa916801633ull
#define ASCON_XOF_IV0 0xc75782817e351ae6ull
#define ASCON_XOF_IV1 0x70045f441d238220ull
#define ASCON_XOF_IV2 0x5dd5ab52a13e3f04ull
#define ASCON_XOF_IV3 0x3e378142c30c1db2ull
#define ASCON_XOF_IV4 0x3735189db624d656ull
#define ASCON_XOFA_IV0 0x0846d7a5a4b87d44ull
#define ASCON_XOFA_IV1 0xaa6f1005b3a2dbf4ull
#define ASCON_XOFA_IV2 0xdc451146f713e811ull
#define ASCON_XOFA_IV3 0x468cb2532839e30dull
#define ASCON_XOFA_IV4 0xeb2d429709e96977ull
#define RC0 0x0000000c0000000cull
#define RC1 0x0000000c00000009ull
#define RC2 0x000000090000000cull
#define RC3 0x0000000900000009ull
#define RC4 0x0000000c00000006ull
#define RC5 0x0000000c00000003ull
#define RC6 0x0000000900000006ull
#define RC7 0x0000000900000003ull
#define RC8 0x000000060000000cull
#define RC9 0x0000000600000009ull
#define RCa 0x000000030000000cull
#define RCb 0x0000000300000009ull
#define RC(i) ((uint64_t)constants[i + 1] << 32 | constants[i])
#define START(n) (24 - 2 * (n))
#define INC 2
#define END 24
extern const uint8_t constants[];
#endif /* CONSTANTS_H_ */
#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
#ifdef ASCON_AEAD_RATE
forceinline void ascon_loadkey(key_t* key, const uint8_t* k) {
#if CRYPTO_KEYBYTES == 16
key->k1 = LOAD(k, 8);
key->k2 = LOAD(k + 8, 8);
#else /* CRYPTO_KEYBYTES == 20 */
key->k0 = KEYROT(0, LOADBYTES(k, 4));
key->k1 = LOADBYTES(k + 4, 8);
key->k2 = LOADBYTES(k + 12, 8);
#endif
}
forceinline void ascon_initaead(state_t* s, const uint8_t* npub,
const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV;
if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV;
#else /* CRYPTO_KEYBYTES == 20 */
s->x[0] = ASCON_80PQ_IV ^ key->k0;
#endif
s->x[1] = key->k1;
s->x[2] = key->k2;
s->x[3] = LOAD(npub, 8);
s->x[4] = LOAD(npub + 8, 8);
printstate("init 1st key xor", s);
P(s, 12);
#if CRYPTO_KEYBYTES == 20
s->x[2] ^= key->k0;
#endif
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("init 2nd key xor", 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->x[0] ^= LOAD(ad, 8);
if (ASCON_AEAD_RATE == 16) s->x[1] ^= LOAD(ad + 8, 8);
printstate("absorb adata", s);
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x[0] ^= LOAD(ad, 8);
px = &s->x[1];
ad += 8;
adlen -= 8;
}
*px ^= PAD(adlen);
if (adlen) *px ^= LOAD(ad, adlen);
printstate("pad adata", s);
P(s, nr);
}
/* domain separation */
s->x[4] ^= 1;
printstate("domain separation", 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->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
if (ASCON_AEAD_RATE == 16) {
s->x[1] ^= LOAD(m + 8, 8);
STORE(c + 8, s->x[1], 8);
}
printstate("absorb plaintext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
px = &s->x[1];
m += 8;
c += 8;
mlen -= 8;
}
*px ^= PAD(mlen);
if (mlen) {
*px ^= LOAD(m, mlen);
STORE(c, *px, mlen);
}
printstate("pad 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) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x[1] ^= cx;
STORE(m + 8, s->x[1], 8);
s->x[1] = cx;
}
printstate("insert ciphertext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
px = &s->x[1];
m += 8;
c += 8;
clen -= 8;
}
*px ^= PAD(clen);
if (clen) {
uint64_t cx = LOAD(c, clen);
*px ^= cx;
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px ^= cx;
}
printstate("pad ciphertext", s);
}
forceinline void ascon_final(state_t* s, const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) {
s->x[1] ^= key->k1;
s->x[2] ^= key->k2;
} else {
s->x[2] ^= key->k1;
s->x[3] ^= key->k2;
}
#else /* CRYPTO_KEYBYTES == 20 */
s->x[1] ^= KEYROT(key->k0, key->k1);
s->x[2] ^= KEYROT(key->k1, key->k2);
s->x[3] ^= KEYROT(key->k2, 0);
#endif
printstate("final 1st key xor", s);
P(s, 12);
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("final 2nd key xor", 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, &key);
/* set tag */
STOREBYTES(c + mlen, s.x[3], 8);
STOREBYTES(c + mlen + 8, s.x[4], 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, &key);
/* verify tag (should be constant time, check compiler output) */
s.x[3] ^= LOADBYTES(c + clen, 8);
s.x[4] ^= LOADBYTES(c + clen + 8, 8);
return NOTZERO(s.x[3], s.x[4]);
}
#endif
#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_ */
#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_ */
#include "interleave.h"
#if !ASCON_EXTERN_BI
const uint32_t B[3] = {0x22222222, 0x0c0c0c0c, 0x00f000f0};
#if !ASCON_INLINE_BI
uint64_t TOBI(uint64_t in) { return deinterleave32(in); }
uint64_t FROMBI(uint64_t in) { return interleave32(in); }
#endif
#endif
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#if ASCON_INLINE_BI
#define TOBI deinterleave32
#define FROMBI interleave32
#else
uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);
#endif
extern const uint32_t B[3];
forceinline uint32_t deinterleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
in = U64BIG(in);
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t t0, t1, e, o;
t0 = deinterleave16(lo);
t1 = deinterleave16(hi);
e = (t1 << 16) | (t0 & 0x0000FFFF);
o = (t1 & 0xFFFF0000) | (t0 >> 16);
return (uint64_t)o << 32 | e;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t e = in;
uint32_t o = in >> 32;
uint32_t t0, t1, lo, hi;
t0 = (o << 16) | (e & 0x0000FFFF);
t1 = (o & 0xFFFF0000) | (e >> 16);
lo = interleave16(t0);
hi = interleave16(t1);
return U64BIG((uint64_t)hi << 32 | lo);
}
#endif /* INTERLEAVE_H_ */
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
#endif
#if ((defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 16) || \
(defined(ASCON_HASH_ROUNDS) && ASCON_HASH_ROUNDS == 8)) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P8(state_t* s) { P8ROUNDS(s); }
#endif
#if (defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 8) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "constants.h"
#include "printstate.h"
#include "round.h"
forceinline void P12ROUNDS(state_t* s) {
ROUND(s, RC0);
ROUND(s, RC1);
ROUND(s, RC2);
ROUND(s, RC3);
ROUND(s, RC4);
ROUND(s, RC5);
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
forceinline void P8ROUNDS(state_t* s) {
ROUND(s, RC4);
ROUND(s, RC5);
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
forceinline void P6ROUNDS(state_t* s) {
ROUND(s, RC6);
ROUND(s, RC7);
ROUND(s, RC8);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
}
#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_ */
#ifdef ASCON_PRINT_STATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#ifndef WORDTOU64
#define WORDTOU64
#endif
#ifndef U64BIG
#define U64BIG
#endif
void printword(const char* text, const uint64_t x) {
printf("%s=%016" PRIx64, text, U64BIG(WORDTOU64(x)));
}
void printstate(const char* text, const state_t* s) {
printf("%s:", text);
for (int i = strlen(text); i < 17; ++i) printf(" ");
printword(" x0", s->x[0]);
printword(" x1", s->x[1]);
printword(" x2", s->x[2]);
printword(" x3", s->x[3]);
printword(" x4", s->x[4]);
#ifdef ASCON_PRINT_BI
printf(" ");
printf(" x0=%08x_%08x", s->w[0][1], s->w[0][0]);
printf(" x1=%08x_%08x", s->w[1][1], s->w[1][0]);
printf(" x2=%08x_%08x", s->w[2][1], s->w[2][0]);
printf(" x3=%08x_%08x", s->w[3][1], s->w[3][0]);
printf(" x4=%08x_%08x", s->w[4][1], s->w[4][0]);
#endif
printf("\n");
}
#endif
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINT_STATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const uint64_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_ */
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
#if ASCON_EXTERN_BI
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
#else
#define U64TOWORD(x) TOBI(x)
#define WORDTOU64(x) FROMBI(x)
#endif
typedef union {
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return x >> n | x << (-n & 31);
}
forceinline uint64_t ROR(uint64_t x, int n) {
word_t b, a = {.x = x};
b.w[0] = (n % 2) ? ROR32(a.w[1], (n - 1) / 2) : ROR32(a.w[0], n / 2);
b.w[1] = (n % 2) ? ROR32(a.w[0], (n + 1) / 2) : ROR32(a.w[1], n / 2);
return b.x;
}
forceinline uint64_t KEYROT(uint64_t a, uint64_t b) {
word_t w, lo2hi = {.x = a}, hi2lo = {.x = b};
w.w[0] = lo2hi.w[0] << 16 | hi2lo.w[0] >> 16;
w.w[1] = lo2hi.w[1] << 16 | hi2lo.w[1] >> 16;
return w.x;
}
forceinline int NOTZERO(uint64_t a, uint64_t b) {
uint64_t result = a | b;
result |= result >> 32;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
#if ASCON_EXTERN_BI
forceinline uint64_t PAD(int i) { return 0x80ull << (56 - 8 * i); }
forceinline uint64_t PRFS_MLEN(uint64_t len) { return len << 51; }
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint64_t mask = ~0ull >> (8 * n);
return w & mask;
}
#else
forceinline uint64_t PAD(int i) {
return ((uint64_t)((uint32_t)0x08 << (28 - 4 * i)) << 32);
}
forceinline uint64_t PRFS_MLEN(uint64_t len) {
return ((len & 0x01) << 57) | /* 0000x */
((len & 0x02) << 25) | /* 000x0 */
((len & 0x04) << 56) | /* 00x00 */
((len & 0x08) << 24) | /* 0x000 */
((len & 0x10) << 55); /* x0000 */
}
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0xffffffffull >> (4 * n);
return w & ((uint64_t)mask << 32 | mask);
}
#endif
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline uint64_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(x);
}
forceinline void STORE(uint8_t* bytes, uint64_t w, int n) {
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= WORDTOU64(w);
}
forceinline uint64_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
memcpy(&x, bytes, n);
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, uint64_t w, int n) {
uint64_t x = WORDTOU64(w);
memcpy(bytes, &x, n);
}
#endif /* WORD_H_ */
#define CRYPTO_VERSION "1.2.6"
#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
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef union {
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
typedef struct {
#if (CRYPTO_KEYBYTES == 20)
uint64_t k0;
#endif
uint64_t k1;
uint64_t k2;
} key_t;
void ascon_initaead(state_t* s, const uint8_t* npub, const key_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 key_t* k);
void ascon_inithash(state_t* s);
void ascon_absorb(state_t* s, const uint8_t* in, uint64_t inlen);
void ascon_squeeze(state_t* s, uint8_t* out, uint64_t outlen);
#endif /* ASCON_H_ */
#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
/* inline bitinterleaving */
#ifndef ASCON_INLINE_BI
#define ASCON_INLINE_BI 1
#endif
/* extern bitinterleaving */
#ifndef ASCON_EXTERN_BI
#define ASCON_EXTERN_BI 1
#endif
#endif /* CONFIG_H_ */
#include "constants.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[] = {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
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#include <stdint.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_PRF_IN_RATE 32
#define ASCON_PRF_OUT_RATE 16
#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_PRF_PA_ROUNDS 12
#define ASCON_PRF_PB_ROUNDS 12
#define ASCON_128_IV 0x8021000008220000ull
#define ASCON_128A_IV 0x8822000000200000ull
#define ASCON_80PQ_IV 0xc021000008220000ull
#define ASCON_HASH_IV 0x0020000008200010ull
#define ASCON_HASHA_IV 0x0020000008220010ull
#define ASCON_XOF_IV 0x0020000008200000ull
#define ASCON_XOFA_IV 0x0020000008220000ull
#define ASCON_PRF_IV 0x88a0000000200000ull
#define ASCON_MAC_IV 0x88a0000800200000ull
#define ASCON_PRFS_IV 0x8028000000a00000ull
#define ASCON_HASH_IV0 0xf9afb5c6a540dbc7ull
#define ASCON_HASH_IV1 0xbd2493011445a340ull
#define ASCON_HASH_IV2 0xcb9ba8b5604d4fc8ull
#define ASCON_HASH_IV3 0x12a4eede94514c98ull
#define ASCON_HASH_IV4 0x4bca84c06339f398ull
#define ASCON_HASHA_IV0 0x0108e46d1b16eb02ull
#define ASCON_HASHA_IV1 0x5b9b8efdd29083f3ull
#define ASCON_HASHA_IV2 0x7ad665622891ae4aull
#define ASCON_HASHA_IV3 0x9dc27156ee3bfc7full
#define ASCON_HASHA_IV4 0xc61d5fa916801633ull
#define ASCON_XOF_IV0 0xc75782817e351ae6ull
#define ASCON_XOF_IV1 0x70045f441d238220ull
#define ASCON_XOF_IV2 0x5dd5ab52a13e3f04ull
#define ASCON_XOF_IV3 0x3e378142c30c1db2ull
#define ASCON_XOF_IV4 0x3735189db624d656ull
#define ASCON_XOFA_IV0 0x0846d7a5a4b87d44ull
#define ASCON_XOFA_IV1 0xaa6f1005b3a2dbf4ull
#define ASCON_XOFA_IV2 0xdc451146f713e811ull
#define ASCON_XOFA_IV3 0x468cb2532839e30dull
#define ASCON_XOFA_IV4 0xeb2d429709e96977ull
#define RC0 0x0000000c0000000cull
#define RC1 0x0000000c00000009ull
#define RC2 0x000000090000000cull
#define RC3 0x0000000900000009ull
#define RC4 0x0000000c00000006ull
#define RC5 0x0000000c00000003ull
#define RC6 0x0000000900000006ull
#define RC7 0x0000000900000003ull
#define RC8 0x000000060000000cull
#define RC9 0x0000000600000009ull
#define RCa 0x000000030000000cull
#define RCb 0x0000000300000009ull
#define RC(i) ((uint64_t)constants[i + 1] << 32 | constants[i])
#define START(n) (24 - 2 * (n))
#define INC 2
#define END 24
extern const uint8_t constants[];
#endif /* CONSTANTS_H_ */
#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
#ifdef ASCON_AEAD_RATE
forceinline void ascon_loadkey(key_t* key, const uint8_t* k) {
#if CRYPTO_KEYBYTES == 16
key->k1 = LOAD(k, 8);
key->k2 = LOAD(k + 8, 8);
#else /* CRYPTO_KEYBYTES == 20 */
key->k0 = KEYROT(0, LOADBYTES(k, 4));
key->k1 = LOADBYTES(k + 4, 8);
key->k2 = LOADBYTES(k + 12, 8);
#endif
}
forceinline void ascon_initaead(state_t* s, const uint8_t* npub,
const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV;
if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV;
#else /* CRYPTO_KEYBYTES == 20 */
s->x[0] = ASCON_80PQ_IV ^ key->k0;
#endif
s->x[1] = key->k1;
s->x[2] = key->k2;
s->x[3] = LOAD(npub, 8);
s->x[4] = LOAD(npub + 8, 8);
printstate("init 1st key xor", s);
P(s, 12);
#if CRYPTO_KEYBYTES == 20
s->x[2] ^= key->k0;
#endif
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("init 2nd key xor", 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->x[0] ^= LOAD(ad, 8);
if (ASCON_AEAD_RATE == 16) s->x[1] ^= LOAD(ad + 8, 8);
printstate("absorb adata", s);
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x[0] ^= LOAD(ad, 8);
px = &s->x[1];
ad += 8;
adlen -= 8;
}
*px ^= PAD(adlen);
if (adlen) *px ^= LOAD(ad, adlen);
printstate("pad adata", s);
P(s, nr);
}
/* domain separation */
s->x[4] ^= 1;
printstate("domain separation", 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->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
if (ASCON_AEAD_RATE == 16) {
s->x[1] ^= LOAD(m + 8, 8);
STORE(c + 8, s->x[1], 8);
}
printstate("absorb plaintext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
px = &s->x[1];
m += 8;
c += 8;
mlen -= 8;
}
*px ^= PAD(mlen);
if (mlen) {
*px ^= LOAD(m, mlen);
STORE(c, *px, mlen);
}
printstate("pad 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) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x[1] ^= cx;
STORE(m + 8, s->x[1], 8);
s->x[1] = cx;
}
printstate("insert ciphertext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
px = &s->x[1];
m += 8;
c += 8;
clen -= 8;
}
*px ^= PAD(clen);
if (clen) {
uint64_t cx = LOAD(c, clen);
*px ^= cx;
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px ^= cx;
}
printstate("pad ciphertext", s);
}
forceinline void ascon_final(state_t* s, const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) {
s->x[1] ^= key->k1;
s->x[2] ^= key->k2;
} else {
s->x[2] ^= key->k1;
s->x[3] ^= key->k2;
}
#else /* CRYPTO_KEYBYTES == 20 */
s->x[1] ^= KEYROT(key->k0, key->k1);
s->x[2] ^= KEYROT(key->k1, key->k2);
s->x[3] ^= KEYROT(key->k2, 0);
#endif
printstate("final 1st key xor", s);
P(s, 12);
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("final 2nd key xor", 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, &key);
/* set tag */
STOREBYTES(c + mlen, s.x[3], 8);
STOREBYTES(c + mlen + 8, s.x[4], 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, &key);
/* verify tag (should be constant time, check compiler output) */
s.x[3] ^= LOADBYTES(c + clen, 8);
s.x[4] ^= LOADBYTES(c + clen + 8, 8);
return NOTZERO(s.x[3], s.x[4]);
}
#endif
#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_ */
#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_ */
#include "interleave.h"
#if !ASCON_EXTERN_BI
const uint32_t B[3] = {0x22222222, 0x0c0c0c0c, 0x00f000f0};
#if !ASCON_INLINE_BI
uint64_t TOBI(uint64_t in) { return deinterleave32(in); }
uint64_t FROMBI(uint64_t in) { return interleave32(in); }
#endif
#endif
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#if ASCON_INLINE_BI
#define TOBI deinterleave32
#define FROMBI interleave32
#else
uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);
#endif
extern const uint32_t B[3];
forceinline uint32_t deinterleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
in = U64BIG(in);
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t t0, t1, e, o;
t0 = deinterleave16(lo);
t1 = deinterleave16(hi);
e = (t1 << 16) | (t0 & 0x0000FFFF);
o = (t1 & 0xFFFF0000) | (t0 >> 16);
return (uint64_t)o << 32 | e;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t e = in;
uint32_t o = in >> 32;
uint32_t t0, t1, lo, hi;
t0 = (o << 16) | (e & 0x0000FFFF);
t1 = (o & 0xFFFF0000) | (e >> 16);
lo = interleave16(t0);
hi = interleave16(t1);
return U64BIG((uint64_t)hi << 32 | lo);
}
#endif /* INTERLEAVE_H_ */
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
#endif
#if ((defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 16) || \
(defined(ASCON_HASH_ROUNDS) && ASCON_HASH_ROUNDS == 8)) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P8(state_t* s) { P8ROUNDS(s); }
#endif
#if (defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 8) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "constants.h"
#include "printstate.h"
#include "round.h"
#define LOADSTATE(s, a, b, c, d, e) \
do { \
a.x = s->x[0]; \
b.x = s->x[1]; \
c.x = s->x[2]; \
d.x = s->x[3]; \
e.x = s->x[4]; \
} while (0)
#define STORESTATE(s, a, b, c, d, e) \
do { \
s->x[0] = a.x; \
s->x[1] = b.x; \
s->x[2] = c.x; \
s->x[3] = d.x; \
s->x[4] = e.x; \
} while (0)
forceinline void P12ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC0);
ROUND5(x2, x3, x4, x0, x1, RC1);
ROUND5(x4, x0, x1, x2, x3, RC2);
ROUND5(x1, x2, x3, x4, x0, RC3);
ROUND5(x3, x4, x0, x1, x2, RC4);
ROUND5(x0, x1, x2, x3, x4, RC5);
ROUND5(x2, x3, x4, x0, x1, RC6);
ROUND5(x4, x0, x1, x2, x3, RC7);
ROUND5(x1, x2, x3, x4, x0, RC8);
ROUND5(x3, x4, x0, x1, x2, RC9);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCa);
ROUND5(x2, x3, x4, x0, x1, RCb);
STORESTATE(s, x4, x0, x1, x2, x3);
#else
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P8ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC4);
ROUND5(x2, x3, x4, x0, x1, RC5);
ROUND5(x4, x0, x1, x2, x3, RC6);
ROUND5(x1, x2, x3, x4, x0, RC7);
ROUND5(x3, x4, x0, x1, x2, RC8);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RC9);
ROUND5(x2, x3, x4, x0, x1, RCa);
ROUND5(x4, x0, x1, x2, x3, RCb);
STORESTATE(s, x1, x2, x3, x4, x0);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P6ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC6);
ROUND5(x2, x3, x4, x0, x1, RC7);
ROUND5(x4, x0, x1, x2, x3, RC8);
ROUND5(x1, x2, x3, x4, x0, RC9);
ROUND5(x3, x4, x0, x1, x2, RCa);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCb);
STORESTATE(s, x2, x3, x4, x0, x1);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCb);
#endif
}
#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_ */
#ifdef ASCON_PRINT_STATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#ifndef WORDTOU64
#define WORDTOU64
#endif
#ifndef U64BIG
#define U64BIG
#endif
void printword(const char* text, const uint64_t x) {
printf("%s=%016" PRIx64, text, U64BIG(WORDTOU64(x)));
}
void printstate(const char* text, const state_t* s) {
printf("%s:", text);
for (int i = strlen(text); i < 17; ++i) printf(" ");
printword(" x0", s->x[0]);
printword(" x1", s->x[1]);
printword(" x2", s->x[2]);
printword(" x3", s->x[3]);
printword(" x4", s->x[4]);
#ifdef ASCON_PRINT_BI
printf(" ");
printf(" x0=%08x_%08x", s->w[0][1], s->w[0][0]);
printf(" x1=%08x_%08x", s->w[1][1], s->w[1][0]);
printf(" x2=%08x_%08x", s->w[2][1], s->w[2][0]);
printf(" x3=%08x_%08x", s->w[3][1], s->w[3][0]);
printf(" x4=%08x_%08x", s->w[4][1], s->w[4][0]);
#endif
printf("\n");
}
#endif
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINT_STATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const uint64_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_ */
#ifndef WORD_H_
#define WORD_H_
#include <stdint.h>
#include <string.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#include "interleave.h"
#if ASCON_EXTERN_BI
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
#else
#define U64TOWORD(x) TOBI(x)
#define WORDTOU64(x) FROMBI(x)
#endif
typedef union {
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} word_t;
forceinline uint32_t ROR32(uint32_t x, int n) {
return x >> n | x << (-n & 31);
}
forceinline uint64_t ROR(uint64_t x, int n) {
word_t b, a = {.x = x};
b.w[0] = (n % 2) ? ROR32(a.w[1], (n - 1) / 2) : ROR32(a.w[0], n / 2);
b.w[1] = (n % 2) ? ROR32(a.w[0], (n + 1) / 2) : ROR32(a.w[1], n / 2);
return b.x;
}
forceinline uint64_t KEYROT(uint64_t a, uint64_t b) {
word_t w, lo2hi = {.x = a}, hi2lo = {.x = b};
w.w[0] = lo2hi.w[0] << 16 | hi2lo.w[0] >> 16;
w.w[1] = lo2hi.w[1] << 16 | hi2lo.w[1] >> 16;
return w.x;
}
forceinline int NOTZERO(uint64_t a, uint64_t b) {
uint64_t result = a | b;
result |= result >> 32;
result |= result >> 16;
result |= result >> 8;
return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1;
}
#if ASCON_EXTERN_BI
forceinline uint64_t PAD(int i) { return 0x80ull << (56 - 8 * i); }
forceinline uint64_t PRFS_MLEN(uint64_t len) { return len << 51; }
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint64_t mask = ~0ull >> (8 * n);
return w & mask;
}
#else
forceinline uint64_t PAD(int i) {
return ((uint64_t)((uint32_t)0x08 << (28 - 4 * i)) << 32);
}
forceinline uint64_t PRFS_MLEN(uint64_t len) {
return ((len & 0x01) << 57) | /* 0000x */
((len & 0x02) << 25) | /* 000x0 */
((len & 0x04) << 56) | /* 00x00 */
((len & 0x08) << 24) | /* 0x000 */
((len & 0x10) << 55); /* x0000 */
}
forceinline uint64_t CLEAR(uint64_t w, int n) {
/* undefined for n == 0 */
uint32_t mask = 0xffffffffull >> (4 * n);
return w & ((uint64_t)mask << 32 | mask);
}
#endif
forceinline uint64_t MASK(int n) {
/* undefined for n == 0 */
return ~0ull >> (64 - 8 * n);
}
forceinline uint64_t LOAD(const uint8_t* bytes, int n) {
uint64_t x = *(uint64_t*)bytes & MASK(n);
return U64TOWORD(x);
}
forceinline void STORE(uint8_t* bytes, uint64_t w, int n) {
*(uint64_t*)bytes &= ~MASK(n);
*(uint64_t*)bytes |= WORDTOU64(w);
}
forceinline uint64_t LOADBYTES(const uint8_t* bytes, int n) {
uint64_t x = 0;
memcpy(&x, bytes, n);
return U64TOWORD(x);
}
forceinline void STOREBYTES(uint8_t* bytes, uint64_t w, int n) {
uint64_t x = WORDTOU64(w);
memcpy(bytes, &x, n);
}
#endif /* WORD_H_ */
#define CRYPTO_VERSION "1.2.6"
#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
#ifndef ASCON_H_
#define ASCON_H_
#include <stdint.h>
#include "word.h"
typedef union {
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
typedef struct {
#if (CRYPTO_KEYBYTES == 20)
uint64_t k0;
#endif
uint64_t k1;
uint64_t k2;
} key_t;
void ascon_initaead(state_t* s, const uint8_t* npub, const key_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 key_t* k);
void ascon_inithash(state_t* s);
void ascon_absorb(state_t* s, const uint8_t* in, uint64_t inlen);
void ascon_squeeze(state_t* s, uint8_t* out, uint64_t outlen);
#endif /* ASCON_H_ */
#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 0
#endif
/* inline bitinterleaving */
#ifndef ASCON_INLINE_BI
#define ASCON_INLINE_BI 0
#endif
/* extern bitinterleaving */
#ifndef ASCON_EXTERN_BI
#define ASCON_EXTERN_BI 1
#endif
#endif /* CONFIG_H_ */
#include "constants.h"
#if !ASCON_UNROLL_LOOPS
const uint8_t constants[] = {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
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#include <stdint.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_PRF_IN_RATE 32
#define ASCON_PRF_OUT_RATE 16
#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_PRF_PA_ROUNDS 12
#define ASCON_PRF_PB_ROUNDS 12
#define ASCON_128_IV 0x8021000008220000ull
#define ASCON_128A_IV 0x8822000000200000ull
#define ASCON_80PQ_IV 0xc021000008220000ull
#define ASCON_HASH_IV 0x0020000008200010ull
#define ASCON_HASHA_IV 0x0020000008220010ull
#define ASCON_XOF_IV 0x0020000008200000ull
#define ASCON_XOFA_IV 0x0020000008220000ull
#define ASCON_PRF_IV 0x88a0000000200000ull
#define ASCON_MAC_IV 0x88a0000800200000ull
#define ASCON_PRFS_IV 0x8028000000a00000ull
#define ASCON_HASH_IV0 0xf9afb5c6a540dbc7ull
#define ASCON_HASH_IV1 0xbd2493011445a340ull
#define ASCON_HASH_IV2 0xcb9ba8b5604d4fc8ull
#define ASCON_HASH_IV3 0x12a4eede94514c98ull
#define ASCON_HASH_IV4 0x4bca84c06339f398ull
#define ASCON_HASHA_IV0 0x0108e46d1b16eb02ull
#define ASCON_HASHA_IV1 0x5b9b8efdd29083f3ull
#define ASCON_HASHA_IV2 0x7ad665622891ae4aull
#define ASCON_HASHA_IV3 0x9dc27156ee3bfc7full
#define ASCON_HASHA_IV4 0xc61d5fa916801633ull
#define ASCON_XOF_IV0 0xc75782817e351ae6ull
#define ASCON_XOF_IV1 0x70045f441d238220ull
#define ASCON_XOF_IV2 0x5dd5ab52a13e3f04ull
#define ASCON_XOF_IV3 0x3e378142c30c1db2ull
#define ASCON_XOF_IV4 0x3735189db624d656ull
#define ASCON_XOFA_IV0 0x0846d7a5a4b87d44ull
#define ASCON_XOFA_IV1 0xaa6f1005b3a2dbf4ull
#define ASCON_XOFA_IV2 0xdc451146f713e811ull
#define ASCON_XOFA_IV3 0x468cb2532839e30dull
#define ASCON_XOFA_IV4 0xeb2d429709e96977ull
#define RC0 0x0000000c0000000cull
#define RC1 0x0000000c00000009ull
#define RC2 0x000000090000000cull
#define RC3 0x0000000900000009ull
#define RC4 0x0000000c00000006ull
#define RC5 0x0000000c00000003ull
#define RC6 0x0000000900000006ull
#define RC7 0x0000000900000003ull
#define RC8 0x000000060000000cull
#define RC9 0x0000000600000009ull
#define RCa 0x000000030000000cull
#define RCb 0x0000000300000009ull
#define RC(i) ((uint64_t)constants[i + 1] << 32 | constants[i])
#define START(n) (24 - 2 * (n))
#define INC 2
#define END 24
extern const uint8_t constants[];
#endif /* CONSTANTS_H_ */
#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
#ifdef ASCON_AEAD_RATE
forceinline void ascon_loadkey(key_t* key, const uint8_t* k) {
#if CRYPTO_KEYBYTES == 16
key->k1 = LOAD(k, 8);
key->k2 = LOAD(k + 8, 8);
#else /* CRYPTO_KEYBYTES == 20 */
key->k0 = KEYROT(0, LOADBYTES(k, 4));
key->k1 = LOADBYTES(k + 4, 8);
key->k2 = LOADBYTES(k + 12, 8);
#endif
}
forceinline void ascon_initaead(state_t* s, const uint8_t* npub,
const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) s->x[0] = ASCON_128_IV;
if (ASCON_AEAD_RATE == 16) s->x[0] = ASCON_128A_IV;
#else /* CRYPTO_KEYBYTES == 20 */
s->x[0] = ASCON_80PQ_IV ^ key->k0;
#endif
s->x[1] = key->k1;
s->x[2] = key->k2;
s->x[3] = LOAD(npub, 8);
s->x[4] = LOAD(npub + 8, 8);
printstate("init 1st key xor", s);
P(s, 12);
#if CRYPTO_KEYBYTES == 20
s->x[2] ^= key->k0;
#endif
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("init 2nd key xor", 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->x[0] ^= LOAD(ad, 8);
if (ASCON_AEAD_RATE == 16) s->x[1] ^= LOAD(ad + 8, 8);
printstate("absorb adata", s);
P(s, nr);
ad += ASCON_AEAD_RATE;
adlen -= ASCON_AEAD_RATE;
}
/* final associated data block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && adlen >= 8) {
s->x[0] ^= LOAD(ad, 8);
px = &s->x[1];
ad += 8;
adlen -= 8;
}
*px ^= PAD(adlen);
if (adlen) *px ^= LOAD(ad, adlen);
printstate("pad adata", s);
P(s, nr);
}
/* domain separation */
s->x[4] ^= 1;
printstate("domain separation", 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->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
if (ASCON_AEAD_RATE == 16) {
s->x[1] ^= LOAD(m + 8, 8);
STORE(c + 8, s->x[1], 8);
}
printstate("absorb plaintext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
mlen -= ASCON_AEAD_RATE;
}
/* final plaintext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && mlen >= 8) {
s->x[0] ^= LOAD(m, 8);
STORE(c, s->x[0], 8);
px = &s->x[1];
m += 8;
c += 8;
mlen -= 8;
}
*px ^= PAD(mlen);
if (mlen) {
*px ^= LOAD(m, mlen);
STORE(c, *px, mlen);
}
printstate("pad 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) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
if (ASCON_AEAD_RATE == 16) {
cx = LOAD(c + 8, 8);
s->x[1] ^= cx;
STORE(m + 8, s->x[1], 8);
s->x[1] = cx;
}
printstate("insert ciphertext", s);
P(s, nr);
m += ASCON_AEAD_RATE;
c += ASCON_AEAD_RATE;
clen -= ASCON_AEAD_RATE;
}
/* final ciphertext block */
uint64_t* px = &s->x[0];
if (ASCON_AEAD_RATE == 16 && clen >= 8) {
uint64_t cx = LOAD(c, 8);
s->x[0] ^= cx;
STORE(m, s->x[0], 8);
s->x[0] = cx;
px = &s->x[1];
m += 8;
c += 8;
clen -= 8;
}
*px ^= PAD(clen);
if (clen) {
uint64_t cx = LOAD(c, clen);
*px ^= cx;
STORE(m, *px, clen);
*px = CLEAR(*px, clen);
*px ^= cx;
}
printstate("pad ciphertext", s);
}
forceinline void ascon_final(state_t* s, const key_t* key) {
#if CRYPTO_KEYBYTES == 16
if (ASCON_AEAD_RATE == 8) {
s->x[1] ^= key->k1;
s->x[2] ^= key->k2;
} else {
s->x[2] ^= key->k1;
s->x[3] ^= key->k2;
}
#else /* CRYPTO_KEYBYTES == 20 */
s->x[1] ^= KEYROT(key->k0, key->k1);
s->x[2] ^= KEYROT(key->k1, key->k2);
s->x[3] ^= KEYROT(key->k2, 0);
#endif
printstate("final 1st key xor", s);
P(s, 12);
s->x[3] ^= key->k1;
s->x[4] ^= key->k2;
printstate("final 2nd key xor", 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_encrypt(&s, c, m, mlen);
ascon_final(&s, &key);
/* set tag */
STOREBYTES(c + mlen, s.x[3], 8);
STOREBYTES(c + mlen + 8, s.x[4], 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 */
key_t key;
ascon_loadkey(&key, k);
ascon_initaead(&s, npub, &key);
ascon_adata(&s, ad, adlen);
ascon_decrypt(&s, m, c, clen);
ascon_final(&s, &key);
/* verify tag (should be constant time, check compiler output) */
s.x[3] ^= LOADBYTES(c + clen, 8);
s.x[4] ^= LOADBYTES(c + clen + 8, 8);
return NOTZERO(s.x[3], s.x[4]);
}
#endif
#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_ */
#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_ */
#include "interleave.h"
#if !ASCON_EXTERN_BI
const uint32_t B[3] = {0x22222222, 0x0c0c0c0c, 0x00f000f0};
#if !ASCON_INLINE_BI
uint64_t TOBI(uint64_t in) { return deinterleave32(in); }
uint64_t FROMBI(uint64_t in) { return interleave32(in); }
#endif
#endif
#ifndef INTERLEAVE_H_
#define INTERLEAVE_H_
#include <stdint.h>
#include "config.h"
#include "endian.h"
#include "forceinline.h"
#if ASCON_INLINE_BI
#define TOBI deinterleave32
#define FROMBI interleave32
#else
uint64_t TOBI(uint64_t in);
uint64_t FROMBI(uint64_t in);
#endif
extern const uint32_t B[3];
forceinline uint32_t deinterleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
return x;
}
forceinline uint32_t interleave16(uint32_t x) {
uint32_t t;
t = (x ^ (x >> 8)) & 0xff00, x ^= t ^ (t << 8);
t = (x ^ (x >> 4)) & B[2], x ^= t ^ (t << 4);
t = (x ^ (x >> 2)) & B[1], x ^= t ^ (t << 2);
t = (x ^ (x >> 1)) & B[0], x ^= t ^ (t << 1);
return x;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t deinterleave32(uint64_t in) {
in = U64BIG(in);
uint32_t hi = in >> 32;
uint32_t lo = in;
uint32_t t0, t1, e, o;
t0 = deinterleave16(lo);
t1 = deinterleave16(hi);
e = (t1 << 16) | (t0 & 0x0000FFFF);
o = (t1 & 0xFFFF0000) | (t0 >> 16);
return (uint64_t)o << 32 | e;
}
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline uint64_t interleave32(uint64_t in) {
uint32_t e = in;
uint32_t o = in >> 32;
uint32_t t0, t1, lo, hi;
t0 = (o << 16) | (e & 0x0000FFFF);
t1 = (o & 0xFFFF0000) | (e >> 16);
lo = interleave16(t0);
hi = interleave16(t1);
return U64BIG((uint64_t)hi << 32 | lo);
}
#endif /* INTERLEAVE_H_ */
#include "permutations.h"
#if !ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P12(state_t* s) { P12ROUNDS(s); }
#endif
#if ((defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 16) || \
(defined(ASCON_HASH_ROUNDS) && ASCON_HASH_ROUNDS == 8)) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
void P8(state_t* s) { P8ROUNDS(s); }
#endif
#if (defined(ASCON_AEAD_RATE) && ASCON_AEAD_RATE == 8) && \
!ASCON_INLINE_PERM && ASCON_UNROLL_LOOPS
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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_
#include <stdint.h>
#include "api.h"
#include "ascon.h"
#include "config.h"
#include "constants.h"
#include "printstate.h"
#include "round.h"
#define LOADSTATE(s, a, b, c, d, e) \
do { \
a.x = s->x[0]; \
b.x = s->x[1]; \
c.x = s->x[2]; \
d.x = s->x[3]; \
e.x = s->x[4]; \
} while (0)
#define STORESTATE(s, a, b, c, d, e) \
do { \
s->x[0] = a.x; \
s->x[1] = b.x; \
s->x[2] = c.x; \
s->x[3] = d.x; \
s->x[4] = e.x; \
} while (0)
forceinline void P12ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC0);
ROUND5(x2, x3, x4, x0, x1, RC1);
ROUND5(x4, x0, x1, x2, x3, RC2);
ROUND5(x1, x2, x3, x4, x0, RC3);
ROUND5(x3, x4, x0, x1, x2, RC4);
ROUND5(x0, x1, x2, x3, x4, RC5);
ROUND5(x2, x3, x4, x0, x1, RC6);
ROUND5(x4, x0, x1, x2, x3, RC7);
ROUND5(x1, x2, x3, x4, x0, RC8);
ROUND5(x3, x4, x0, x1, x2, RC9);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCa);
ROUND5(x2, x3, x4, x0, x1, RCb);
STORESTATE(s, x4, x0, x1, x2, x3);
#else
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P8ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC4);
ROUND5(x2, x3, x4, x0, x1, RC5);
ROUND5(x4, x0, x1, x2, x3, RC6);
ROUND5(x1, x2, x3, x4, x0, RC7);
ROUND5(x3, x4, x0, x1, x2, RC8);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RC9);
ROUND5(x2, x3, x4, x0, x1, RCa);
ROUND5(x4, x0, x1, x2, x3, RCb);
STORESTATE(s, x1, x2, x3, x4, x0);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RC9);
ROUND(s, RCa);
ROUND(s, RCb);
#endif
}
forceinline void P6ROUNDS(state_t* s) {
word_t x0, x1, x2, x3, x4;
LOADSTATE(s, x0, x1, x2, x3, x4);
ROUND5(x0, x1, x2, x3, x4, RC6);
ROUND5(x2, x3, x4, x0, x1, RC7);
ROUND5(x4, x0, x1, x2, x3, RC8);
ROUND5(x1, x2, x3, x4, x0, RC9);
ROUND5(x3, x4, x0, x1, x2, RCa);
#if !ASCON_INLINE_PERM
ROUND5(x0, x1, x2, x3, x4, RCb);
STORESTATE(s, x2, x3, x4, x0, x1);
#else /* ASCON_INLINE_PERM */
STORESTATE(s, x0, x1, x2, x3, x4);
ROUND(s, RCb);
#endif
}
#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_ */
#ifdef ASCON_PRINT_STATE
#include "printstate.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#ifndef WORDTOU64
#define WORDTOU64
#endif
#ifndef U64BIG
#define U64BIG
#endif
void printword(const char* text, const uint64_t x) {
printf("%s=%016" PRIx64, text, U64BIG(WORDTOU64(x)));
}
void printstate(const char* text, const state_t* s) {
printf("%s:", text);
for (int i = strlen(text); i < 17; ++i) printf(" ");
printword(" x0", s->x[0]);
printword(" x1", s->x[1]);
printword(" x2", s->x[2]);
printword(" x3", s->x[3]);
printword(" x4", s->x[4]);
#ifdef ASCON_PRINT_BI
printf(" ");
printf(" x0=%08x_%08x", s->w[0][1], s->w[0][0]);
printf(" x1=%08x_%08x", s->w[1][1], s->w[1][0]);
printf(" x2=%08x_%08x", s->w[2][1], s->w[2][0]);
printf(" x3=%08x_%08x", s->w[3][1], s->w[3][0]);
printf(" x4=%08x_%08x", s->w[4][1], s->w[4][0]);
#endif
printf("\n");
}
#endif
#ifndef PRINTSTATE_H_
#define PRINTSTATE_H_
#ifdef ASCON_PRINT_STATE
#include "ascon.h"
#include "word.h"
void printword(const char* text, const uint64_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_ */
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment