Commit 6d6bc5a2 by sebastien riou Committed by Enrico Pozzobon

drygascon128.add_arm-cm0

parent ef5a97bf
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#ifndef __BYTES_UTILS_H__
#define __BYTES_UTILS_H__
#include <stdio.h>
#include <stdint.h>
#include <string.h>
//#ifndef bytes_utiles_printf
//#define bytes_utiles_printf printf
//#endif
#ifndef bytes_utiles_printf
#define bytes_utiles_printf printf
#endif
//replace 0 by .
static void print_diff_byte(uint8_t d, const char *sep){
unsigned int n=d>>4;
if(0==n) bytes_utiles_printf("."); else bytes_utiles_printf("%X",n);
n = d & 0xF;
if(0==n) bytes_utiles_printf("."); else bytes_utiles_printf("%X",n);
bytes_utiles_printf("%s",sep);
}
static void print_diff_bytes_sep(const char *msg,const void *vbuf, unsigned int size, const char *m2, const char *sep){
const uint8_t*const buf = (const uint8_t*const)vbuf;
bytes_utiles_printf("%s",msg);
if(size){
unsigned int i;
for(i=0;i<size-1;i++) print_diff_byte(buf[i],sep);
print_diff_byte(buf[i],"");
}
bytes_utiles_printf("%s", m2);
}
static void print_bytes_sep(const char *msg,const void *vbuf, unsigned int size, const char *m2, const char *sep){
const uint8_t*const buf = (const uint8_t*const)vbuf;
bytes_utiles_printf("%s",msg);
if(size){
unsigned int i;
for(i=0;i<size-1;i++) bytes_utiles_printf("%02X%s",buf[i],sep);
bytes_utiles_printf("%02X",buf[i]);
}
bytes_utiles_printf("%s", m2);
}
static void print_bytes(const char *m,const void *buf, unsigned int size, const char *m2){print_bytes_sep(m,buf,size,m2," ");}
static void println_bytes(const char *m,const void *buf, unsigned int size){print_bytes(m,buf,size,"\n");}
static void print_128(const char *m, const uint8_t a[16], const char *m2){
print_bytes_sep( m,a ,4,"_","");
print_bytes_sep("",a+4 ,4,"_","");
print_bytes_sep("",a+8 ,4,"_","");
print_bytes_sep("",a+12,4,m2 ,"");
}
static void println_128(const char m[], const uint8_t a[16]){print_128(m,a,"\n");}
static void xor_bytes( uint8_t *d, const uint8_t *s, size_t size ){
for(size_t i=0;i<size;i++)
d[i] ^= s[i];
}
static int hexdigit_value(char c){
int nibble = -1;
if(('0'<=c) && (c<='9')) nibble = c-'0';
if(('a'<=c) && (c<='f')) nibble = c-'a' + 10;
if(('A'<=c) && (c<='F')) nibble = c-'A' + 10;
return nibble;
}
static int is_hexdigit(char c){
return -1!=hexdigit_value(c);
}
static size_t hexstr_to_bytes(uint8_t *dst, size_t dst_size, const char *const hexstr){
unsigned int len = strlen(hexstr);
if(dst_size>(len/2))
dst_size = (len/2);
memset(dst,0,dst_size);
for(unsigned int i=0;i<dst_size*2;i++){
unsigned int shift = 4 - 4*(i & 1);
unsigned int charIndex = i;//len-1-i;
char c = hexstr[charIndex];
uint8_t nibble = hexdigit_value(c);
dst[i/2] |= nibble << shift;
}
return dst_size;
}
static void bytes_to_hexstr(char *dst,uint8_t *bytes, unsigned int nBytes){
unsigned int i;
for(i=0;i<nBytes;i++){
sprintf(dst+2*i,"%02X",bytes[i]);
}
}
static size_t cleanup_hexstr(char *hexstr, size_t hexstr_size, char *str, size_t str_size){
size_t cnt=0;
int lastIs0=0;
for(unsigned int j = 0;j<str_size;j++){
char c = str[j];
if(is_hexdigit(c)){
if(cnt==hexstr_size-1){//need final char for null.
printf("Too many hex digits. hexstr=%s\n",hexstr);
hexstr[cnt]=0;
return -1;
}
hexstr[cnt++]=c;
} else if(lastIs0) {
if('x'==c) cnt--;
if('X'==c) cnt--;
}
lastIs0 = '0'==c;
}
hexstr[cnt]=0;
return cnt;
}
static size_t user_hexstr_to_bytes(uint8_t*out, size_t out_size, char *str, size_t str_size){
size_t hexstr_size = cleanup_hexstr(str,str_size,str,str_size);
size_t conv_size = (hexstr_size/2) < out_size ? hexstr_size/2 : out_size;
return hexstr_to_bytes(out,conv_size,str);
}
static void bytes_utils_remove_unused_warnings(void){
(void)println_bytes;
(void)println_128;
(void)xor_bytes;
(void)bytes_to_hexstr;
(void)user_hexstr_to_bytes;
(void)print_diff_bytes_sep;
}
#endif
/**
DryGascon128
Sebastien Riou, January 27th 2019
c99 ref implementation meant to fit in the supercop framework
*/
#ifndef __DRYGASCON128_H__
#define __DRYGASCON128_H__
#define DRYSPONGE_DBG_EN 0
//#define DRYSPONGE_ACCUMULATE_SAFE_AND_SLOW
#define DRYSPONGE_KEYSIZE 16
#define DRYSPONGE_NONCESIZE 16
#define DRYSPONGE_BLOCKSIZE 16
#define DRYSPONGE_CAPACITYSIZE (5*64/8)
#define DRYSPONGE_XSIZE (4*32/8)
//remove one round because Mix does 1 round merely for processing the upper
//2 bits of the domain separator (because 128+4 mod 10 is 2)
#define DRYSPONGE_INIT_ROUNDS (12-1)
#define DRYSPONGE_ROUNDS (8-1)
#define DRYSPONGE_ACCUMULATE_FACTOR 2
#define DRYSPONGE_MPR_INPUT_WIDTH 10
#include "drygascon_le32.h"
#endif
/**
DryGascon_le32
Sebastien Riou, January 6th 2019
c99 little endian 32 bit implementation meant to fit in the supercop framework
*/
#ifndef __DRYGASCON_H__
#define __DRYGASCON_H__
#include <stdint.h>
typedef uint64_t DRYSPONGE_EXT_t;
#define DRYSPONGE_EXT
#include "drysponge_common.h"
//input width for one round of MixPhaseRound
#define DRYSPONGE_MPR_INPUT_MASK ((((uint64_t)1)<<DRYSPONGE_MPR_INPUT_WIDTH)-1)
#define DRYSPONGE_MPR_ROUNDS DRYSPONGE_DIVUP((DRYSPONGE_BLOCKSIZE*8)+4,DRYSPONGE_MPR_INPUT_WIDTH)
#if (DRYSPONGE_MPR_ROUNDS*DRYSPONGE_MPR_INPUT_WIDTH-4)<(DRYSPONGE_BLOCKSIZE*8)
#error "(DRYSPONGE_MPR_ROUNDS*DRYSPONGE_MPR_INPUT_WIDTH-4)<(DRYSPONGE_BLOCKSIZE*8)"
#endif
#if DRYSPONGE_XSIZE32>16
#error "DRYSPONGE_XSIZE32>16"
#endif
#if DRYSPONGE_XSIZE32 == 4
#define DRYSPONGE_X_IDX_WIDTH 2
#endif
#if DRYSPONGE_MPR_INPUT_WIDTH == 10
#define DRYSPONGE_RANK_BYTES 2
typedef uint32_t permut_rank_t;
#endif
#if DRYSPONGE_MPR_INPUT_WIDTH == 18
#define DRYSPONGE_RANK_BYTES 3
typedef uint32_t permut_rank_t;
#endif
#define DRYSPONGE_X_IDX_MASK ((1<<DRYSPONGE_X_IDX_WIDTH)-1)
#ifndef DRYSPONGE_OPT_F
DRYSPONGE_FUNC void DRYSPONGE_DomainSeparator(
DRYSPONGE_EXT_t *const ext,
unsigned int dsinfo
){
*ext = dsinfo;
*ext = *ext<<((DRYSPONGE_BLOCKSIZE*8)%DRYSPONGE_MPR_INPUT_WIDTH);
}
DRYSPONGE_FUNC void DRYSPONGE_MixPhaseRound(
DRYSPONGE_EXT_t ext,
uint64_t *const c64,
uint64_t *const x64,
const uint8_t *const in,
unsigned int bitidx,
unsigned int insize
){
uint32_t *const x32 = (uint32_t*const)x64;
unsigned int bi = bitidx/8;
unsigned int shift = bitidx%8;
permut_rank_t r=0;
uint8_t *rb = (uint8_t*)&r;
for(unsigned int i=0;i<DRYSPONGE_RANK_BYTES;i++){
if(bi+i==insize) break;
rb[i]=in[bi+i];
}
r = (r>>shift) & DRYSPONGE_MPR_INPUT_MASK;
r^=ext;
for(unsigned int j=0;j<DRYSPONGE_CAPACITYSIZE64;j++){
unsigned int i = r & DRYSPONGE_X_IDX_MASK;
r = r >> DRYSPONGE_X_IDX_WIDTH;
c64[j]^=x32[i];
}
}
#endif
struct DRYSPONGE_struct_t;
typedef struct DRYSPONGE_struct_t DRYSPONGE_t ;
DRYSPONGE_FUNC void DRYSPONGE_MixPhase(
DRYSPONGE_t *const ctx,
const uint8_t *const in
);
DRYSPONGE_FUNC void DRYSPONGE_CoreRound(
DRYSPONGE_t *const ctx,
unsigned int r
);
#include "drysponge_le32.h"
#ifndef DRYSPONGE_OPT_F
DRYSPONGE_FUNC void DRYSPONGE_MixPhase(
DRYSPONGE_t *const ctx,
const uint8_t *const in
){
unsigned int bitidx=0;
#if DRYSPONGE_MPR_ROUNDS > 1
for(unsigned int i=0;i<DRYSPONGE_MPR_ROUNDS-1;i++){
#if DRYSPONGE_DBG_EN >= 4
printf("Mix phase MixPhaseRound entry %lu:\n",i);
DRYSPONGE_print_state(ctx);
#endif
DRYSPONGE_EXT_t ext=0;
#if ((DRYSPONGE_MPR_ROUNDS-1)*(DRYSPONGE_MPR_INPUT_WIDTH))>(DRYSPONGE_BLOCKSIZE*8)
if((ctx->ext) && (i==(DRYSPONGE_MPR_ROUNDS-2))){
//DS info is split accross this block and the last one
ext = ctx->ext;
ctx->ext = ctx->ext >> ((DRYSPONGE_BLOCKSIZE*8)%DRYSPONGE_MPR_INPUT_WIDTH);
ctx->ext = ctx->ext >> ((((DRYSPONGE_MPR_ROUNDS-1)*DRYSPONGE_MPR_INPUT_WIDTH))-(DRYSPONGE_BLOCKSIZE*8));
}
#endif
DRYSPONGE_MixPhaseRound(ext,ctx->c,ctx->x,in,bitidx,DRYSPONGE_BLOCKSIZE);
bitidx+=DRYSPONGE_MPR_INPUT_WIDTH;
#if DRYSPONGE_DBG_EN >= 4
printf("Mix phase CoreRound entry %lu:\n",i);
DRYSPONGE_print_state(ctx);
#endif
DRYSPONGE_CoreRound(ctx,0);
}
#endif
#if DRYSPONGE_DBG_EN >= 4
printf("Mix phase MixPhaseRound entry %lu:\n",DRYSPONGE_MPR_ROUNDS-1);
DRYSPONGE_print_state(ctx);
#endif
DRYSPONGE_MixPhaseRound(ctx->ext,ctx->c,ctx->x,in,bitidx,DRYSPONGE_BLOCKSIZE);
ctx->ext=0;
}
#endif
//#ifndef DRYSPONGE_OPT_G //keep for now, needed for key init
DRYSPONGE_FUNC void gascon_sboxes(uint64_t * const x, unsigned int nw){
uint64_t t[DRYSPONGE_CAPACITYSIZE64];
const unsigned int mid = nw/2;
for(unsigned int i=0;i<mid+1;i++){
unsigned int dst = 2*i;
unsigned int src = (nw+dst-1) % nw;
x[dst] ^= x[src];
}
for(unsigned int i=0;i<nw;i++){
t[i] = (x[i] ^ 0xFFFFFFFFFFFFFFFFull) & x[(i+1)%nw];
}
for(unsigned int i=0;i<nw;i++){
x[i] ^= t[(i+1)%nw];
}
for(unsigned int i=0;i<mid+1;i++){
unsigned int src = 2*i;
unsigned int dst = (src+1) % nw;
x[dst] ^= x[src];
}
x[mid] ^= 0XFFFFFFFFFFFFFFFFull;
}
DRYSPONGE_FUNC uint64_t gascon_rotr64_interleaved(uint64_t in, unsigned int shift){
uint32_t i[2];
memcpy(i,&in,sizeof(i));
unsigned int shift2 = shift/2;
if(shift & 1){
uint32_t tmp = DRYSPONGE_ROTR32(i[1],shift2);
i[1] = DRYSPONGE_ROTR32(i[0],(shift2+1)%32);
i[0] = tmp;
}else{
i[0] = DRYSPONGE_ROTR32(i[0],shift2);
i[1] = DRYSPONGE_ROTR32(i[1],shift2);
}
uint64_t out;
memcpy(&out,i,sizeof(i));
return out;
}
DRYSPONGE_FUNC void gascon_add_cst(uint64_t* x, unsigned int round) {
const unsigned int mid = DRYSPONGE_CAPACITYSIZE64 / 2;
unsigned int rounds = 12;
const unsigned int r = 12-rounds+round;
// addition of round constant
x[mid] ^= ((0xfull - r) << 4) | r;
}
DRYSPONGE_FUNC void gascon_lin_layer(uint64_t* x) {
// linear diffusion layer
x[0] ^= gascon_rotr64_interleaved(x[0], 19) ^ gascon_rotr64_interleaved(x[0], 28);
x[1] ^= gascon_rotr64_interleaved(x[1], 61) ^ gascon_rotr64_interleaved(x[1], 38);
x[2] ^= gascon_rotr64_interleaved(x[2], 1) ^ gascon_rotr64_interleaved(x[2], 6);
x[3] ^= gascon_rotr64_interleaved(x[3], 10) ^ gascon_rotr64_interleaved(x[3], 17);
x[4] ^= gascon_rotr64_interleaved(x[4], 7) ^ gascon_rotr64_interleaved(x[4], 40);
#if DRYSPONGE_CAPACITYSIZE64 > 5
x[5] ^= gascon_rotr64_interleaved(x[5], 31) ^ gascon_rotr64_interleaved(x[5], 26);
x[6] ^= gascon_rotr64_interleaved(x[6], 53) ^ gascon_rotr64_interleaved(x[6], 58);
x[7] ^= gascon_rotr64_interleaved(x[7], 9) ^ gascon_rotr64_interleaved(x[7], 46);
x[8] ^= gascon_rotr64_interleaved(x[8], 43) ^ gascon_rotr64_interleaved(x[8], 50);
#endif
}
DRYSPONGE_FUNC void gascon_permutation_round(uint64_t* S, unsigned int round) {
(void)DRYSPONGE_rotr64;
// addition of round constant
gascon_add_cst(S, round);
// substitution layer
gascon_sboxes(S,DRYSPONGE_CAPACITYSIZE64);
// linear diffusion layer
gascon_lin_layer(S);
}
DRYSPONGE_FUNC void DRYSPONGE_CoreRound(
DRYSPONGE_t *const ctx,
unsigned int r
){
gascon_permutation_round(ctx->c, r);
}
#endif
#ifndef __DRYSPONGE_COMMON_H__
#define __DRYSPONGE_COMMON_H__
#ifndef DRYSPONGE_FUNC
#define DRYSPONGE_FUNC inline static
#endif
//convention:
// width means length in bits
// size means length in bytes
#include <stdint.h>
#include <string.h>
#include <assert.h>
#if DRYSPONGE_DBG_EN
#include "bytes_utils.h"
#endif
#define DRYSPONGE_PASS 0
#define DRYSPONGE_DS 2
#define DRYSPONGE_DD 1
#define DRYSPONGE_DA 2
#define DRYSPONGE_DM 3
#define DRYSPONGE_STATESIZE (DRYSPONGE_CAPACITYSIZE+DRYSPONGE_BLOCKSIZE)
#define DRYSPONGE_DIGESTSIZE (DRYSPONGE_KEYSIZE*2)
#define DRYSPONGE_TAGSIZE DRYSPONGE_KEYSIZE
#define DRYSPONGE_KEYMAXSIZE (DRYSPONGE_CAPACITYSIZE+DRYSPONGE_XSIZE)
#define DRYSPONGE_DIVUP(a,b) (((a)+(b)-1)/(b))
#define DRYSPONGE_ROTR32(x,n) (0xFFFFFFFF & (((x)>>(n))|((x)<<(0x1F & (32-(n))))))
#define DRYSPONGE_ROTR64(x,n) (0xFFFFFFFFFFFFFFFF & (((x)>>(n))|((x)<<(0x3F & (64-(n))))))
#define DRYSPONGE_STATESIZE32 DRYSPONGE_DIVUP(DRYSPONGE_STATESIZE,4)
#define DRYSPONGE_CE_SIZE32 DRYSPONGE_DIVUP(DRYSPONGE_CE_SIZE,4)
#define DRYSPONGE_BLOCKSIZE32 DRYSPONGE_DIVUP(DRYSPONGE_BLOCKSIZE,4)
#define DRYSPONGE_CAPACITYSIZE32 DRYSPONGE_DIVUP(DRYSPONGE_CAPACITYSIZE,4)
#define DRYSPONGE_XSIZE32 DRYSPONGE_DIVUP(DRYSPONGE_XSIZE,4)
#define DRYSPONGE_KEYSIZE32 DRYSPONGE_DIVUP(DRYSPONGE_KEYSIZE,4)
#define DRYSPONGE_STATESIZE64 DRYSPONGE_DIVUP(DRYSPONGE_STATESIZE,8)
#define DRYSPONGE_CE_SIZE64 DRYSPONGE_DIVUP(DRYSPONGE_CE_SIZE,8)
#define DRYSPONGE_BLOCKSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_BLOCKSIZE,8)
#define DRYSPONGE_CAPACITYSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_CAPACITYSIZE,8)
#define DRYSPONGE_XSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_XSIZE,8)
#define DRYSPONGE_KEYSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_KEYSIZE,8)
#define DRYSPONGE_TAGSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_TAGSIZE,8)
#define DRYSPONGE_KEYMAXSIZE64 DRYSPONGE_DIVUP(DRYSPONGE_KEYMAXSIZE,8)
#define DRYSPONGE_NONCESIZE64 DRYSPONGE_DIVUP(DRYSPONGE_NONCESIZE,8)
#if DRYSPONGE_NONCESIZE < 12
#error "DRYSPONGE_NONCESIZE < 12"
#endif
#if DRYSPONGE_KEYSIZE < 16
#error "DRYSPONGE_KEYSIZE < 16"
#endif
#if DRYSPONGE_DIGESTSIZE < 2*DRYSPONGE_KEYSIZE
#error "DRYSPONGE_DIGESTSIZE < 2*DRYSPONGE_KEYSIZE"
#endif
#if DRYSPONGE_ACCUMULATE_FACTOR > ((DRYSPONGE_CAPACITYSIZE/4)/DRYSPONGE_BLOCKSIZE32)
#error "DRYSPONGE_ACCUMULATE_FACTOR > ((DRYSPONGE_CAPACITYSIZE/4)/DRYSPONGE_BLOCKSIZE32)"
#endif
#ifdef DRYSPONGE_EXT
#define DRYSPONGE_EXT_ARG (&(ctx->ext))
#else
#define DRYSPONGE_EXT_ARG 0
#endif
DRYSPONGE_FUNC unsigned int DRYSPONGE_DSINFO(unsigned int padded, unsigned int domain, unsigned int finalize){
#if DRYSPONGE_DBG_EN
bytes_utiles_printf(" Adding DS: padded=%d, domain=%u, finalize=%d\n",padded,domain,finalize);
#endif
return padded+(finalize<<1)+(domain<<2);
}
DRYSPONGE_FUNC uint32_t DRYSPONGE_rotr32(uint32_t x, unsigned int n){
assert(n<32);
return DRYSPONGE_ROTR32(x,n);
}
DRYSPONGE_FUNC uint64_t DRYSPONGE_rotr64(uint64_t x, unsigned int n){
assert(n<64);
return DRYSPONGE_ROTR64(x,n);
}
DRYSPONGE_FUNC void DRYSPONGE_xor(
const uint8_t *const a,//exactly one block of input
const uint8_t *const b,
uint8_t *const y
){
for(unsigned int i=0;i<DRYSPONGE_BLOCKSIZE;i++){
y[i] = a[i] ^ b[i];
}
}
DRYSPONGE_FUNC void DRYSPONGE_load16(uint16_t* x, const uint8_t*const in) {
*x = 0;
for(unsigned int i = 0;i<2;i++){
uint16_t b = in[i];
*x = *x | (b<<(8*i));
}
}
DRYSPONGE_FUNC void DRYSPONGE_load32(uint32_t* x, const uint8_t*const in) {
*x = 0;
for(unsigned int i = 0;i<4;i++){
uint32_t b = in[i];
*x = *x | (b<<(8*i));
}
}
DRYSPONGE_FUNC void DRYSPONGE_store32(uint8_t* out, uint32_t x) {
for(unsigned int i = 0;i<4;i++){
out[i] = x >> (8*i);
}
}
DRYSPONGE_FUNC void DRYSPONGE_load64(uint64_t* x, uint8_t* in) {
*x = 0;
for(unsigned int i = 0;i<8;i++){
uint64_t b = in[i];
*x = *x | (b<<(8*i));
}
}
DRYSPONGE_FUNC void DRYSPONGE_store64(uint8_t* out, uint64_t x) {
(void)DRYSPONGE_rotr32;
(void)DRYSPONGE_load16;
(void)DRYSPONGE_store32;
for(unsigned int i = 0;i<8;i++){
out[i] = x >> (8*i);
}
}
#endif
#ifndef __DRYSPONGE_DBG_SUPPORT_H__
#define __DRYSPONGE_DBG_SUPPORT_H__
#define DRYSPONGE_DBG_NONE 0
#define DRYSPONGE_DBG_ALG_IO 1
#define DRYSPONGE_DBG_F_IO 2
#define DRYSPONGE_DBG_ROUND_IO 3
#define DRYSPONGE_DBG_FULL 4
#if DRYSPONGE_DBG_EN
#define DRYSPONGE_DBG(a) a;
#else
#define DRYSPONGE_DBG(a)
#endif
#if DRYSPONGE_DBG_EN
#include <assert.h>
#include <stdio.h>
#include "bytes_utils.h"
static void DRYSPONGE_print_state(
DRYSPONGE_t *const ctx
){
(void)xor_bytes;
(void)println_128;
(void)bytes_utils_remove_unused_warnings;
unsigned int linesize = 32;
if(linesize<DRYSPONGE_BLOCKSIZE) linesize = DRYSPONGE_BLOCKSIZE;
unsigned int remaining = DRYSPONGE_CAPACITYSIZE;
const uint8_t*const c = (const uint8_t*const)ctx->c;
for(unsigned int i=0;i<DRYSPONGE_DIVUP(DRYSPONGE_CAPACITYSIZE,linesize);i++){
bytes_utiles_printf( " C[%2u] = ",i);
unsigned int len = linesize < remaining ? linesize : remaining;
print_bytes_sep("",c+i*linesize,len,"\n","");
remaining -= len;
}
remaining = DRYSPONGE_XSIZE;
const uint8_t*const x = (const uint8_t*const)ctx->x;
for(unsigned int i=0;i<DRYSPONGE_DIVUP(DRYSPONGE_XSIZE,linesize);i++){
bytes_utiles_printf( " X[%2u] = ",i);
unsigned int len = linesize < remaining ? linesize : remaining;
print_bytes_sep("",x+i*linesize,len,"\n","");
remaining -= len;
}
print_bytes_sep(" R = ",ctx->r,DRYSPONGE_BLOCKSIZE,"\n","");
}
#endif
#endif
/**
DrySponge
Sebastien Riou, January 6th 2019
c99 little endian 32 bit implementation meant to fit in the supercop framework
Note: although this is faster than the ref implementation we noticed that it is
still several times slower compared to what can be done with assembly.
*/
#ifndef __DRYSPONGE_H__
#define __DRYSPONGE_H__
#include "drysponge_common.h"
//assume 32bit alignement is enough to access uint64_t since we target 32 bit CPU
#define ALIGN64 4
//#define ALIGN64 8
#ifndef DRYSPONGE_DBG_EN
#define DRYSPONGE_DBG_EN 0
#endif
typedef struct DRYSPONGE_struct_t {
uint64_t c[DRYSPONGE_CAPACITYSIZE64];
uint64_t r[DRYSPONGE_BLOCKSIZE64];
uint64_t x[DRYSPONGE_XSIZE64];
uint8_t *obuf;
uint64_t fcnt;
#ifdef DRYSPONGE_EXT
DRYSPONGE_EXT_t ext;
#endif
unsigned int rounds;
} DRYSPONGE_t;
#include "drysponge_dbg_support.h"
static void DRYSPONGE_xor64(
const uint64_t *const a,//exactly one block of input
const uint64_t *const b,
uint64_t *const y
){
for(unsigned int i=0;i<DRYSPONGE_BLOCKSIZE64;i++){
y[i] = a[i] ^ b[i];
}
}
//static void DRYSPONGE_xor32(
// const uint32_t *const a,//exactly one block of input
// const uint32_t *const b,
// uint32_t *const y
//){
// for(unsigned int i=0;i<DRYSPONGE_BLOCKSIZE32;i++){
// y[i] = a[i] ^ b[i];
// }
//}
#ifdef DRYSPONGE_OPT_G
void drygascon128_g(uint64_t* x, uint32_t rounds);
static void DRYSPONGE_g(
DRYSPONGE_t *const ctx
){
DRYSPONGE_OPT_G((uint64_t*)&(ctx->c),ctx->rounds);
}
#else
static void DRYSPONGE_g(
DRYSPONGE_t *const ctx
){
#if DRYSPONGE_DBG_EN
printf(" G entry %lu:\n",ctx->fcnt);
DRYSPONGE_print_state(ctx);
#endif
ctx->fcnt++;
DRYSPONGE_xor64(ctx->r,ctx->r,ctx->r);//r=0
for(unsigned int j = 0;j<ctx->rounds;j++){
#if DRYSPONGE_DBG_EN >= DRYSPONGE_DBG_ROUND_IO
printf(" CoreRound entry %d:\n",j);
DRYSPONGE_print_state(ctx);
#endif
DRYSPONGE_CoreRound(ctx,j);
uint32_t r32[DRYSPONGE_BLOCKSIZE32];
uint32_t cpart[DRYSPONGE_BLOCKSIZE32];
memcpy(r32,ctx->r,sizeof(r32));
for(unsigned int k=0;k<DRYSPONGE_ACCUMULATE_FACTOR;k++){
memcpy(cpart,ctx->c+k*DRYSPONGE_BLOCKSIZE64,sizeof(cpart));
for(unsigned int i=0;i<DRYSPONGE_BLOCKSIZE32;i++){
r32[i]^=cpart[(i+k)%DRYSPONGE_BLOCKSIZE32];
}
}
memcpy(ctx->r,r32,sizeof(r32));
}
}
#endif
#ifdef DRYSPONGE_OPT_F
static void DRYSPONGE_DomainSeparator(
DRYSPONGE_EXT_t *const ext,
unsigned int dsinfo
){
*ext = dsinfo;
}
void drygascon128_f(uint64_t* x, uint32_t*in,uint32_t ds,uint32_t rounds);
static void DRYSPONGE_f(
DRYSPONGE_t *const ctx,
const uint8_t *const i
){
DRYSPONGE_OPT_F((uint64_t*)&(ctx->c),(uint32_t*)i,(uint32_t)ctx->ext,ctx->rounds);
ctx->ext=0;
}
#else
static void DRYSPONGE_f(
DRYSPONGE_t *const ctx,
const uint8_t *const i
){
#if DRYSPONGE_DBG_EN
printf(" F entry %lu:\n",ctx->fcnt);
DRYSPONGE_print_state(ctx);
print_bytes_sep(" I = ",i,DRYSPONGE_BLOCKSIZE,"\n","");
#endif
DRYSPONGE_MixPhase(ctx,i);
#if DRYSPONGE_DBG_EN >= DRYSPONGE_DBG_ROUND_IO
printf(" After mix phase:\n");
DRYSPONGE_print_state(ctx);
#endif
DRYSPONGE_g(ctx);
}
#endif
static void DRYSPONGE_set_key(
DRYSPONGE_t *const ctx,
const uint8_t *const key,
const unsigned int keylen
){
assert(DRYSPONGE_KEYSIZE<=keylen);
const unsigned int midkeysize = DRYSPONGE_KEYSIZE+DRYSPONGE_XSIZE;
const unsigned int fullkeysize = DRYSPONGE_CAPACITYSIZE+DRYSPONGE_XSIZE;
if(DRYSPONGE_KEYSIZE!=keylen){//all words for x assumed to be different
if(fullkeysize == keylen){
memcpy(ctx->c,key,DRYSPONGE_CAPACITYSIZE);
memcpy(ctx->x,key+DRYSPONGE_CAPACITYSIZE,DRYSPONGE_XSIZE);
} else {
uint8_t c[DRYSPONGE_CAPACITYSIZE];
uint8_t x[DRYSPONGE_XSIZE];
assert(midkeysize==keylen);
for(unsigned int i=0;i<DRYSPONGE_CAPACITYSIZE;i++){
c[i] = key[i%DRYSPONGE_KEYSIZE];
}
for(unsigned int i=0;i<DRYSPONGE_XSIZE;i++){
x[i] = key[DRYSPONGE_KEYSIZE+i];
}
memcpy(ctx->c,c,DRYSPONGE_CAPACITYSIZE);
memcpy(ctx->x,x,DRYSPONGE_XSIZE);
}
}else{
uint8_t c[DRYSPONGE_CAPACITYSIZE];
for(unsigned int i=0;i<DRYSPONGE_CAPACITYSIZE;i++){
c[i] = key[i%DRYSPONGE_KEYSIZE];
}
memcpy(ctx->c,c,DRYSPONGE_CAPACITYSIZE);
DRYSPONGE_CoreRound(ctx,0);
//need to fixup x such that all words are different
unsigned int modified=1;
while(modified){
uint32_t c32[DRYSPONGE_CAPACITYSIZE32];
memcpy(c32,ctx->c,DRYSPONGE_CAPACITYSIZE);
modified=0;
for(unsigned int i=0;i<DRYSPONGE_XSIZE32-1;i++){
for(unsigned int j=i+1;j<DRYSPONGE_XSIZE32;j++){
if(c32[i]==c32[j]){
DRYSPONGE_CoreRound(ctx,0);
modified=1;
break;
}
}
if(modified) break;
}
}
memcpy(ctx->x,ctx->c,DRYSPONGE_XSIZE);
memcpy(ctx->c,key,DRYSPONGE_XSIZE);
}
uint32_t x32[DRYSPONGE_XSIZE32];// = (uint32_t *const)ctx->x;
memcpy(x32,ctx->x,DRYSPONGE_XSIZE);
//sanity check: all words in x shall be different
for(unsigned int i=0;i<DRYSPONGE_XSIZE32-1;i++){
for(unsigned int j=i+1;j<DRYSPONGE_XSIZE32;j++){
assert(x32[i]!=x32[j]);
}
}
}
static unsigned int DRYSPONGE_padding(
const uint8_t *const ib,//one block of input or less
uintptr_t iblen,
uint8_t *const ob//exactly one block
){
assert(iblen<=DRYSPONGE_BLOCKSIZE);
memcpy(ob,ib,iblen);
unsigned int padded = 0;
if(iblen<DRYSPONGE_BLOCKSIZE){
ob[iblen] = 0x01;
if(iblen+1<DRYSPONGE_BLOCKSIZE){
memset(ob+iblen+1,0,DRYSPONGE_BLOCKSIZE-iblen-1);
}
padded = 1;
}
return padded;
}
static void DRYSPONGE_absorb_only(
DRYSPONGE_t *const ctx,
const uint8_t *const ad,
size_t alen,
unsigned int ds,
unsigned int finalize
){
const uint8_t *iad = ad;
size_t a = (alen + DRYSPONGE_BLOCKSIZE - 1) / DRYSPONGE_BLOCKSIZE;
if(a){
for(size_t i = 0; i<a-1; i++){//process all blocks except last one
DRYSPONGE_f(ctx,iad);
iad+=DRYSPONGE_BLOCKSIZE;
}
}
uint8_t last_block[DRYSPONGE_BLOCKSIZE];
uintptr_t remaining = ad+alen-iad;
uint8_t apad = DRYSPONGE_padding(iad,remaining,last_block);
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(apad,ds,finalize));
DRYSPONGE_f(ctx,last_block);
}
static void DRYSPONGE_squeez_only(
DRYSPONGE_t *const ctx,
uint8_t *out,
unsigned int remaining
){
while(remaining){
unsigned int len = remaining > DRYSPONGE_BLOCKSIZE ? DRYSPONGE_BLOCKSIZE : remaining;
memcpy(out,ctx->r,len);
out+=len;
remaining-=len;
if(remaining){
DRYSPONGE_g(ctx);
}
}
}
static void DRYSPONGE_init_ctx(
DRYSPONGE_t *const ctx
){
#ifdef DRYSPONGE_EXT
memset(DRYSPONGE_EXT_ARG,0,sizeof(DRYSPONGE_EXT_t));
#endif
ctx->fcnt=0;
memset(ctx->r,0x00,DRYSPONGE_BLOCKSIZE);
}
static void DRYSPONGE_hash(
const uint8_t *const message,
const size_t mlen,
uint8_t *const digest
){
DRYSPONGE_t ctx_storage;
DRYSPONGE_t *const ctx = &ctx_storage;
DRYSPONGE_init_ctx(ctx);
ctx->rounds=DRYSPONGE_ROUNDS;
#if DRYSPONGE_DBG_EN
printf("Hashing %lu bytes message: ",mlen);
print_bytes_sep("",message,mlen,"\n","");
#endif
const uint64_t CST_H[] = {
0xd308a385886a3f24,
0x447370032e8a1913,
0xd0319f29223809a4,
0x896c4eec98fa2e08,
0x7713d038e6212845,
0x6c0ce934cf6654be,
0xdd507cc9b729acc0,
0x170947b5b5d5843f,
0x1bfb7989d9d51692,
0xacb5df98a60b31d1,
0xb7df1ad0db72fd2f,
0x967e266aedafe1b8,
0x997f2cf145907cba,
0xf76c91b34799a124,
0x16fc8e85e2f20108,
0x694e5771d8206963,
};
DRYSPONGE_set_key(ctx,(const uint8_t*)CST_H,DRYSPONGE_KEYSIZE+DRYSPONGE_XSIZE);
DRYSPONGE_absorb_only(ctx,message,mlen,DRYSPONGE_DS,1);
DRYSPONGE_squeez_only(ctx,digest,DRYSPONGE_DIGESTSIZE);
#if DRYSPONGE_DBG_EN
printf(" Final state:\n");
DRYSPONGE_print_state(ctx);
print_bytes_sep(" Digest: ",digest,DRYSPONGE_DIGESTSIZE,"\n","");
#endif
}
static void DRYSPONGE_init(
DRYSPONGE_t *const ctx,
const uint8_t *const key,
const unsigned int klen,
const uint8_t *const nonce,
uint8_t *out_buffer,//output buffer
unsigned int finalize
){
DRYSPONGE_init_ctx(ctx);
ctx->rounds=DRYSPONGE_ROUNDS;
DRYSPONGE_set_key(ctx,key,klen);
ctx->obuf = out_buffer;
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(0,DRYSPONGE_DD,finalize));
ctx->rounds=DRYSPONGE_INIT_ROUNDS;
#if DRYSPONGE_NONCESIZE>DRYSPONGE_BLOCKSIZE
assert(0==(DRYSPONGE_NONCESIZE%DRYSPONGE_BLOCKSIZE));
unsigned int nloops = DRYSPONGE_DIVUP(DRYSPONGE_NONCESIZE,DRYSPONGE_BLOCKSIZE);
for(unsigned int i=0;i<nloops-1;i++){
DRYSPONGE_f(ctx,nonce+i*DRYSPONGE_BLOCKSIZE);
}
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(0,DRYSPONGE_DD,finalize));
DRYSPONGE_f(ctx,nonce+(nloops-1)*DRYSPONGE_BLOCKSIZE);
#else
uint8_t block[DRYSPONGE_BLOCKSIZE] = {0};
memcpy(block,nonce,DRYSPONGE_NONCESIZE);
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(0,DRYSPONGE_DD,finalize));
DRYSPONGE_f(ctx,block);
#endif
ctx->rounds=DRYSPONGE_ROUNDS;
}
static void DRYSPONGE_enc_core(
DRYSPONGE_t *const ctx,
const uint64_t *const ib//exactly one block of input
){
DRYSPONGE_xor((uint8_t *)ctx->r,(uint8_t *)ib,ctx->obuf);
DRYSPONGE_f(ctx,(uint8_t *)ib);
ctx->obuf+=DRYSPONGE_BLOCKSIZE;
}
static void DRYSPONGE_enc_core_aligned(
DRYSPONGE_t *const ctx,
const uint64_t *const ib//exactly one block of input
){
assert((((uintptr_t)ctx->obuf)%8) == 0);
DRYSPONGE_xor64(ctx->r,ib,(uint64_t*const)ctx->obuf);
DRYSPONGE_f(ctx,(uint8_t *)ib);
ctx->obuf+=DRYSPONGE_BLOCKSIZE;
}
static const uint8_t* DRYSPONGE_enc_blocks(
DRYSPONGE_t *const ctx,
const uint8_t *im,//whole message
size_t m
){
(void)DRYSPONGE_load32;
(void)DRYSPONGE_store32;
(void)DRYSPONGE_load64;
(void)DRYSPONGE_store64;
uint64_t buf64[DRYSPONGE_BLOCKSIZE64];
const uint64_t *ib64;
#if DRYSPONGE_BLOCKSIZE % ALIGN64
unsigned int input_aligned = 0;
unsigned int output_aligned = 0;
#else
unsigned int input_aligned = 0==(((uintptr_t)im)%ALIGN64);
unsigned int output_aligned = 0==(((uintptr_t)ctx->obuf)%ALIGN64);
#endif
if(input_aligned && output_aligned){
for(size_t i = 0; i<m; i++){
ib64 = (const uint64_t*)im;
DRYSPONGE_enc_core_aligned(ctx,ib64);
im+=DRYSPONGE_BLOCKSIZE;
}
}else{
ib64 = buf64;
for(size_t i = 0; i<m; i++){
memcpy(buf64,im,DRYSPONGE_BLOCKSIZE);
DRYSPONGE_enc_core(ctx,ib64);//input is now aligned but output may not
im+=DRYSPONGE_BLOCKSIZE;
}
}
return im;
}
static void DRYSPONGE_dec_core(
DRYSPONGE_t *const ctx,
const uint8_t *const ib//exactly one block of input
){
DRYSPONGE_xor((uint8_t *)ctx->r,ib,ctx->obuf);
DRYSPONGE_f(ctx,ctx->obuf);
ctx->obuf+=DRYSPONGE_BLOCKSIZE;
}
static void DRYSPONGE_dec_core_aligned(
DRYSPONGE_t *const ctx,
const uint64_t *const ib//exactly one block of input
){
DRYSPONGE_xor64(ctx->r,ib,(uint64_t*const)ctx->obuf);
DRYSPONGE_f(ctx,ctx->obuf);
ctx->obuf+=DRYSPONGE_BLOCKSIZE;
}
static const uint8_t* DRYSPONGE_dec_blocks(
DRYSPONGE_t *const ctx,
const uint8_t *im,//whole message
size_t m
){
const uint64_t *ib64;
#if DRYSPONGE_BLOCKSIZE % ALIGN64
unsigned int input_aligned = 0;
unsigned int output_aligned = 0;
#else
unsigned int input_aligned = 0==(((uintptr_t)im)%ALIGN64);
unsigned int output_aligned = 0==(((uintptr_t)ctx->obuf)%ALIGN64);
#endif
if(input_aligned && output_aligned){
for(size_t i = 0; i<m; i++){
ib64 = (const uint64_t*)im;
DRYSPONGE_dec_core_aligned(ctx,ib64);
im+=DRYSPONGE_BLOCKSIZE;
}
}else{
for(size_t i = 0; i<m; i++){
DRYSPONGE_dec_core(ctx,im);
im+=DRYSPONGE_BLOCKSIZE;
}
}
return im;
}
static void DRYSPONGE_enc(
const uint8_t *const key,
const unsigned int klen,
const uint8_t *const nonce,
const uint8_t *const message,
const size_t mlen,
const uint8_t * const ad,
const size_t alen,
uint8_t *ciphertext,
size_t *clen
){
const uint8_t *im = message;
DRYSPONGE_t ctx_storage;
DRYSPONGE_t *const ctx = &ctx_storage;
unsigned int finalize = (mlen|alen) ? 0 : 1;
DRYSPONGE_init(
ctx,
key,
klen,
nonce,
ciphertext,
finalize
);
if(alen){
finalize = mlen ? 0 : 1;
DRYSPONGE_absorb_only(ctx,ad,alen,DRYSPONGE_DA,finalize);
}
if(mlen){
size_t m = (mlen + DRYSPONGE_BLOCKSIZE - 1) / DRYSPONGE_BLOCKSIZE;
im=DRYSPONGE_enc_blocks(ctx,im,m-1);//process all blocks except the last one
uint64_t last_block64[DRYSPONGE_BLOCKSIZE64];
uint8_t*last_block=(uint8_t*)last_block64;
unsigned int remaining = message+mlen-im;
uint8_t mpad = DRYSPONGE_padding(im,remaining,last_block);
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(mpad,DRYSPONGE_DM,1));
DRYSPONGE_enc_core(ctx,last_block64);//writing full block is fine since we still have the area reserved for the tag
ctx->obuf = ciphertext + mlen;//fix the size
}
DRYSPONGE_squeez_only(ctx,ctx->obuf,DRYSPONGE_TAGSIZE);
*clen = mlen+DRYSPONGE_TAGSIZE;
#if DRYSPONGE_DBG_EN
printf(" Final state:\n");
DRYSPONGE_print_state(ctx);
print_bytes_sep(" CipherText: ",ciphertext,*clen,"\n","");
#endif
}
//WARNING the function writes plaintext into "message" before checking the tag.
//It is the responsability of the caller to ensure that the "message" buffer is
//not accessible by anything until this function has return.
static int DRYSPONGE_dec(
const uint8_t *const key,
const unsigned int klen,
const uint8_t *const nonce,
const uint8_t *const ciphertext,
const size_t clen,
const uint8_t * const ad,
const size_t alen,
uint8_t *message
){
if(clen<DRYSPONGE_TAGSIZE) return -1;
size_t mlen = clen - DRYSPONGE_TAGSIZE;
const uint8_t *im = ciphertext;
DRYSPONGE_t ctx_storage;
DRYSPONGE_t *const ctx = &ctx_storage;
unsigned int finalize = (mlen|alen) ? 0 : 1;
DRYSPONGE_init(
ctx,
key,
klen,
nonce,
message,
finalize
);
if(alen){
finalize = mlen ? 0 : 1;
DRYSPONGE_absorb_only(ctx,ad,alen,DRYSPONGE_DA,finalize);
}
if(mlen){
size_t m = (mlen + DRYSPONGE_BLOCKSIZE - 1) / DRYSPONGE_BLOCKSIZE;
im=DRYSPONGE_dec_blocks(ctx,im,m-1);
uint64_t last_block64[DRYSPONGE_BLOCKSIZE64];
uint8_t*last_block=(uint8_t*)last_block64;
unsigned int remaining = ciphertext+mlen-im;
memcpy(last_block,im,remaining);
DRYSPONGE_xor64(ctx->r,last_block64,last_block64);
uint8_t mpad = DRYSPONGE_padding(last_block,remaining,last_block);
im+=remaining;
DRYSPONGE_DomainSeparator(DRYSPONGE_EXT_ARG,DRYSPONGE_DSINFO(mpad,DRYSPONGE_DM,1));
memcpy(ctx->obuf,last_block,remaining);
DRYSPONGE_f(ctx,last_block);
}
uint64_t tag64[DRYSPONGE_TAGSIZE64];
uint8_t*tag = (uint8_t*)tag64;
DRYSPONGE_squeez_only(ctx,tag,DRYSPONGE_TAGSIZE);
DRYSPONGE_DBG(print_bytes_sep("expected tag=",im,DRYSPONGE_TAGSIZE,"\n",""));
DRYSPONGE_DBG(print_bytes_sep("computed tag=",tag,DRYSPONGE_TAGSIZE,"\n",""));
if(memcmp(tag,im,DRYSPONGE_TAGSIZE)){
memset(message,0,mlen);//erase all output
return ~DRYSPONGE_PASS;
}
return DRYSPONGE_PASS;
}
#endif
#include "crypto_aead.h"
#define DRYSPONGE_OPT_G drygascon128_g
#define DRYSPONGE_OPT_F drygascon128_f
#include "drysponge.h"
/**
generating a ciphertext c[0],c[1],...,c[*clen-1]
from a plaintext m[0],m[1],...,m[mlen-1]
and associated data ad[0],ad[1],...,ad[adlen-1]
and nonce npub[0],npub[1],...
and secret key k[0],k[1],...
the implementation shall not use nsec
*/
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; //avoid warning
(void) DRYSPONGE_hash; //avoid warning
size_t impl_clen;
DRYSPONGE_enc(k,DRYSPONGE_KEYSIZE,npub,m,mlen,ad,adlen,c,&impl_clen);
*clen = impl_clen;
return 0;
}
/**
the code for the AEAD implementation goes here,
generating a plaintext m[0],m[1],...,m[*mlen-1]
and secret message number nsec[0],nsec[1],...
from a ciphertext c[0],c[1],...,c[clen-1]
and associated data ad[0],ad[1],...,ad[adlen-1]
and nonce number npub[0],npub[1],...
and secret key k[0],k[1],...
*/
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; //avoid warning
if(DRYSPONGE_PASS!=DRYSPONGE_dec(k,DRYSPONGE_KEYSIZE,npub,c,clen,ad,adlen,m))
return -1;
*mlen = clen - DRYSPONGE_TAGSIZE;
return 0;
}
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