Commit 2f8aa5e2 by Robert Primas Committed by Sebastian Renner

isap 3rd round optimizations

parent 07f5a6f4
### Folder Structure: **Folder Structure:**
* **isapa128av20** - `isapa128av20`: Code for ISAP128a using Ascon-p (primary recommendation).
* Code for ISAP128a using Ascon-p. - `isapa128v20`: Code for ISAP128 using Ascon-p.
* **isapa128v20** - `isapk128av20`: Code for ISAP128a using Keccak-p[400].
* Code for ISAP128 using Ascon-p. - `isapk128v20`: Code for ISAP128 using Keccak-p[400].
* **isapk128av20** - `isapxv20`: A generic codebase that can be used to build reference code for all four instances of ISAP.
* Code for ISAP128a using Keccak-p[400].
* **isapk128v20**
* Code for ISAP128 using Keccak-p[400].
* **isapxv20**
* A common codebase that can be used to build reference code for all four instances of ISAP.
#ifndef API_H
#define API_H
#define CRYPTO_VERSION "2.0.1"
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#endif
#include "api.h"
#include "isap.h"
#include "crypto_aead.h"
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
){
(void)nsec;
// Ciphertext length is mlen + tag length
*clen = mlen+ISAP_TAG_SZ;
// Encrypt plaintext and Generate tag
unsigned char *tag = c+mlen;
isap_mac_enc(k,npub,ad,adlen,c,mlen,m,mlen,tag);
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
){
(void)nsec;
// Plaintext length is clen - tag length
*mlen = clen-ISAP_TAG_SZ;
// Generate tag
unsigned char tag[ISAP_TAG_SZ];
isap_mac(k,npub,ad,adlen,c,*mlen,tag);
// Compare tag
unsigned long eq_cnt = 0;
for(unsigned int i = 0; i < ISAP_TAG_SZ; i++) {
eq_cnt += (tag[i] == c[(*mlen)+i]);
}
// Perform decryption if tag is correct
if(eq_cnt == (unsigned long)ISAP_TAG_SZ){
if (*mlen > 0) {
isap_enc(k,npub,c,*mlen,m);
}
return 0;
} else {
return -1;
}
}
#ifndef ISAP_H
#define ISAP_H
// Rate in bits
#define ISAP_rH 64
#define ISAP_rB 1
// Number of rounds
#define ISAP_sH 12
#define ISAP_sB 1
#define ISAP_sE 6
#define ISAP_sK 12
// State size in bytes
#define ISAP_STATE_SZ 40
// Size of rate in bytes
#define ISAP_rH_SZ ((ISAP_rH+7)/8)
// Size of zero truncated IV in bytes
#define ISAP_IV_SZ 8
// Size of tag in bytes
#define ISAP_TAG_SZ 16
// Security level
#define ISAP_K 128
void isap_mac(
const unsigned char *k,
const unsigned char *npub,
const unsigned char *ad, const unsigned long long adlen,
const unsigned char *c, const unsigned long long clen,
unsigned char *tag
);
void isap_mac_enc(
const unsigned char *k,
const unsigned char *npub,
const unsigned char *ad, const unsigned long long adlen,
unsigned char *c, const unsigned long long clen,
const unsigned char *m, const unsigned long long mlen,
unsigned char *tag
);
void isap_rk(
const unsigned char *k,
const unsigned char *iv,
const unsigned char *in,
const unsigned long long inlen,
unsigned char *out,
const unsigned long long outlen
);
void isap_enc(
const unsigned char *k,
const unsigned char *npub,
const unsigned char *m, const unsigned long long mlen,
unsigned char *c
);
#endif
#ifndef API_H
#define API_H
// isapa128a
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
// asconhashv12
#define CRYPTO_BYTES 32
#define ASCON_HASH_OUTLEN 32
#define ASCON_HASH_ROUNDS 12
#endif
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH P12ROUNDS(s)
#define P_sB P1ROUNDS(s)
#define P_sE P6ROUNDS(s)
#define P_sK P12ROUNDS(s)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
forceinline lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline uint32_t ROR32(uint32_t x, int n)
{
return x >> n | x << (-n & 31);
}
/* ---------------------------------------------------------------- */
forceinline uint64_t ROR(uint64_t x, int n)
{
lane_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 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];
}
/* ---------------------------------------------------------------- */
forceinline void P12ROUNDS(state_t *s)
{
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
ROUND(s, 0xc00000003);
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P6ROUNDS(state_t *s)
{
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P1ROUNDS(state_t *s)
{
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
#include "api.h"
#include "isap.h"
#include "crypto_aead.h"
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
){
(void)nsec;
// Ciphertext length is mlen + tag length
*clen = mlen+ISAP_TAG_SZ;
// Encrypt plaintext
if (mlen > 0) {
isap_enc(k,npub,m,mlen,c);
}
// Generate tag
unsigned char *tag = c+mlen;
isap_mac(k,npub,ad,adlen,c,mlen,tag);
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
){
(void)nsec;
// Plaintext length is clen - tag length
*mlen = clen-ISAP_TAG_SZ;
// Generate tag
unsigned char tag[ISAP_TAG_SZ];
isap_mac(k,npub,ad,adlen,c,*mlen,tag);
// Compare tag
unsigned long eq_cnt = 0;
for(unsigned int i = 0; i < ISAP_TAG_SZ; i++) {
eq_cnt += (tag[i] == c[(*mlen)+i]);
}
// Perform decryption if tag is correct
if(eq_cnt == (unsigned long)ISAP_TAG_SZ){
if (*mlen > 0) {
isap_enc(k,npub,c,*mlen,m);
}
return 0;
} else {
return -1;
}
}
#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 <string.h>
#include <inttypes.h>
#include "api.h"
#include "isap.h"
#include "asconp.h"
#include "config.h"
forceinline void ABSORB_LANES(state_t *s, const uint8_t *src, uint64_t len)
{
while (len >= 8)
{
// Absorb full lanes
lane_t t0 = U64TOWORD(*(lane_t *)(src + 0));
s->x[0] ^= t0.x;
len -= ISAP_rH / 8;
src += ISAP_rH / 8;
P_sH;
}
if (len > 0)
{
// Absorb partial lane and padding
size_t i;
lane_t t0 = {0};
for (i = 0; i < len; i++)
{
t0.b[7 - i] ^= *src;
src++;
}
t0.b[7 - i] ^= 0x80;
t0 = TOBI(t0);
s->x[0] ^= t0.x;
P_sH;
}
else
{
// Absorb padded empty lane
s->b[0][7] ^= 0x80;
P_sH;
}
}
/******************************************************************************/
/* ISAP_RK */
/******************************************************************************/
void isap_rk(
const uint8_t *k,
const uint8_t *iv,
const uint8_t *y,
state_t *out,
const size_t outlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(k + 0));
s->l[1] = U64TOWORD(*(lane_t *)(k + 8));
s->l[2] = U64TOWORD(*(lane_t *)(iv + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sK;
// Absorb Y, bit by bit
for (size_t i = 0; i < 16; i++)
{
uint8_t y_byte = *y;
s->b[0][7] ^= (y_byte & 0x80) << 0;
P_sB;
s->b[0][7] ^= (y_byte & 0x40) << 1;
P_sB;
s->b[0][7] ^= (y_byte & 0x20) << 2;
P_sB;
s->b[0][7] ^= (y_byte & 0x10) << 3;
P_sB;
s->b[0][7] ^= (y_byte & 0x08) << 4;
P_sB;
s->b[0][7] ^= (y_byte & 0x04) << 5;
P_sB;
s->b[0][7] ^= (y_byte & 0x02) << 6;
P_sB;
s->b[0][7] ^= (y_byte & 0x01) << 7;
if (i != 15)
{
P_sB;
y += 1;
}
}
// Squeeze K*
P_sK;
out->x[0] = s->x[0];
out->x[1] = s->x[1];
if (outlen > 16)
{
out->x[2] = s->x[2];
}
}
/******************************************************************************/
/* ISAP_MAC */
/******************************************************************************/
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, uint64_t adlen,
const uint8_t *c, uint64_t clen,
uint8_t *tag)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[1] = U64TOWORD(*(lane_t *)(npub + 8));
s->l[2] = U64TOWORD(*(lane_t *)(ISAP_IV_A + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb associated data
ABSORB_LANES(s, ad, adlen);
// Domain seperation
s->w[4][0] ^= 0x1UL;
// Absorb ciphertext
ABSORB_LANES(s, c, clen);
// Derive KA*
s->l[0] = WORDTOU64(s->l[0]);
s->l[1] = WORDTOU64(s->l[1]);
isap_rk(k, ISAP_IV_KA, (const uint8_t *)(s->b), s, CRYPTO_KEYBYTES);
// Squeeze tag
P_sH;
lane_t t0 = WORDTOU64(s->l[0]);
memcpy(tag + 0, t0.b, 8);
t0 = WORDTOU64(s->l[1]);
memcpy(tag + 8, t0.b, 8);
}
/******************************************************************************/
/* ISAP_ENC */
/******************************************************************************/
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, uint64_t mlen,
uint8_t *c)
{
state_t state;
state_t *s = &state;
// Init state
isap_rk(k, ISAP_IV_KE, npub, s, ISAP_STATE_SZ - CRYPTO_NPUBBYTES);
s->l[3] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[4] = U64TOWORD(*(lane_t *)(npub + 8));
while (mlen >= ISAP_rH / 8)
{
// Encrypt full lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)c = *(uint64_t *)m ^ t0.x;
mlen -= ISAP_rH / 8;
m += ISAP_rH / 8;
c += ISAP_rH / 8;
}
if (mlen > 0)
{
// Encrypt partial lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
for (uint8_t i = 0; i < mlen; i++)
{
*c = *m ^ t0.b[i];
m += 1;
c += 1;
}
}
}
/******************************************************************************/
/* Ascon-Hash */
/******************************************************************************/
#if ENABLE_HASH == 1
int crypto_hash(uint8_t *out, const uint8_t *in, unsigned long long inlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(ASCON_HASH_IV + 0));
s->x[1] = 0;
s->x[2] = 0;
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb input
ABSORB_LANES(s, in, inlen);
for (size_t i = 0; i < 4; i++)
{
// Squeeze full lanes
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)(out + 8 * i) = t0.x;
if (i < 3)
{
P_sH;
}
}
return 0;
}
#endif
#ifndef ISAP_H
#define ISAP_H
#include <inttypes.h>
// Rate in bits
#define ISAP_rH 64
#define ISAP_rB 1
// Number of rounds
#define ISAP_sH 12
#define ISAP_sB 1
#define ISAP_sE 6
#define ISAP_sK 12
// State size in bytes
#define ISAP_STATE_SZ 40
// Size of rate in bytes
#define ISAP_rH_SZ ((ISAP_rH + 7) / 8)
// Size of zero truncated IV in bytes
#define ISAP_IV_SZ 8
// Size of tag in bytes
#define ISAP_TAG_SZ 16
// Security level
#define ISAP_K 128
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, const uint64_t adlen,
const uint8_t *c, const uint64_t clen,
uint8_t *tag);
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, const uint64_t mlen,
uint8_t *c);
#endif
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH P12ROUNDS(s)
#define P_sB P1ROUNDS(s)
#define P_sE P6ROUNDS(s)
#define P_sK P12ROUNDS(s)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
forceinline lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint64_t C)
{
uint32_t tmp0, tmp1;
__asm__ __volatile__(
"eor %[x0_e], %[x0_e], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[x3_e]\n\t"
"eor %[x2_e], %[x2_e], %[x1_e]\n\t"
"mvn %[tmp0], %[x0_e]\n\t"
"orr %[tmp0], %[x4_e], %[tmp0]\n\t"
"eor %[x2_e], %[x2_e], %[C_e]\n\t"
"bic %[tmp1], %[x2_e], %[x1_e]\n\t"
"eor %[x0_e], %[x0_e], %[tmp1]\n\t"
"mvn %[tmp1], %[x4_e]\n\t"
"orr %[tmp1], %[x3_e], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"bic %[tmp1], %[x1_e], %[x0_e]\n\t"
"eor %[x4_e], %[x4_e], %[tmp1]\n\t"
"and %[tmp1], %[x3_e], %[x2_e]\n\t"
"eor %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x3_e], %[x3_e], %[tmp0]\n\t"
"eor %[x1_e], %[x1_e], %[x0_e]\n\t"
"eor %[x3_e], %[x3_e], %[x2_e]\n\t"
"eor %[x0_e], %[x0_e], %[x4_e]\n\t"
"eor %[x0_o], %[x0_o], %[x4_o]\n\t"
"eor %[x4_o], %[x4_o], %[x3_o]\n\t"
"eor %[x2_o], %[x2_o], %[C_o]\n\t"
"eor %[x2_o], %[x2_o], %[x1_o]\n\t"
"mvn %[tmp0], %[x0_o]\n\t"
"orr %[tmp0], %[x4_o], %[tmp0]\n\t"
"bic %[tmp1], %[x2_o], %[x1_o]\n\t"
"eor %[x0_o], %[x0_o], %[tmp1]\n\t"
"mvn %[tmp1], %[x4_o]\n\t"
"orr %[tmp1], %[x3_o], %[tmp1]\n\t"
"eor %[x2_o], %[x2_o], %[tmp1]\n\t"
"bic %[tmp1], %[x1_o], %[x0_o]\n\t"
"eor %[x4_o], %[x4_o], %[tmp1]\n\t"
"and %[tmp1], %[x3_o], %[x2_o]\n\t"
"eor %[x1_o], %[x1_o], %[tmp1]\n\t"
"eor %[x3_o], %[x3_o], %[tmp0]\n\t"
"eor %[x1_o], %[x1_o], %[x0_o]\n\t"
"eor %[x3_o], %[x3_o], %[x2_o]\n\t"
"eor %[x0_o], %[x0_o], %[x4_o]\n\t"
"eor %[tmp0], %[x0_e], %[x0_o], ror #4\n\t"
"eor %[tmp1], %[x0_o], %[x0_e], ror #5\n\t"
"eor %[x0_o], %[x0_o], %[tmp0], ror #10\n\t"
"eor %[x0_e], %[x0_e], %[tmp1], ror #9\n\t"
"eor %[tmp0], %[x1_e], %[x1_e], ror #11\n\t"
"eor %[tmp1], %[x1_o], %[x1_o], ror #11\n\t"
"eor %[x1_o], %[x1_o], %[tmp0], ror #20\n\t"
"eor %[x1_e], %[x1_e], %[tmp1], ror #19\n\t"
"eor %[tmp0], %[x2_e], %[x2_o], ror #2\n\t"
"eor %[tmp1], %[x2_o], %[x2_e], ror #3\n\t"
"eor %[x2_o], %[x2_o], %[tmp0], ror #1\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[tmp0], %[x3_e], %[x3_o], ror #3\n\t"
"eor %[tmp1], %[x3_o], %[x3_e], ror #4\n\t"
"eor %[x3_e], %[x3_e], %[tmp0], ror #5\n\t"
"eor %[x3_o], %[x3_o], %[tmp1], ror #5\n\t"
"eor %[tmp0], %[x4_e], %[x4_e], ror #17\n\t"
"eor %[tmp1], %[x4_o], %[x4_o], ror #17\n\t"
"eor %[x4_o], %[x4_o], %[tmp0], ror #4\n\t"
"eor %[x4_e], %[x4_e], %[tmp1], ror #3\n\t"
: [x0_e] "+r"(s->w[0][0]), [x0_o] "+r"(s->w[0][1]),
[x1_e] "+r"(s->w[1][0]), [x1_o] "+r"(s->w[1][1]),
[x2_e] "+r"(s->w[2][0]), [x2_o] "+r"(s->w[2][1]),
[x3_e] "+r"(s->w[3][0]), [x3_o] "+r"(s->w[3][1]),
[x4_e] "+r"(s->w[4][0]), [x4_o] "+r"(s->w[4][1]), [tmp0] "=r"(tmp0),
[tmp1] "=r"(tmp1)
: [C_e] "i"((uint32_t)C), [C_o] "i"((uint32_t)(C >> 32))
:);
}
/* ---------------------------------------------------------------- */
forceinline void P12ROUNDS(state_t *s)
{
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
ROUND(s, 0xc00000003);
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P6ROUNDS(state_t *s)
{
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P1ROUNDS(state_t *s)
{
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H_
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
../bi_32/crypto_aead.c
\ No newline at end of file
../bi_32/forceinline.h
\ No newline at end of file
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
../bi_32/crypto_aead.c
\ No newline at end of file
../bi_32/forceinline.h
\ No newline at end of file
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint64_t C)
{
uint32_t tmp0, tmp1, tmp2;
__asm__ __volatile__(
"@.syntax_unified\n\t"
"movs %[tmp1], %[C_e]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x0_e], %[x0_e], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[x3_e]\n\t"
"eor %[x2_e], %[x2_e], %[x1_e]\n\t"
"movs %[tmp0], %[x0_e]\n\t"
"bic %[tmp0], %[tmp0], %[x4_e]\n\t"
"movs %[tmp1], %[x2_e]\n\t"
"bic %[tmp1], %[tmp1], %[x1_e]\n\t"
"eor %[x0_e], %[x0_e], %[tmp1]\n\t"
"movs %[tmp1], %[x4_e]\n\t"
"bic %[tmp1], %[tmp1], %[x3_e]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"movs %[tmp2], %[x1_e]\n\t"
"bic %[tmp2], %[tmp2], %[x0_e]\n\t"
"eor %[tmp2], %[x4_e], %[tmp2]\n\t"
"movs %[tmp1], %[x3_e]\n\t"
"bic %[tmp1], %[tmp1], %[x2_e]\n\t"
"eor %[tmp1], %[x1_e], %[tmp1]\n\t"
"eor %[tmp0], %[x3_e], %[tmp0]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"eor %[tmp1], %[tmp1], %[x0_e]\n\t"
"eor %[x0_e], %[x0_e], %[tmp2]\n\t"
"movs %[x4_e], %[x4_o]\n\t"
"movs %[x1_e], %[x1_o]\n\t"
"movs %[x3_e], %[x3_o]\n\t"
"movs %[x3_o], %[tmp0]\n\t"
"movs %[x1_o], %[tmp1]\n\t"
"movs %[tmp0], %[x0_o]\n\t"
"movs %[tmp1], %[x2_o]\n\t"
"movs %[x0_o], %[x0_e]\n\t"
"movs %[x2_o], %[x2_e]\n\t"
"movs %[x0_e], %[C_o]\n\t"
"eor %[tmp1], %[tmp1], %[x0_e]\n\t"
"eor %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[x3_e]\n\t"
"eor %[tmp1], %[tmp1], %[x1_e]\n\t"
"movs %[x0_e], %[tmp0] \n\t"
"bic %[x0_e], %[x0_e], %[x4_e]\n\t"
"movs %[x2_e], %[tmp1] \n\t"
"bic %[x2_e], %[x2_e], %[x1_e]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"movs %[x2_e], %[x4_e] \n\t"
"bic %[x2_e], %[x2_e], %[x3_e]\n\t"
"eor %[tmp1], %[tmp1], %[x2_e]\n\t"
"movs %[x2_e], %[x1_e]\n\t"
"bic %[x2_e], %[x2_e], %[tmp0]\n\t"
"eor %[x4_e], %[x4_e], %[x2_e]\n\t"
"movs %[x2_e], %[x3_e] \n\t"
"bic %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[x2_e]\n\t"
"eor %[x3_e], %[x3_e], %[x0_e]\n\t"
"eor %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[tmp0]\n\t"
"eor %[tmp0], %[tmp0], %[x4_e]\n\t"
"movs %[x4_o], %[tmp1]\n\t"
"movs %[x2_e], %[x3_o]\n\t"
"movs %[x3_o], %[x1_e]\n\t"
"movs %[tmp1], #17\n\t"
"movs %[x0_e], %[tmp2]\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x0_e], %[tmp2], %[x0_e]\n\t"
"movs %[x1_e], %[x4_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x1_e], %[x4_e], %[x1_e]\n\t"
"movs %[tmp1], #3\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[tmp2], %[tmp2], %[x1_e]\n\t"
"movs %[tmp1], #4\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x4_e], %[x4_e], %[x0_e]\n\t"
"movs %[x1_e], %[x2_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x1_e], %[x3_e], %[x1_e]\n\t"
"movs %[tmp1], #3\n\t"
"movs %[x0_e], %[x3_e]\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x0_e], %[x2_e], %[x0_e]\n\t"
"movs %[tmp1], #5\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[x0_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x3_e], %[x3_e], %[x1_e]\n\t"
"movs %[x0_e], %[x0_o]\n\t"
"movs %[x1_e], %[x1_o]\n\t"
"movs %[x1_o], %[x2_e]\n\t"
"movs %[x0_o], %[tmp2]\n\t"
"movs %[tmp2], %[x4_o]\n\t"
"movs %[x4_o], %[x4_e]\n\t"
"movs %[x4_e], %[x3_o]\n\t"
"movs %[x3_o], %[x3_e]\n\t"
"movs %[x3_e], %[x0_e]\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x3_e], %[tmp0], %[x3_e]\n\t"
"movs %[tmp1], #4\n\t"
"movs %[x2_e], %[tmp0]\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x2_e], %[x0_e], %[x2_e]\n\t"
"movs %[tmp1], #9\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x0_e], %[x0_e], %[x3_e]\n\t"
"movs %[tmp1], #10\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"movs %[tmp1], #11\n\t"
"movs %[x2_e], %[x1_e]\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x2_e], %[x1_e], %[x2_e]\n\t"
"movs %[x3_e], %[x4_e]\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x3_e], %[x4_e], %[x3_e]\n\t"
"movs %[tmp1], #19\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[x3_e]\n\t"
"movs %[tmp1], #20\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x4_e], %[x4_e], %[x2_e]\n\t"
"movs %[x2_e], %[x2_o]\n\t"
"movs %[x3_e], %[x1_o]\n\t"
"movs %[x1_o], %[x4_e]\n\t"
"movs %[x2_o], %[tmp0]\n\t"
"movs %[x4_e], #2\n\t"
"mvn %[tmp0], %[tmp2]\n\t"
"ror %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[tmp0], %[x2_e], %[tmp0]\n\t"
"movs %[x4_e], #3\n\t"
"mvn %[tmp1], %[x2_e]\n\t"
"ror %[tmp1], %[tmp1], %[x4_e]\n\t"
"eor %[tmp1], %[tmp2], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"movs %[x4_e], #1\n\t"
"ror %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[tmp2], %[tmp2], %[tmp0]\n\t"
"movs %[x4_e], %[x0_o]\n\t"
"movs %[x0_o], %[x2_o]\n\t"
"movs %[x2_o], %[tmp2]\n\t"
: [x0_e] "+l"(s->w[0][0]), [x1_e] "+l"(s->w[1][0]),
[x2_e] "+l"(s->w[2][0]), [x3_e] "+l"(s->w[3][0]),
[x4_e] "+l"(s->w[4][0]), [x0_o] "+r"(s->w[0][1]),
[x1_o] "+r"(s->w[1][1]), [x2_o] "+r"(s->w[2][1]),
[x3_o] "+r"(s->w[3][1]), [x4_o] "+r"(s->w[4][1]),
[tmp0] "=l"(tmp0), [tmp1] "=l"(tmp1), [tmp2] "=l"(tmp2)
: [C_e] "ri"((uint32_t)C), [C_o] "ri"((uint32_t)(C >> 32))
:);
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
ROUND(s, 0xc00000003);
case 6:
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
default:
ROUND(s, 0x300000009);
;
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
#define P_PVP PROUNDS(s, 7)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint64_t C)
{
uint32_t tmp0, tmp1, tmp2;
__asm__ __volatile__(
"@.syntax_unified\n\t"
"movs %[tmp1], %[C_e]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x0_e], %[x0_e], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[x3_e]\n\t"
"eor %[x2_e], %[x2_e], %[x1_e]\n\t"
"movs %[tmp0], %[x0_e]\n\t"
"bic %[tmp0], %[tmp0], %[x4_e]\n\t"
"movs %[tmp1], %[x2_e]\n\t"
"bic %[tmp1], %[tmp1], %[x1_e]\n\t"
"eor %[x0_e], %[x0_e], %[tmp1]\n\t"
"movs %[tmp1], %[x4_e]\n\t"
"bic %[tmp1], %[tmp1], %[x3_e]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"movs %[tmp2], %[x1_e]\n\t"
"bic %[tmp2], %[tmp2], %[x0_e]\n\t"
"eor %[tmp2], %[x4_e], %[tmp2]\n\t"
"movs %[tmp1], %[x3_e]\n\t"
"bic %[tmp1], %[tmp1], %[x2_e]\n\t"
"eor %[tmp1], %[x1_e], %[tmp1]\n\t"
"eor %[tmp0], %[x3_e], %[tmp0]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"eor %[tmp1], %[tmp1], %[x0_e]\n\t"
"eor %[x0_e], %[x0_e], %[tmp2]\n\t"
"movs %[x4_e], %[x4_o]\n\t"
"movs %[x1_e], %[x1_o]\n\t"
"movs %[x3_e], %[x3_o]\n\t"
"movs %[x3_o], %[tmp0]\n\t"
"movs %[x1_o], %[tmp1]\n\t"
"movs %[tmp0], %[x0_o]\n\t"
"movs %[tmp1], %[x2_o]\n\t"
"movs %[x0_o], %[x0_e]\n\t"
"movs %[x2_o], %[x2_e]\n\t"
"movs %[x0_e], %[C_o]\n\t"
"eor %[tmp1], %[tmp1], %[x0_e]\n\t"
"eor %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[x3_e]\n\t"
"eor %[tmp1], %[tmp1], %[x1_e]\n\t"
"movs %[x0_e], %[tmp0] \n\t"
"bic %[x0_e], %[x0_e], %[x4_e]\n\t"
"movs %[x2_e], %[tmp1] \n\t"
"bic %[x2_e], %[x2_e], %[x1_e]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"movs %[x2_e], %[x4_e] \n\t"
"bic %[x2_e], %[x2_e], %[x3_e]\n\t"
"eor %[tmp1], %[tmp1], %[x2_e]\n\t"
"movs %[x2_e], %[x1_e]\n\t"
"bic %[x2_e], %[x2_e], %[tmp0]\n\t"
"eor %[x4_e], %[x4_e], %[x2_e]\n\t"
"movs %[x2_e], %[x3_e] \n\t"
"bic %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[x2_e]\n\t"
"eor %[x3_e], %[x3_e], %[x0_e]\n\t"
"eor %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[tmp0]\n\t"
"eor %[tmp0], %[tmp0], %[x4_e]\n\t"
"movs %[x4_o], %[tmp1]\n\t"
"movs %[x2_e], %[x3_o]\n\t"
"movs %[x3_o], %[x1_e]\n\t"
"movs %[tmp1], #17\n\t"
"movs %[x0_e], %[tmp2]\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x0_e], %[tmp2], %[x0_e]\n\t"
"movs %[x1_e], %[x4_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x1_e], %[x4_e], %[x1_e]\n\t"
"movs %[tmp1], #3\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[tmp2], %[tmp2], %[x1_e]\n\t"
"movs %[tmp1], #4\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x4_e], %[x4_e], %[x0_e]\n\t"
"movs %[x1_e], %[x2_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x1_e], %[x3_e], %[x1_e]\n\t"
"movs %[tmp1], #3\n\t"
"movs %[x0_e], %[x3_e]\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x0_e], %[x2_e], %[x0_e]\n\t"
"movs %[tmp1], #5\n\t"
"ror %[x0_e], %[x0_e], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[x0_e]\n\t"
"ror %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x3_e], %[x3_e], %[x1_e]\n\t"
"movs %[x0_e], %[x0_o]\n\t"
"movs %[x1_e], %[x1_o]\n\t"
"movs %[x1_o], %[x2_e]\n\t"
"movs %[x0_o], %[tmp2]\n\t"
"movs %[tmp2], %[x4_o]\n\t"
"movs %[x4_o], %[x4_e]\n\t"
"movs %[x4_e], %[x3_o]\n\t"
"movs %[x3_o], %[x3_e]\n\t"
"movs %[x3_e], %[x0_e]\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x3_e], %[tmp0], %[x3_e]\n\t"
"movs %[tmp1], #4\n\t"
"movs %[x2_e], %[tmp0]\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x2_e], %[x0_e], %[x2_e]\n\t"
"movs %[tmp1], #9\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x0_e], %[x0_e], %[x3_e]\n\t"
"movs %[tmp1], #10\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[tmp0], %[tmp0], %[x2_e]\n\t"
"movs %[tmp1], #11\n\t"
"movs %[x2_e], %[x1_e]\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x2_e], %[x1_e], %[x2_e]\n\t"
"movs %[x3_e], %[x4_e]\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x3_e], %[x4_e], %[x3_e]\n\t"
"movs %[tmp1], #19\n\t"
"ror %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[x3_e]\n\t"
"movs %[tmp1], #20\n\t"
"ror %[x2_e], %[x2_e], %[tmp1]\n\t"
"eor %[x4_e], %[x4_e], %[x2_e]\n\t"
"movs %[x2_e], %[x2_o]\n\t"
"movs %[x3_e], %[x1_o]\n\t"
"movs %[x1_o], %[x4_e]\n\t"
"movs %[x2_o], %[tmp0]\n\t"
"movs %[x4_e], #2\n\t"
"mvn %[tmp0], %[tmp2]\n\t"
"ror %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[tmp0], %[x2_e], %[tmp0]\n\t"
"movs %[x4_e], #3\n\t"
"mvn %[tmp1], %[x2_e]\n\t"
"ror %[tmp1], %[tmp1], %[x4_e]\n\t"
"eor %[tmp1], %[tmp2], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"movs %[x4_e], #1\n\t"
"ror %[tmp0], %[tmp0], %[x4_e]\n\t"
"eor %[tmp2], %[tmp2], %[tmp0]\n\t"
"movs %[x4_e], %[x0_o]\n\t"
"movs %[x0_o], %[x2_o]\n\t"
"movs %[x2_o], %[tmp2]\n\t"
: [x0_e] "+l"(s->w[0][0]), [x1_e] "+l"(s->w[1][0]),
[x2_e] "+l"(s->w[2][0]), [x3_e] "+l"(s->w[3][0]),
[x4_e] "+l"(s->w[4][0]), [x0_o] "+r"(s->w[0][1]),
[x1_o] "+r"(s->w[1][1]), [x2_o] "+r"(s->w[2][1]),
[x3_o] "+r"(s->w[3][1]), [x4_o] "+r"(s->w[4][1]),
[tmp0] "=l"(tmp0), [tmp1] "=l"(tmp1), [tmp2] "=l"(tmp2)
: [C_e] "ri"((uint32_t)C), [C_o] "ri"((uint32_t)(C >> 32))
:);
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
case 7:
ROUND(s, 0xc00000003);
case 6:
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
default:
ROUND(s, 0x300000009);
;
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
#include "api.h"
#include "isap.h"
#include "crypto_aead.h"
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)
{
(void)nsec;
// Ciphertext length is mlen + tag length
*clen = mlen + ISAP_TAG_SZ;
// Encrypt plaintext
if (mlen > 0)
{
isap_enc(k, npub, m, mlen, c);
}
// Generate tag
unsigned char *tag = c + mlen;
isap_mac(k, npub, ad, adlen, c, mlen, tag);
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)
{
(void)nsec;
// Plaintext length is clen - tag length
*mlen = clen - ISAP_TAG_SZ;
// Generate tag
unsigned char T[16];
isap_mac(k, npub, ad, adlen, c, *mlen, T);
// Compare tag
unsigned char T_star[16];
for (int i = 0; i < 16; i++)
{
T_star[i] = *(c + *mlen + i);
}
int eq_cnt = pvp(T, T_star);
// Perform decryption if tag is correct
if (eq_cnt == ISAP_TAG_SZ)
{
if (*mlen > 0)
{
isap_enc(k, npub, c, *mlen, m);
}
return 0;
}
else
{
return -1;
}
}
#include <string.h>
#include <inttypes.h>
#include "api.h"
#include "isap.h"
#include "asconp.h"
#include "config.h"
// Needed for LR tag comparison
uint64_t s0, s1;
forceinline void ABSORB_LANES(state_t *s, const uint8_t *src, uint64_t len)
{
while (len >= 8)
{
// Absorb full lanes
lane_t t0 = U64TOWORD(*(lane_t *)(src + 0));
s->x[0] ^= t0.x;
len -= ISAP_rH / 8;
src += ISAP_rH / 8;
P_sH;
}
if (len > 0)
{
// Absorb partial lane and padding
size_t i;
lane_t t0 = {0};
for (i = 0; i < len; i++)
{
t0.b[7 - i] ^= *src;
src++;
}
t0.b[7 - i] ^= 0x80;
t0 = TOBI(t0);
s->x[0] ^= t0.x;
P_sH;
}
else
{
// Absorb padded empty lane
s->b[0][7] ^= 0x80;
P_sH;
}
}
/******************************************************************************/
/* ISAP_RK */
/******************************************************************************/
void isap_rk(
const uint8_t *k,
const uint8_t *iv,
const uint8_t *y,
state_t *out,
const size_t outlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(k + 0));
s->l[1] = U64TOWORD(*(lane_t *)(k + 8));
s->l[2] = U64TOWORD(*(lane_t *)(iv + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sK;
// Absorb Y, bit by bit
for (size_t i = 0; i < 16; i++)
{
uint8_t y_byte = *y;
s->b[0][7] ^= (y_byte & 0x80) << 0;
P_sB;
s->b[0][7] ^= (y_byte & 0x40) << 1;
P_sB;
s->b[0][7] ^= (y_byte & 0x20) << 2;
P_sB;
s->b[0][7] ^= (y_byte & 0x10) << 3;
P_sB;
s->b[0][7] ^= (y_byte & 0x08) << 4;
P_sB;
s->b[0][7] ^= (y_byte & 0x04) << 5;
P_sB;
s->b[0][7] ^= (y_byte & 0x02) << 6;
P_sB;
s->b[0][7] ^= (y_byte & 0x01) << 7;
if (i != 15)
{
P_sB;
y += 1;
}
}
// Squeeze K*
P_sK;
out->x[0] = s->x[0];
out->x[1] = s->x[1];
if (outlen > 16)
{
out->x[2] = s->x[2];
}
}
/******************************************************************************/
/* ISAP_MAC */
/******************************************************************************/
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, uint64_t adlen,
const uint8_t *c, uint64_t clen,
uint8_t *tag)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[1] = U64TOWORD(*(lane_t *)(npub + 8));
s->l[2] = U64TOWORD(*(lane_t *)(ISAP_IV_A + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb associated data
ABSORB_LANES(s, ad, adlen);
// Domain seperation
s->w[4][0] ^= 0x1UL;
// Absorb ciphertext
ABSORB_LANES(s, c, clen);
// Needed for LR tag comparison
s0 = s->x[0];
s1 = s->x[1];
// Derive KA*
s->l[0] = WORDTOU64(s->l[0]);
s->l[1] = WORDTOU64(s->l[1]);
isap_rk(k, ISAP_IV_KA, (const uint8_t *)(s->b), s, CRYPTO_KEYBYTES);
// Squeeze tag
P_sH;
lane_t t0 = WORDTOU64(s->l[0]);
memcpy(tag + 0, t0.b, 8);
t0 = WORDTOU64(s->l[1]);
memcpy(tag + 8, t0.b, 8);
}
/******************************************************************************/
/* Leakage resilient tag comparison. */
/* Similar to Fig.3 of https://eprint.iacr.org/2021/402.pdf. */
/******************************************************************************/
int pvp(
const uint8_t *T, const uint8_t *T_star)
{
state_t state;
state_t *s = &state;
// Calculate U
s->l[0] = U64TOWORD(*(lane_t *)(T + 0));
s->l[1] = U64TOWORD(*(lane_t *)(T + 8));
s->x[2] = s0;
s->x[3] = s1;
s->x[4] = 0;
P_PVP;
uint64_t u0, u1;
u0 = s->x[0];
u1 = s->x[1];
// Calculate U'
s->l[0] = U64TOWORD(*(lane_t *)(T_star + 0));
s->l[1] = U64TOWORD(*(lane_t *)(T_star + 8));
s->x[2] = s0;
s->x[3] = s1;
s->x[4] = 0;
P_PVP;
// Compare tag
int eq_cnt = 0;
for (size_t i = 0; i < 8; i++)
{
eq_cnt += (s->b[0][i] == ((uint8_t *)&u0)[i]);
}
for (size_t i = 0; i < 8; i++)
{
eq_cnt += (s->b[1][i] == ((uint8_t *)&u1)[i]);
}
return eq_cnt;
}
/******************************************************************************/
/* ISAP_ENC */
/******************************************************************************/
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, uint64_t mlen,
uint8_t *c)
{
state_t state;
state_t *s = &state;
// Init state
isap_rk(k, ISAP_IV_KE, npub, s, ISAP_STATE_SZ - CRYPTO_NPUBBYTES);
s->l[3] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[4] = U64TOWORD(*(lane_t *)(npub + 8));
while (mlen >= ISAP_rH / 8)
{
// Encrypt full lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)c = *(uint64_t *)m ^ t0.x;
mlen -= ISAP_rH / 8;
m += ISAP_rH / 8;
c += ISAP_rH / 8;
}
if (mlen > 0)
{
// Encrypt partial lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
for (uint8_t i = 0; i < mlen; i++)
{
*c = *m ^ t0.b[i];
m += 1;
c += 1;
}
}
}
/******************************************************************************/
/* Ascon-Hash */
/******************************************************************************/
#if ENABLE_HASH == 1
int crypto_hash(uint8_t *out, const uint8_t *in, unsigned long long inlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(ASCON_HASH_IV + 0));
s->x[1] = 0;
s->x[2] = 0;
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb input
ABSORB_LANES(s, in, inlen);
for (size_t i = 0; i < 4; i++)
{
// Squeeze full lanes
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)(out + 8 * i) = t0.x;
if (i < 3)
{
P_sH;
}
}
return 0;
}
#endif
#ifndef ISAP_H
#define ISAP_H
#include <inttypes.h>
// Rate in bits
#define ISAP_rH 64
#define ISAP_rB 1
// Number of rounds
#define ISAP_sH 12
#define ISAP_sB 1
#define ISAP_sE 6
#define ISAP_sK 12
// State size in bytes
#define ISAP_STATE_SZ 40
// Size of rate in bytes
#define ISAP_rH_SZ ((ISAP_rH + 7) / 8)
// Size of zero truncated IV in bytes
#define ISAP_IV_SZ 8
// Size of tag in bytes
#define ISAP_TAG_SZ 16
// Security level
#define ISAP_K 128
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, const uint64_t adlen,
const uint8_t *c, const uint64_t clen,
uint8_t *tag);
int pvp(
const unsigned char *T,
const unsigned char *T_star);
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, const uint64_t mlen,
uint8_t *c);
#endif
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH P12ROUNDS(s)
#define P_sB P1ROUNDS(s)
#define P_sE P6ROUNDS(s)
#define P_sK P12ROUNDS(s)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
forceinline lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
forceinline lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint64_t C)
{
// Based on the round description of Ascon given in the Bachelor's
// thesis: "Optimizing Ascon on RISC-V" of Lars Jellema
// see https://github.com/Lucus16/ascon-riscv/
uint32_t tmp0, tmp1, tmp2;
__asm__ __volatile__(
"eor %[x2_e], %[x2_e], %[C_e]\n\t"
"eor %[tmp0], %[x1_e], %[x2_e]\n\t"
"eor %[tmp1], %[x0_e], %[x4_e]\n\t"
"eor %[tmp2], %[x3_e], %[x4_e]\n\t"
"orn %[x4_e], %[x3_e], %[x4_e]\n\t"
"eor %[x4_e], %[x4_e], %[tmp0]\n\t"
"eor %[x3_e], %[x3_e], %[x1_e]\n\t"
"orr %[x3_e], %[x3_e], %[tmp0]\n\t"
"eor %[x3_e], %[x3_e], %[tmp1]\n\t"
"eor %[x2_e], %[x2_e], %[tmp1]\n\t"
"orr %[x2_e], %[x2_e], %[x1_e]\n\t"
"eor %[x2_e], %[x2_e], %[tmp2]\n\t"
"bic %[x1_e], %[x1_e], %[tmp1]\n\t"
"eor %[x1_e], %[x1_e], %[tmp2]\n\t"
"orr %[x0_e], %[x0_e], %[tmp2]\n\t"
"eor %[x0_e], %[x0_e], %[tmp0]\n\t"
"eor %[x2_o], %[x2_o], %[C_o]\n\t"
"eor %[tmp0], %[x1_o], %[x2_o]\n\t"
"eor %[tmp1], %[x0_o], %[x4_o]\n\t"
"eor %[tmp2], %[x3_o], %[x4_o]\n\t"
"orn %[x4_o], %[x3_o], %[x4_o]\n\t"
"eor %[x4_o], %[x4_o], %[tmp0]\n\t"
"eor %[x3_o], %[x3_o], %[x1_o]\n\t"
"orr %[x3_o], %[x3_o], %[tmp0]\n\t"
"eor %[x3_o], %[x3_o], %[tmp1]\n\t"
"eor %[x2_o], %[x2_o], %[tmp1]\n\t"
"orr %[x2_o], %[x2_o], %[x1_o]\n\t"
"eor %[x2_o], %[x2_o], %[tmp2]\n\t"
"bic %[x1_o], %[x1_o], %[tmp1]\n\t"
"eor %[x1_o], %[x1_o], %[tmp2]\n\t"
"orr %[x0_o], %[x0_o], %[tmp2]\n\t"
"eor %[x0_o], %[x0_o], %[tmp0]\n\t"
"eor %[tmp0], %[x2_e], %[x2_o], ror #4\n\t"
"eor %[tmp1], %[x2_o], %[x2_e], ror #5\n\t"
"eor %[x2_o], %[x2_o], %[tmp0], ror #10\n\t"
"eor %[x2_e], %[x2_e], %[tmp1], ror #9\n\t"
"eor %[tmp0], %[x3_e], %[x3_e], ror #11\n\t"
"eor %[tmp1], %[x3_o], %[x3_o], ror #11\n\t"
"eor %[x3_o], %[x3_o], %[tmp0], ror #20\n\t"
"eor %[x3_e], %[x3_e], %[tmp1], ror #19\n\t"
"eor %[tmp0], %[x4_e], %[x4_o], ror #2\n\t"
"eor %[tmp1], %[x4_o], %[x4_e], ror #3\n\t"
"eor %[x4_o], %[x4_o], %[tmp0], ror #1\n\t"
"eor %[x4_e], %[x4_e], %[tmp1]\n\t"
"eor %[tmp0], %[x0_e], %[x0_o], ror #3\n\t"
"eor %[tmp1], %[x0_o], %[x0_e], ror #4\n\t"
"eor %[x0_e], %[x0_e], %[tmp0], ror #5\n\t"
"eor %[x0_o], %[x0_o], %[tmp1], ror #5\n\t"
"eor %[tmp0], %[x1_e], %[x1_e], ror #17\n\t"
"eor %[tmp1], %[x1_o], %[x1_o], ror #17\n\t"
"eor %[x1_o], %[x1_o], %[tmp0], ror #4\n\t"
"eor %[x1_e], %[x1_e], %[tmp1], ror #3\n\t"
: [x0_e] "+r"(s->w[0][0]), [x0_o] "+r"(s->w[0][1]),
[x1_e] "+r"(s->w[1][0]), [x1_o] "+r"(s->w[1][1]),
[x2_e] "+r"(s->w[2][0]), [x2_o] "+r"(s->w[2][1]),
[x3_e] "+r"(s->w[3][0]), [x3_o] "+r"(s->w[3][1]),
[x4_e] "+r"(s->w[4][0]), [x4_o] "+r"(s->w[4][1]), [tmp0] "=r"(tmp0),
[tmp1] "=r"(tmp1), [tmp2] "=r"(tmp2)
: [C_e] "i"((uint32_t)C), [C_o] "i"((uint32_t)(C >> 32))
:);
}
/* ---------------------------------------------------------------- */
forceinline void P12ROUNDS(state_t *s)
{
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
ROUND(s, 0xc00000003);
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P6ROUNDS(state_t *s)
{
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
forceinline void P1ROUNDS(state_t *s)
{
ROUND(s, 0x300000009);
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H_
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
../bi_32/crypto_aead.c
\ No newline at end of file
../bi_32/forceinline.h
\ No newline at end of file
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline uint32_t ROR32(uint32_t x, int n)
{
return x >> n | x << (-n & 31);
}
/* ---------------------------------------------------------------- */
forceinline uint64_t ROR(uint64_t x, int n)
{
lane_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 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];
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
ROUND(s, 0xc00000003);
case 6:
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
default:
ROUND(s, 0x300000009);
;
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
../bi_32/crypto_aead.c
\ No newline at end of file
../bi_32/forceinline.h
\ No newline at end of file
../bi_32/api.h
\ No newline at end of file
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
#define P_PVP PROUNDS(s, 7)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) to_bit_interleaving(U64BIG(x))
#define WORDTOU64(x) U64BIG(from_bit_interleaving(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) to_bit_interleaving(x)
#define FROMBI(x) from_bit_interleaving(x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t to_bit_interleaving(lane_t in)
{
uint32_t lo = in.w[0];
uint32_t hi = in.w[1];
uint32_t r0, r1;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
lane_t out;
out.w[0] = (lo & 0x0000FFFF) | (hi << 16);
out.w[1] = (lo >> 16) | (hi & 0xFFFF0000);
return out;
}
/* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
lane_t from_bit_interleaving(lane_t in)
{
uint32_t lo = ((in).w[0] & 0x0000FFFF) | ((in).w[1] << 16);
uint32_t hi = ((in).w[0] >> 16) | ((in).w[1] & 0xFFFF0000);
uint32_t r0, r1;
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1);
lane_t out;
out.x = (uint64_t)hi << 32 | lo;
return out;
}
/* ---------------------------------------------------------------- */
forceinline uint32_t ROR32(uint32_t x, int n)
{
return x >> n | x << (-n & 31);
}
/* ---------------------------------------------------------------- */
forceinline uint64_t ROR(uint64_t x, int n)
{
lane_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 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];
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xc0000000c);
ROUND(s, 0xc00000009);
ROUND(s, 0x90000000c);
ROUND(s, 0x900000009);
ROUND(s, 0xc00000006);
case 7:
ROUND(s, 0xc00000003);
case 6:
ROUND(s, 0x900000006);
ROUND(s, 0x900000003);
ROUND(s, 0x60000000c);
ROUND(s, 0x600000009);
ROUND(s, 0x30000000c);
default:
ROUND(s, 0x300000009);
;
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
#include "api.h"
#include "isap.h"
#include "crypto_aead.h"
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)
{
(void)nsec;
// Ciphertext length is mlen + tag length
*clen = mlen + ISAP_TAG_SZ;
// Encrypt plaintext
if (mlen > 0)
{
isap_enc(k, npub, m, mlen, c);
}
// Generate tag
unsigned char *tag = c + mlen;
isap_mac(k, npub, ad, adlen, c, mlen, tag);
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)
{
(void)nsec;
// Plaintext length is clen - tag length
*mlen = clen - ISAP_TAG_SZ;
// Generate tag
unsigned char T[16];
isap_mac(k, npub, ad, adlen, c, *mlen, T);
// Compare tag
unsigned char T_star[16];
for (int i = 0; i < 16; i++)
{
T_star[i] = *(c + *mlen + i);
}
int eq_cnt = pvp(T, T_star);
// Perform decryption if tag is correct
if (eq_cnt == ISAP_TAG_SZ)
{
if (*mlen > 0)
{
isap_enc(k, npub, c, *mlen, m);
}
return 0;
}
else
{
return -1;
}
}
../bi_32/forceinline.h
\ No newline at end of file
#include <string.h>
#include <inttypes.h>
#include "api.h"
#include "isap.h"
#include "asconp.h"
#include "config.h"
// Needed for LR tag comparison
uint64_t s0, s1;
forceinline void ABSORB_LANES(state_t *s, const uint8_t *src, uint64_t len)
{
while (len >= 8)
{
// Absorb full lanes
lane_t t0 = U64TOWORD(*(lane_t *)(src + 0));
s->x[0] ^= t0.x;
len -= ISAP_rH / 8;
src += ISAP_rH / 8;
P_sH;
}
if (len > 0)
{
// Absorb partial lane and padding
size_t i;
lane_t t0 = {0};
for (i = 0; i < len; i++)
{
t0.b[7 - i] ^= *src;
src++;
}
t0.b[7 - i] ^= 0x80;
t0 = TOBI(t0);
s->x[0] ^= t0.x;
P_sH;
}
else
{
// Absorb padded empty lane
s->b[0][7] ^= 0x80;
P_sH;
}
}
/******************************************************************************/
/* ISAP_RK */
/******************************************************************************/
void isap_rk(
const uint8_t *k,
const uint8_t *iv,
const uint8_t *y,
state_t *out,
const size_t outlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(k + 0));
s->l[1] = U64TOWORD(*(lane_t *)(k + 8));
s->l[2] = U64TOWORD(*(lane_t *)(iv + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sK;
// Absorb Y, bit by bit
for (size_t i = 0; i < 16; i++)
{
uint8_t y_byte = *y;
s->b[0][7] ^= (y_byte & 0x80) << 0;
P_sB;
s->b[0][7] ^= (y_byte & 0x40) << 1;
P_sB;
s->b[0][7] ^= (y_byte & 0x20) << 2;
P_sB;
s->b[0][7] ^= (y_byte & 0x10) << 3;
P_sB;
s->b[0][7] ^= (y_byte & 0x08) << 4;
P_sB;
s->b[0][7] ^= (y_byte & 0x04) << 5;
P_sB;
s->b[0][7] ^= (y_byte & 0x02) << 6;
P_sB;
s->b[0][7] ^= (y_byte & 0x01) << 7;
if (i != 15)
{
P_sB;
y += 1;
}
}
// Squeeze K*
P_sK;
out->x[0] = s->x[0];
out->x[1] = s->x[1];
if (outlen > 16)
{
out->x[2] = s->x[2];
}
}
/******************************************************************************/
/* ISAP_MAC */
/******************************************************************************/
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, uint64_t adlen,
const uint8_t *c, uint64_t clen,
uint8_t *tag)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[1] = U64TOWORD(*(lane_t *)(npub + 8));
s->l[2] = U64TOWORD(*(lane_t *)(ISAP_IV_A + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb associated data
ABSORB_LANES(s, ad, adlen);
// Domain seperation
s->w[4][0] ^= 0x1UL;
// Absorb ciphertext
ABSORB_LANES(s, c, clen);
// Needed for LR tag comparison
s0 = s->x[0];
s1 = s->x[1];
// Derive KA*
s->l[0] = WORDTOU64(s->l[0]);
s->l[1] = WORDTOU64(s->l[1]);
isap_rk(k, ISAP_IV_KA, (const uint8_t *)(s->b), s, CRYPTO_KEYBYTES);
// Squeeze tag
P_sH;
lane_t t0 = WORDTOU64(s->l[0]);
memcpy(tag + 0, t0.b, 8);
t0 = WORDTOU64(s->l[1]);
memcpy(tag + 8, t0.b, 8);
}
/******************************************************************************/
/* Leakage resilient tag comparison. */
/* Similar to Fig.3 of https://eprint.iacr.org/2021/402.pdf. */
/******************************************************************************/
int pvp(
const uint8_t *T, const uint8_t *T_star)
{
state_t state;
state_t *s = &state;
// Calculate U
s->l[0] = U64TOWORD(*(lane_t *)(T + 0));
s->l[1] = U64TOWORD(*(lane_t *)(T + 8));
s->x[2] = s0;
s->x[3] = s1;
s->x[4] = 0;
P_PVP;
uint64_t u0, u1;
u0 = s->x[0];
u1 = s->x[1];
// Calculate U'
s->l[0] = U64TOWORD(*(lane_t *)(T_star + 0));
s->l[1] = U64TOWORD(*(lane_t *)(T_star + 8));
s->x[2] = s0;
s->x[3] = s1;
s->x[4] = 0;
P_PVP;
// Compare tag
int eq_cnt = 0;
for (size_t i = 0; i < 8; i++)
{
eq_cnt += (s->b[0][i] == ((uint8_t *)&u0)[i]);
}
for (size_t i = 0; i < 8; i++)
{
eq_cnt += (s->b[1][i] == ((uint8_t *)&u1)[i]);
}
return eq_cnt;
}
/******************************************************************************/
/* ISAP_ENC */
/******************************************************************************/
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, uint64_t mlen,
uint8_t *c)
{
state_t state;
state_t *s = &state;
// Init state
isap_rk(k, ISAP_IV_KE, npub, s, ISAP_STATE_SZ - CRYPTO_NPUBBYTES);
s->l[3] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[4] = U64TOWORD(*(lane_t *)(npub + 8));
while (mlen >= ISAP_rH / 8)
{
// Encrypt full lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)c = *(uint64_t *)m ^ t0.x;
mlen -= ISAP_rH / 8;
m += ISAP_rH / 8;
c += ISAP_rH / 8;
}
if (mlen > 0)
{
// Encrypt partial lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
for (uint8_t i = 0; i < mlen; i++)
{
*c = *m ^ t0.b[i];
m += 1;
c += 1;
}
}
}
/******************************************************************************/
/* Ascon-Hash */
/******************************************************************************/
#if ENABLE_HASH == 1
int crypto_hash(uint8_t *out, const uint8_t *in, unsigned long long inlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(ASCON_HASH_IV + 0));
s->x[1] = 0;
s->x[2] = 0;
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb input
ABSORB_LANES(s, in, inlen);
for (size_t i = 0; i < 4; i++)
{
// Squeeze full lanes
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)(out + 8 * i) = t0.x;
if (i < 3)
{
P_sH;
}
}
return 0;
}
#endif
#ifndef ISAP_H
#define ISAP_H
#include <inttypes.h>
// Rate in bits
#define ISAP_rH 64
#define ISAP_rB 1
// Number of rounds
#define ISAP_sH 12
#define ISAP_sB 1
#define ISAP_sE 6
#define ISAP_sK 12
// State size in bytes
#define ISAP_STATE_SZ 40
// Size of rate in bytes
#define ISAP_rH_SZ ((ISAP_rH + 7) / 8)
// Size of zero truncated IV in bytes
#define ISAP_IV_SZ 8
// Size of tag in bytes
#define ISAP_TAG_SZ 16
// Security level
#define ISAP_K 128
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, const uint64_t adlen,
const uint8_t *c, const uint64_t clen,
uint8_t *tag);
int pvp(
const unsigned char *T,
const unsigned char *T_star);
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, const uint64_t mlen,
uint8_t *c);
#endif
#ifndef API_H
#define API_H
// isapa128a
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
// asconhashv12
#define CRYPTO_BYTES 32
#define ASCON_HASH_OUTLEN 32
#define ASCON_HASH_ROUNDS 12
#endif
#ifndef ASCONP_H
#define ASCONP_H
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) interleave8(U64BIG(x))
#define WORDTOU64(x) U64BIG(interleave8(x))
/* ---------------------------------------------------------------- */
#define TOBI(x) interleave8(x)
#define FROMBI(x) interleave8(x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
forceinline uint8_t ROR8(uint8_t a, int n) { return a >> n | a << (8 - n); }
/* ---------------------------------------------------------------- */
forceinline uint64_t ROR(uint64_t x, int n)
{
lane_t b, a = {.x = x};
b.b[0] = ROR8(a.b[(n + 0) & 0x7], (n + 0) >> 3);
b.b[1] = ROR8(a.b[(n + 1) & 0x7], (n + 1) >> 3);
b.b[2] = ROR8(a.b[(n + 2) & 0x7], (n + 2) >> 3);
b.b[3] = ROR8(a.b[(n + 3) & 0x7], (n + 3) >> 3);
b.b[4] = ROR8(a.b[(n + 4) & 0x7], (n + 4) >> 3);
b.b[5] = ROR8(a.b[(n + 5) & 0x7], (n + 5) >> 3);
b.b[6] = ROR8(a.b[(n + 6) & 0x7], (n + 6) >> 3);
b.b[7] = ROR8(a.b[(n + 7) & 0x7], (n + 7) >> 3);
return b.x;
}
/* ---------------------------------------------------------------- */
/* credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */
forceinline lane_t interleave8(lane_t x)
{
x.x = (x.x & 0xaa55aa55aa55aa55ull) | ((x.x & 0x00aa00aa00aa00aaull) << 7) |
((x.x >> 7) & 0x00aa00aa00aa00aaull);
x.x = (x.x & 0xcccc3333cccc3333ull) | ((x.x & 0x0000cccc0000ccccull) << 14) |
((x.x >> 14) & 0x0000cccc0000ccccull);
x.x = (x.x & 0xf0f0f0f00f0f0f0full) | ((x.x & 0x00000000f0f0f0f0ull) << 28) |
((x.x >> 28) & 0x00000000f0f0f0f0ull);
return x;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint64_t C)
{
uint64_t xtemp;
/* 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];
xtemp = s->x[0] & ~s->x[4];
s->x[0] ^= s->x[2] & ~s->x[1];
s->x[2] ^= s->x[4] & ~s->x[3];
s->x[4] ^= s->x[1] & ~s->x[0];
s->x[1] ^= s->x[3] & ~s->x[2];
s->x[3] ^= xtemp;
s->x[1] ^= s->x[0];
s->x[3] ^= s->x[2];
s->x[0] ^= s->x[4];
/* linear layer */
xtemp = s->x[0] ^ ROR(s->x[0], 28 - 19);
s->x[0] ^= ROR(xtemp, 19);
xtemp = s->x[1] ^ ROR(s->x[1], 61 - 39);
s->x[1] ^= ROR(xtemp, 39);
xtemp = s->x[2] ^ ROR(s->x[2], 6 - 1);
s->x[2] ^= ROR(xtemp, 1);
xtemp = s->x[3] ^ ROR(s->x[3], 17 - 10);
s->x[3] ^= ROR(xtemp, 10);
xtemp = s->x[4] ^ ROR(s->x[4], 41 - 7);
s->x[4] ^= ROR(xtemp, 7);
s->x[2] = ~s->x[2];
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0x0101010100000000ull);
ROUND(s, 0x0101010000000001ull);
ROUND(s, 0x0101000100000100ull);
ROUND(s, 0x0101000000000101ull);
ROUND(s, 0x0100010100010000ull);
ROUND(s, 0x0100010000010001ull);
case 6:
ROUND(s, 0x0100000100010100ull);
ROUND(s, 0x0100000000010101ull);
ROUND(s, 0x0001010101000000ull);
ROUND(s, 0x0001010001000001ull);
ROUND(s, 0x0001000101000100ull);
default:
ROUND(s, 0x0001000001000101ull);
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
#include "api.h"
#include "isap.h"
#include "crypto_aead.h"
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
){
(void)nsec;
// Ciphertext length is mlen + tag length
*clen = mlen+ISAP_TAG_SZ;
// Encrypt plaintext
if (mlen > 0) {
isap_enc(k,npub,m,mlen,c);
}
// Generate tag
unsigned char *tag = c+mlen;
isap_mac(k,npub,ad,adlen,c,mlen,tag);
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
){
(void)nsec;
// Plaintext length is clen - tag length
*mlen = clen-ISAP_TAG_SZ;
// Generate tag
unsigned char tag[ISAP_TAG_SZ];
isap_mac(k,npub,ad,adlen,c,*mlen,tag);
// Compare tag
unsigned long eq_cnt = 0;
for(unsigned int i = 0; i < ISAP_TAG_SZ; i++) {
eq_cnt += (tag[i] == c[(*mlen)+i]);
}
// Perform decryption if tag is correct
if(eq_cnt == (unsigned long)ISAP_TAG_SZ){
if (*mlen > 0) {
isap_enc(k,npub,c,*mlen,m);
}
return 0;
} else {
return -1;
}
}
#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 <string.h>
#include <inttypes.h>
#include "api.h"
#include "isap.h"
#include "asconp.h"
#include "config.h"
forceinline void ABSORB_LANES(state_t *s, const uint8_t *src, uint64_t len)
{
while (len >= 8)
{
// Absorb full lanes
lane_t t0 = U64TOWORD(*(lane_t *)(src + 0));
s->x[0] ^= t0.x;
len -= ISAP_rH / 8;
src += ISAP_rH / 8;
P_sH;
}
if (len > 0)
{
// Absorb partial lane and padding
size_t i;
lane_t t0 = {0};
for (i = 0; i < len; i++)
{
t0.b[7 - i] ^= *src;
src++;
}
t0.b[7 - i] ^= 0x80;
t0 = TOBI(t0);
s->x[0] ^= t0.x;
P_sH;
}
else
{
// Absorb padded empty lane
s->b[0][7] ^= 0x80;
P_sH;
}
}
/******************************************************************************/
/* ISAP_RK */
/******************************************************************************/
void isap_rk(
const uint8_t *k,
const uint8_t *iv,
const uint8_t *y,
state_t *out,
const size_t outlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(k + 0));
s->l[1] = U64TOWORD(*(lane_t *)(k + 8));
s->l[2] = U64TOWORD(*(lane_t *)(iv + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sK;
// Absorb Y, bit by bit
for (size_t i = 0; i < 16; i++)
{
uint8_t y_byte = *y;
s->b[0][7] ^= (y_byte & 0x80) << 0;
P_sB;
s->b[0][7] ^= (y_byte & 0x40) << 1;
P_sB;
s->b[0][7] ^= (y_byte & 0x20) << 2;
P_sB;
s->b[0][7] ^= (y_byte & 0x10) << 3;
P_sB;
s->b[0][7] ^= (y_byte & 0x08) << 4;
P_sB;
s->b[0][7] ^= (y_byte & 0x04) << 5;
P_sB;
s->b[0][7] ^= (y_byte & 0x02) << 6;
P_sB;
s->b[0][7] ^= (y_byte & 0x01) << 7;
if (i != 15)
{
P_sB;
y += 1;
}
}
// Squeeze K*
P_sK;
out->x[0] = s->x[0];
out->x[1] = s->x[1];
if (outlen > 16)
{
out->x[2] = s->x[2];
}
}
/******************************************************************************/
/* ISAP_MAC */
/******************************************************************************/
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, uint64_t adlen,
const uint8_t *c, uint64_t clen,
uint8_t *tag)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[1] = U64TOWORD(*(lane_t *)(npub + 8));
s->l[2] = U64TOWORD(*(lane_t *)(ISAP_IV_A + 0));
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb associated data
ABSORB_LANES(s, ad, adlen);
// Domain seperation
s->w[4][0] ^= 0x1UL;
// Absorb ciphertext
ABSORB_LANES(s, c, clen);
// Derive KA*
s->l[0] = WORDTOU64(s->l[0]);
s->l[1] = WORDTOU64(s->l[1]);
isap_rk(k, ISAP_IV_KA, (const uint8_t *)(s->b), s, CRYPTO_KEYBYTES);
// Squeeze tag
P_sH;
lane_t t0 = WORDTOU64(s->l[0]);
memcpy(tag + 0, t0.b, 8);
t0 = WORDTOU64(s->l[1]);
memcpy(tag + 8, t0.b, 8);
}
/******************************************************************************/
/* ISAP_ENC */
/******************************************************************************/
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, uint64_t mlen,
uint8_t *c)
{
state_t state;
state_t *s = &state;
// Init state
isap_rk(k, ISAP_IV_KE, npub, s, ISAP_STATE_SZ - CRYPTO_NPUBBYTES);
s->l[3] = U64TOWORD(*(lane_t *)(npub + 0));
s->l[4] = U64TOWORD(*(lane_t *)(npub + 8));
while (mlen >= ISAP_rH / 8)
{
// Encrypt full lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)c = *(uint64_t *)m ^ t0.x;
mlen -= ISAP_rH / 8;
m += ISAP_rH / 8;
c += ISAP_rH / 8;
}
if (mlen > 0)
{
// Encrypt partial lanes
P_sE;
lane_t t0 = WORDTOU64(s->l[0]);
for (uint8_t i = 0; i < mlen; i++)
{
*c = *m ^ t0.b[i];
m += 1;
c += 1;
}
}
}
/******************************************************************************/
/* Ascon-Hash */
/******************************************************************************/
#if ENABLE_HASH == 1
int crypto_hash(uint8_t *out, const uint8_t *in, unsigned long long inlen)
{
state_t state;
state_t *s = &state;
// Initialize
s->l[0] = U64TOWORD(*(lane_t *)(ASCON_HASH_IV + 0));
s->x[1] = 0;
s->x[2] = 0;
s->x[3] = 0;
s->x[4] = 0;
P_sH;
// Absorb input
ABSORB_LANES(s, in, inlen);
for (size_t i = 0; i < 4; i++)
{
// Squeeze full lanes
lane_t t0 = WORDTOU64(s->l[0]);
*(uint64_t *)(out + 8 * i) = t0.x;
if (i < 3)
{
P_sH;
}
}
return 0;
}
#endif
#ifndef ISAP_H
#define ISAP_H
#include <inttypes.h>
// Rate in bits
#define ISAP_rH 64
#define ISAP_rB 1
// Number of rounds
#define ISAP_sH 12
#define ISAP_sB 1
#define ISAP_sE 6
#define ISAP_sK 12
// State size in bytes
#define ISAP_STATE_SZ 40
// Size of rate in bytes
#define ISAP_rH_SZ ((ISAP_rH + 7) / 8)
// Size of zero truncated IV in bytes
#define ISAP_IV_SZ 8
// Size of tag in bytes
#define ISAP_TAG_SZ 16
// Security level
#define ISAP_K 128
void isap_mac(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *ad, const uint64_t adlen,
const uint8_t *c, const uint64_t clen,
uint8_t *tag);
void isap_enc(
const uint8_t *k,
const uint8_t *npub,
const uint8_t *m, const uint64_t mlen,
uint8_t *c);
#endif
#ifndef API_H #ifndef API_H
#define API_H #define API_H
#define CRYPTO_VERSION "2.0.1" // isapa128a
#define CRYPTO_KEYBYTES 16 #define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0 #define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16 #define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16 #define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1 #define CRYPTO_NOOVERLAP 1
// asconhashv12
#define CRYPTO_BYTES 32
#define ASCON_HASH_OUTLEN 32
#define ASCON_HASH_ROUNDS 12
#endif #endif
...@@ -2,139 +2,122 @@ ...@@ -2,139 +2,122 @@
#define ASCONP_H_ #define ASCONP_H_
#include <inttypes.h> #include <inttypes.h>
#include "forceinline.h"
typedef unsigned char u8; typedef union
typedef uint32_t u32; {
typedef unsigned long long u64; uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef struct typedef union
{ {
u32 e; lane_t l[5];
u32 o; uint64_t x[5];
} u32_2; uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH P12ROUNDS(s)
#define P_sB P1ROUNDS(s)
#define P_sE P6ROUNDS(s)
#define P_sK P12ROUNDS(s)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
/* ---------------------------------------------------------------- */
// Round constants, bit-interleaved #define TOBI(x) (x)
u32 rc_o[12] = {0xc, 0xc, 0x9, 0x9, 0xc, 0xc, 0x9, 0x9, 0x6, 0x6, 0x3, 0x3}; #define FROMBI(x) (x)
u32 rc_e[12] = {0xc, 0x9, 0xc, 0x9, 0x6, 0x3, 0x6, 0x3, 0xc, 0x9, 0xc, 0x9};
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
u64 U64BIG(u64 x) forceinline lane_t U64BIG(lane_t x)
{ {
return ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | (((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | (((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)); (((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
} }
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 forceinline void ROUND(state_t *s, uint8_t C)
void to_bit_interleaving(u32_2 *out, u64 in)
{ {
u32 hi = (in) >> 32; uint64_t xtemp;
u32 lo = (u32)(in); /* round constant */
u32 r0, r1; s->x[2] ^= C;
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); /* s-box layer */
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); s->x[0] ^= s->x[4];
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); s->x[4] ^= s->x[3];
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); s->x[2] ^= s->x[1];
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); xtemp = s->x[0] & ~s->x[4];
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); s->x[0] ^= s->x[2] & ~s->x[1];
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); s->x[2] ^= s->x[4] & ~s->x[3];
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); s->x[4] ^= s->x[1] & ~s->x[0];
(*out).e = (lo & 0x0000FFFF) | (hi << 16); s->x[1] ^= s->x[3] & ~s->x[2];
(*out).o = (lo >> 16) | (hi & 0xFFFF0000); s->x[3] ^= xtemp;
s->x[1] ^= s->x[0];
s->x[3] ^= s->x[2];
s->x[0] ^= s->x[4];
s->x[2] = ~s->x[2];
/* linear layer */
s->x[0] ^=
(s->x[0] >> 19) ^ (s->x[0] << 45) ^ (s->x[0] >> 28) ^ (s->x[0] << 36);
s->x[1] ^=
(s->x[1] >> 61) ^ (s->x[1] << 3) ^ (s->x[1] >> 39) ^ (s->x[1] << 25);
s->x[2] ^=
(s->x[2] >> 1) ^ (s->x[2] << 63) ^ (s->x[2] >> 6) ^ (s->x[2] << 58);
s->x[3] ^=
(s->x[3] >> 10) ^ (s->x[3] << 54) ^ (s->x[3] >> 17) ^ (s->x[3] << 47);
s->x[4] ^=
(s->x[4] >> 7) ^ (s->x[4] << 57) ^ (s->x[4] >> 41) ^ (s->x[4] << 23);
} }
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 forceinline void P12ROUNDS(state_t *s)
void from_bit_interleaving(u64 *out, u32_2 in)
{ {
u32 lo = ((in).e & 0x0000FFFF) | ((in).o << 16); ROUND(s, 0xf0);
u32 hi = ((in).e >> 16) | ((in).o & 0xFFFF0000); ROUND(s, 0xe1);
u32 r0, r1; ROUND(s, 0xd2);
r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); ROUND(s, 0xc3);
r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); ROUND(s, 0xb4);
r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); ROUND(s, 0xa5);
r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); ROUND(s, 0x96);
r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); ROUND(s, 0x87);
r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); ROUND(s, 0x78);
r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); ROUND(s, 0x69);
r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); ROUND(s, 0x5a);
*out = (u64)hi << 32 | lo; ROUND(s, 0x4b);
} }
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
#define ROTR32(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) forceinline void P6ROUNDS(state_t *s)
{
ROUND(s, 0x96);
ROUND(s, 0x87);
ROUND(s, 0x78);
ROUND(s, 0x69);
ROUND(s, 0x5a);
ROUND(s, 0x4b);
}
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
void static inline PX(u32 rounds, u32_2* x0, u32_2* x1, u32_2* x2, u32_2* x3, u32_2* x4) { forceinline void P1ROUNDS(state_t *s)
u32_2 t0, t1, t2, t3, t4; {
for (u32 r = 12 - rounds; r < 12; r++){ ROUND(s, 0x4b);
/* rcon */
(*x2).e ^= rc_e[r];
(*x2).o ^= rc_o[r];
/* non-linear layer */
(*x0).e ^= (*x4).e;
(*x0).o ^= (*x4).o;
(*x4).e ^= (*x3).e;
(*x4).o ^= (*x3).o;
(*x2).e ^= (*x1).e;
(*x2).o ^= (*x1).o;
(t0).e = (*x0).e;
(t0).o = (*x0).o;
(t4).e = (*x4).e;
(t4).o = (*x4).o;
(t3).e = (*x3).e;
(t3).o = (*x3).o;
(t1).e = (*x1).e;
(t1).o = (*x1).o;
(t2).e = (*x2).e;
(t2).o = (*x2).o;
(*x0).e = t0.e ^ (~t1.e & t2.e);
(*x0).o = t0.o ^ (~t1.o & t2.o);
(*x2).e = t2.e ^ (~t3.e & t4.e);
(*x2).o = t2.o ^ (~t3.o & t4.o);
(*x4).e = t4.e ^ (~t0.e & t1.e);
(*x4).o = t4.o ^ (~t0.o & t1.o);
(*x1).e = t1.e ^ (~t2.e & t3.e);
(*x1).o = t1.o ^ (~t2.o & t3.o);
(*x3).e = t3.e ^ (~t4.e & t0.e);
(*x3).o = t3.o ^ (~t4.o & t0.o);
(*x1).e ^= (*x0).e;
(*x1).o ^= (*x0).o;
(*x3).e ^= (*x2).e;
(*x3).o ^= (*x2).o;
(*x0).e ^= (*x4).e;
(*x0).o ^= (*x4).o;
/* linear layer */
t0.e = (*x0).e ^ ROTR32((*x0).o, 4);
t0.o = (*x0).o ^ ROTR32((*x0).e, 5);
t1.e = (*x1).e ^ ROTR32((*x1).e, 11);
t1.o = (*x1).o ^ ROTR32((*x1).o, 11);
t2.e = (*x2).e ^ ROTR32((*x2).o, 2);
t2.o = (*x2).o ^ ROTR32((*x2).e, 3);
t3.e = (*x3).e ^ ROTR32((*x3).o, 3);
t3.o = (*x3).o ^ ROTR32((*x3).e, 4);
t4.e = (*x4).e ^ ROTR32((*x4).e, 17);
t4.o = (*x4).o ^ ROTR32((*x4).o, 17);
(*x0).e ^= ROTR32(t0.o, 9);
(*x0).o ^= ROTR32(t0.e, 10);
(*x1).e ^= ROTR32(t1.o, 19);
(*x1).o ^= ROTR32(t1.e, 20);
(*x2).e ^= t2.o;
(*x2).o ^= ROTR32(t2.e, 1);
(*x3).e ^= ROTR32(t3.e, 5);
(*x3).o ^= ROTR32(t3.o, 5);
(*x4).e ^= ROTR32(t4.o, 3);
(*x4).o ^= ROTR32(t4.e, 4);
(*x2).e = ~(*x2).e;
(*x2).o = ~(*x2).o;
}
} }
/* ---------------------------------------------------------------- */
#endif // ASCONP_H_ #endif // ASCONP_H_
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_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_ */
#ifndef ISAP_H #ifndef ISAP_H_
#define ISAP_H #define ISAP_H_
#include <inttypes.h>
// Rate in bits // Rate in bits
#define ISAP_rH 64 #define ISAP_rH 64
...@@ -27,23 +29,16 @@ ...@@ -27,23 +29,16 @@
#define ISAP_K 128 #define ISAP_K 128
void isap_mac( void isap_mac(
const unsigned char *k, const uint8_t *k,
const unsigned char *npub, const uint8_t *npub,
const unsigned char *ad, unsigned long long adlen, const uint8_t *ad, const uint64_t adlen,
const unsigned char *c, unsigned long long clen, const uint8_t *c, const uint64_t clen,
unsigned char *tag); uint8_t *tag);
void isap_rk(
const unsigned char *k,
const unsigned char *iv,
const unsigned char *in,
unsigned char *out,
const unsigned char outlen);
void isap_enc( void isap_enc(
const unsigned char *k, const uint8_t *k,
const unsigned char *npub, const uint8_t *npub,
const unsigned char *m, unsigned long long mlen, const uint8_t *m, const uint64_t mlen,
unsigned char *c); uint8_t *c);
#endif #endif // ISAP_H_
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
/* ---------------------------------------------------------------- */
#define TOBI(x) (x)
#define FROMBI(x) (x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint8_t C)
{
uint64_t xtemp;
/* 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];
xtemp = s->x[0] & ~s->x[4];
s->x[0] ^= s->x[2] & ~s->x[1];
s->x[2] ^= s->x[4] & ~s->x[3];
s->x[4] ^= s->x[1] & ~s->x[0];
s->x[1] ^= s->x[3] & ~s->x[2];
s->x[3] ^= xtemp;
s->x[1] ^= s->x[0];
s->x[3] ^= s->x[2];
s->x[0] ^= s->x[4];
s->x[2] = ~s->x[2];
/* linear layer */
s->x[0] ^=
(s->x[0] >> 19) ^ (s->x[0] << 45) ^ (s->x[0] >> 28) ^ (s->x[0] << 36);
s->x[1] ^=
(s->x[1] >> 61) ^ (s->x[1] << 3) ^ (s->x[1] >> 39) ^ (s->x[1] << 25);
s->x[2] ^=
(s->x[2] >> 1) ^ (s->x[2] << 63) ^ (s->x[2] >> 6) ^ (s->x[2] << 58);
s->x[3] ^=
(s->x[3] >> 10) ^ (s->x[3] << 54) ^ (s->x[3] >> 17) ^ (s->x[3] << 47);
s->x[4] ^=
(s->x[4] >> 7) ^ (s->x[4] << 57) ^ (s->x[4] >> 41) ^ (s->x[4] << 23);
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xf0);
ROUND(s, 0xe1);
ROUND(s, 0xd2);
ROUND(s, 0xc3);
ROUND(s, 0xb4);
ROUND(s, 0xa5);
case 6:
ROUND(s, 0x96);
ROUND(s, 0x87);
ROUND(s, 0x78);
ROUND(s, 0x69);
ROUND(s, 0x5a);
default:
ROUND(s, 0x4b);
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H_
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
../opt_32/crypto_aead.c
\ No newline at end of file
../opt_32/forceinline.h
\ No newline at end of file
../opt_32/api.h
\ No newline at end of file
#ifndef ASCONP_H_
#define ASCONP_H_
#include <inttypes.h>
#include "forceinline.h"
typedef union
{
uint64_t x;
uint32_t w[2];
uint8_t b[8];
} lane_t;
typedef union
{
lane_t l[5];
uint64_t x[5];
uint32_t w[5][2];
uint8_t b[5][8];
} state_t;
/* ---------------------------------------------------------------- */
#define P_sH PROUNDS(s, 12)
#define P_sB PROUNDS(s, 1)
#define P_sE PROUNDS(s, 6)
#define P_sK PROUNDS(s, 12)
#define P_PVP PROUNDS(s, 7)
/* ---------------------------------------------------------------- */
#define U64TOWORD(x) U64BIG(x)
#define WORDTOU64(x) U64BIG(x)
/* ---------------------------------------------------------------- */
#define TOBI(x) (x)
#define FROMBI(x) (x)
/* ---------------------------------------------------------------- */
lane_t U64BIG(lane_t x)
{
x.x = ((((x.x) & 0x00000000000000FFULL) << 56) | (((x.x) & 0x000000000000FF00ULL) << 40) |
(((x.x) & 0x0000000000FF0000ULL) << 24) | (((x.x) & 0x00000000FF000000ULL) << 8) |
(((x.x) & 0x000000FF00000000ULL) >> 8) | (((x.x) & 0x0000FF0000000000ULL) >> 24) |
(((x.x) & 0x00FF000000000000ULL) >> 40) | (((x.x) & 0xFF00000000000000ULL) >> 56));
return x;
}
/* ---------------------------------------------------------------- */
forceinline void ROUND(state_t *s, uint8_t C)
{
uint64_t xtemp;
/* 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];
xtemp = s->x[0] & ~s->x[4];
s->x[0] ^= s->x[2] & ~s->x[1];
s->x[2] ^= s->x[4] & ~s->x[3];
s->x[4] ^= s->x[1] & ~s->x[0];
s->x[1] ^= s->x[3] & ~s->x[2];
s->x[3] ^= xtemp;
s->x[1] ^= s->x[0];
s->x[3] ^= s->x[2];
s->x[0] ^= s->x[4];
s->x[2] = ~s->x[2];
/* linear layer */
s->x[0] ^=
(s->x[0] >> 19) ^ (s->x[0] << 45) ^ (s->x[0] >> 28) ^ (s->x[0] << 36);
s->x[1] ^=
(s->x[1] >> 61) ^ (s->x[1] << 3) ^ (s->x[1] >> 39) ^ (s->x[1] << 25);
s->x[2] ^=
(s->x[2] >> 1) ^ (s->x[2] << 63) ^ (s->x[2] >> 6) ^ (s->x[2] << 58);
s->x[3] ^=
(s->x[3] >> 10) ^ (s->x[3] << 54) ^ (s->x[3] >> 17) ^ (s->x[3] << 47);
s->x[4] ^=
(s->x[4] >> 7) ^ (s->x[4] << 57) ^ (s->x[4] >> 41) ^ (s->x[4] << 23);
}
/* ---------------------------------------------------------------- */
void PROUNDS(state_t *s, uint8_t nr)
{
switch (nr)
{
case 12:
ROUND(s, 0xf0);
ROUND(s, 0xe1);
ROUND(s, 0xd2);
ROUND(s, 0xc3);
ROUND(s, 0xb4);
case 7:
ROUND(s, 0xa5);
case 6:
ROUND(s, 0x96);
ROUND(s, 0x87);
ROUND(s, 0x78);
ROUND(s, 0x69);
ROUND(s, 0x5a);
default:
ROUND(s, 0x4b);
}
}
/* ---------------------------------------------------------------- */
#endif // ASCONP_H_
#ifndef CONFIG_H
#define CONFIG_H
#define ENABLE_HASH 0
#include "isap.h"
// ISAP-A-128a
const uint8_t ISAP_IV_A[] = {0x01, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KA[] = {0x02, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
const uint8_t ISAP_IV_KE[] = {0x03, ISAP_K, ISAP_rH, ISAP_rB, ISAP_sH, ISAP_sB, ISAP_sE, ISAP_sK};
// Ascon-Hash
const uint8_t ASCON_HASH_IV[] = {0x00, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00};
#endif // CONFIG_H
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