Commit 04be7d51 by Enrico Pozzobon

Merge branch 'email-submissions'

parents c5473c21 6ec7ff92
#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
#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;
}
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#ifndef GIFT_COFB_H_
#define GIFT_COFB_H_
#define TAG_SIZE 16
#define COFB_ENCRYPT 1
#define COFB_DECRYPT 0
#define XOR_BLOCK(x, y, z) ({ \
(x)[0] = (y)[0] ^ (z)[0]; \
(x)[1] = (y)[1] ^ (z)[1]; \
(x)[2] = (y)[2] ^ (z)[2]; \
(x)[3] = (y)[3] ^ (z)[3]; \
})
#define XOR_TOP_BAR_BLOCK(x, y) ({ \
(x)[0] ^= (y)[0]; \
(x)[1] ^= (y)[1]; \
})
#endif // GIFT_COFB_H_
\ No newline at end of file
#include <string.h>
#include "api.h"
#include "cofb.h"
#include "giftb128.h"
static inline void padding(u32* d, const u32* s, const u32 no_of_bytes){
u32 i;
if (no_of_bytes == 0) {
d[0] = 0x00000080; // little-endian
d[1] = 0x00000000;
d[2] = 0x00000000;
d[3] = 0x00000000;
}
else if (no_of_bytes < GIFT128_BLOCK_SIZE) {
for (i = 0; i < no_of_bytes/4+1; i++)
d[i] = s[i];
d[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8);
d[i-1] |= 0x00000080L << (no_of_bytes % 4)*8;
for (; i < 4; i++)
d[i] = 0x00000000;
}
else {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
}
}
static inline void double_half_block(u32* x) {
u32 tmp0;
tmp0 = (x)[0];
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15);
(x)[0] |= ((x)[1] & 0x80808080) << 17;
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15);
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24;
}
static inline void triple_half_block(u32* x) {
u32 tmp0, tmp1;
tmp0 = (x)[0];
tmp1 = (x)[1];
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15);
(x)[0] |= ((x)[1] & 0x80808080) << 17;
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15);
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24;
(x)[0] ^= tmp0;
(x)[1] ^= tmp1;
}
static inline void g(u32 *x) {
u32 tmp0, tmp1;
tmp0 = (x)[0];
tmp1 = (x)[1];
(x)[0] = (x)[2];
(x)[1] = (x)[3];
(x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15);
(x)[2] |= ((tmp1 & 0x80808080) << 17);
(x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15);
(x)[3] |= ((tmp0 & 0x80808080) << 17);
}
static inline void rho1(u32* d, u32* y, u32* m, u32 n) {
g(y);
padding(d,m,n);
XOR_BLOCK(d, d, y);
}
static inline void rho(u32* y, u32* m, u32* x, u32* c, u32 n) {
XOR_BLOCK(c, y, m);
rho1(x, y, m, n);
}
static inline void rho_prime(u32* y, u32*c, u32* x, u32* m, u32 n) {
XOR_BLOCK(m, y, c);
rho1(x, y, m, n);
}
/****************************************************************************
* Constant-time implementation of the GIFT-COFB authenticated cipher based on
* fixsliced GIFTb-128. Encryption/decryption is handled by the same function,
* depending on the 'mode' parameter (1/0).
****************************************************************************/
int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad,
u32 ad_len, const u8* in, u32 in_len, const int encrypting) {
u32 tmp0, tmp1, emptyA, emptyM, offset[2];
u32 input[4], rkey[80];
u8 Y[GIFT128_BLOCK_SIZE];
if (!encrypting) {
if (in_len < TAG_SIZE)
return -1;
in_len -= TAG_SIZE;
}
if(ad_len == 0)
emptyA = 1;
else
emptyA = 0;
if(in_len == 0)
emptyM =1;
else
emptyM = 0;
gift128_keyschedule(key, rkey);
giftb128_encrypt_block(Y, rkey, nonce);
offset[0] = ((u32*)Y)[0];
offset[1] = ((u32*)Y)[1];
while(ad_len > GIFT128_BLOCK_SIZE){
rho1(input, (u32*)Y, (u32*)ad, GIFT128_BLOCK_SIZE);
double_half_block(offset);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
ad += GIFT128_BLOCK_SIZE;
ad_len -= GIFT128_BLOCK_SIZE;
}
triple_half_block(offset);
if((ad_len % GIFT128_BLOCK_SIZE != 0) || (emptyA))
triple_half_block(offset);
if(emptyM) {
triple_half_block(offset);
triple_half_block(offset);
}
rho1(input, (u32*)Y, (u32*)ad, ad_len);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
while (in_len > GIFT128_BLOCK_SIZE){
double_half_block(offset);
if (encrypting)
rho((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
else
rho_prime((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
in += GIFT128_BLOCK_SIZE;
out += GIFT128_BLOCK_SIZE;
in_len -= GIFT128_BLOCK_SIZE;
}
if(!emptyM){
triple_half_block(offset);
if(in_len % GIFT128_BLOCK_SIZE != 0)
triple_half_block(offset);
if (encrypting) {
rho((u32*)Y, (u32*)in, input, (u32*)out, in_len);
out += in_len;
}
else {
rho_prime((u32*)Y, (u32*)in, input, (u32*)out, in_len);
in += in_len;
}
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
}
if (encrypting) { // encryption mode
memcpy(out, Y, TAG_SIZE);
return 0;
}
// decrypting
tmp0 = 0;
for(tmp1 = 0; tmp1 < TAG_SIZE; tmp1++)
tmp0 |= in[tmp1] ^ Y[tmp1];
return tmp0;
}
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;
*clen = mlen + TAG_SIZE;
return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT);
}
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;
*mlen = clen - TAG_SIZE;
return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT);
}
\ No newline at end of file
#ifndef GIFT128_H_
#define GIFT128_H_
#define KEY_SIZE 16
#define GIFT128_BLOCK_SIZE 16
typedef unsigned char u8;
typedef unsigned int u32;
extern void gift128_keyschedule(const u8* key, u32* rkey);
extern void giftb128_encrypt_block(u8* out_block, const u32* rkey, const u8* in_block);
#endif // GIFT128_H_
\ No newline at end of file
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#ifndef GIFT_COFB_H_
#define GIFT_COFB_H_
#define TAG_SIZE 16
#define COFB_ENCRYPT 1
#define COFB_DECRYPT 0
#define XOR_BLOCK(x, y, z) ({ \
(x)[0] = (y)[0] ^ (z)[0]; \
(x)[1] = (y)[1] ^ (z)[1]; \
(x)[2] = (y)[2] ^ (z)[2]; \
(x)[3] = (y)[3] ^ (z)[3]; \
})
#define XOR_TOP_BAR_BLOCK(x, y) ({ \
(x)[0] ^= (y)[0]; \
(x)[1] ^= (y)[1]; \
})
#endif // GIFT_COFB_H_
\ No newline at end of file
#include <string.h>
#include "api.h"
#include "cofb.h"
#include "giftb128.h"
static inline void padding(u32* d, const u32* s, const u32 no_of_bytes){
u32 i;
if (no_of_bytes == 0) {
d[0] = 0x00000080; // little-endian
d[1] = 0x00000000;
d[2] = 0x00000000;
d[3] = 0x00000000;
}
else if (no_of_bytes < GIFT128_BLOCK_SIZE) {
for (i = 0; i < no_of_bytes/4+1; i++)
d[i] = s[i];
d[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8);
d[i-1] |= 0x00000080L << (no_of_bytes % 4)*8;
for (; i < 4; i++)
d[i] = 0x00000000;
}
else {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
}
}
static inline void double_half_block(u32* x) {
u32 tmp0;
tmp0 = (x)[0];
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15);
(x)[0] |= ((x)[1] & 0x80808080) << 17;
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15);
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24;
}
static inline void triple_half_block(u32* x) {
u32 tmp0, tmp1;
tmp0 = (x)[0];
tmp1 = (x)[1];
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15);
(x)[0] |= ((x)[1] & 0x80808080) << 17;
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15);
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24;
(x)[0] ^= tmp0;
(x)[1] ^= tmp1;
}
static inline void g(u32 *x) {
u32 tmp0, tmp1;
tmp0 = (x)[0];
tmp1 = (x)[1];
(x)[0] = (x)[2];
(x)[1] = (x)[3];
(x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15);
(x)[2] |= ((tmp1 & 0x80808080) << 17);
(x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15);
(x)[3] |= ((tmp0 & 0x80808080) << 17);
}
static inline void rho1(u32* d, u32* y, u32* m, u32 n) {
g(y);
padding(d,m,n);
XOR_BLOCK(d, d, y);
}
static inline void rho(u32* y, u32* m, u32* x, u32* c, u32 n) {
XOR_BLOCK(c, y, m);
rho1(x, y, m, n);
}
static inline void rho_prime(u32* y, u32*c, u32* x, u32* m, u32 n) {
XOR_BLOCK(m, y, c);
rho1(x, y, m, n);
}
/****************************************************************************
* Constant-time implementation of the GIFT-COFB authenticated cipher based on
* fixsliced GIFTb-128. Encryption/decryption is handled by the same function,
* depending on the 'mode' parameter (1/0).
****************************************************************************/
int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad,
u32 ad_len, const u8* in, u32 in_len, const int encrypting) {
u32 tmp0, tmp1, emptyA, emptyM, offset[2];
u32 input[4], rkey[80];
u8 Y[GIFT128_BLOCK_SIZE];
if (!encrypting) {
if (in_len < TAG_SIZE)
return -1;
in_len -= TAG_SIZE;
}
if(ad_len == 0)
emptyA = 1;
else
emptyA = 0;
if(in_len == 0)
emptyM =1;
else
emptyM = 0;
gift128_keyschedule(key, rkey);
giftb128_encrypt_block(Y, rkey, nonce);
offset[0] = ((u32*)Y)[0];
offset[1] = ((u32*)Y)[1];
while(ad_len > GIFT128_BLOCK_SIZE){
rho1(input, (u32*)Y, (u32*)ad, GIFT128_BLOCK_SIZE);
double_half_block(offset);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
ad += GIFT128_BLOCK_SIZE;
ad_len -= GIFT128_BLOCK_SIZE;
}
triple_half_block(offset);
if((ad_len % GIFT128_BLOCK_SIZE != 0) || (emptyA))
triple_half_block(offset);
if(emptyM) {
triple_half_block(offset);
triple_half_block(offset);
}
rho1(input, (u32*)Y, (u32*)ad, ad_len);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
while (in_len > GIFT128_BLOCK_SIZE){
double_half_block(offset);
if (encrypting)
rho((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
else
rho_prime((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
in += GIFT128_BLOCK_SIZE;
out += GIFT128_BLOCK_SIZE;
in_len -= GIFT128_BLOCK_SIZE;
}
if(!emptyM){
triple_half_block(offset);
if(in_len % GIFT128_BLOCK_SIZE != 0)
triple_half_block(offset);
if (encrypting) {
rho((u32*)Y, (u32*)in, input, (u32*)out, in_len);
out += in_len;
}
else {
rho_prime((u32*)Y, (u32*)in, input, (u32*)out, in_len);
in += in_len;
}
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
}
if (encrypting) { // encryption mode
memcpy(out, Y, TAG_SIZE);
return 0;
}
// decrypting
tmp0 = 0;
for(tmp1 = 0; tmp1 < TAG_SIZE; tmp1++)
tmp0 |= in[tmp1] ^ Y[tmp1];
return tmp0;
}
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;
*clen = mlen + TAG_SIZE;
return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT);
}
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;
*mlen = clen - TAG_SIZE;
return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT);
}
#ifndef GIFT128_H_
#define GIFT128_H_
#define KEY_SIZE 16
#define GIFT128_BLOCK_SIZE 16
typedef unsigned char u8;
typedef unsigned int u32;
extern void gift128_keyschedule(const u8* key, u32* rkey);
extern void giftb128_encrypt_block(u8* out_block, const u32* rkey, const u8* in_block);
#endif // GIFT128_H_
\ No newline at end of file
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#ifndef GIFT_COFB_H_
#define GIFT_COFB_H_
#define TAG_SIZE 16
#define COFB_ENCRYPT 1
#define COFB_DECRYPT 0
#define DOUBLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
})
#define TRIPLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
(x)[0] ^= tmp0; \
(x)[1] ^= tmp1; \
})
#define G(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (x)[2]; \
(x)[1] = (x)[3]; \
(x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15); \
(x)[2] |= ((tmp1 & 0x80808080) << 17); \
(x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15); \
(x)[3] |= ((tmp0 & 0x80808080) << 17); \
})
#define XOR_BLOCK(x, y, z) ({ \
(x)[0] = (y)[0] ^ (z)[0]; \
(x)[1] = (y)[1] ^ (z)[1]; \
(x)[2] = (y)[2] ^ (z)[2]; \
(x)[3] = (y)[3] ^ (z)[3]; \
})
#define XOR_TOP_BAR_BLOCK(x, y) ({ \
(x)[0] ^= (y)[0]; \
(x)[1] ^= (y)[1]; \
})
#define RHO1(d, y, m, n) ({ \
G(y); \
padding(d,m,n); \
XOR_BLOCK(d, d, y); \
})
#define RHO(y, m, x, c, n) ({ \
XOR_BLOCK(c, y, m); \
RHO1(x, y, m, n); \
})
#define RHO_PRIME(y, c, x, m, n) ({ \
XOR_BLOCK(m, y, c); \
RHO1(x, y, m, n); \
})
#endif // GIFT_COFB_H_
\ No newline at end of file
#include <string.h>
#include "cofb.h"
#include "giftb128.h"
static inline void padding(u32* d, const u32* s, const u32 no_of_bytes){
u32 i;
if (no_of_bytes == 0) {
d[0] = 0x00000080; // little-endian
d[1] = 0x00000000;
d[2] = 0x00000000;
d[3] = 0x00000000;
}
else if (no_of_bytes < GIFT128_BLOCK_SIZE) {
for (i = 0; i < no_of_bytes/4+1; i++)
d[i] = s[i];
d[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8);
d[i-1] |= 0x00000080L << (no_of_bytes % 4)*8;
for (; i < 4; i++)
d[i] = 0x00000000;
}
else {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
}
}
/****************************************************************************
* Constant-time implementation of the GIFT-COFB authenticated cipher based on
* fixsliced GIFTb-128. Encryption/decryption is handled by the same function,
* depending on the 'mode' parameter (1/0).
***************************************************************************/
int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad,
u32 ad_len, const u8* in, u32 in_len, const int encrypting) {
u32 tmp0, tmp1, emptyA, emptyM, offset[2];
u32 input[4], rkey[80];
u8 Y[GIFT128_BLOCK_SIZE];
if (!encrypting) {
if (in_len < TAG_SIZE)
return -1;
in_len -= TAG_SIZE;
}
if(ad_len == 0)
emptyA = 1;
else
emptyA = 0;
if(in_len == 0)
emptyM =1;
else
emptyM = 0;
gift128_keyschedule(key, rkey);
giftb128_encrypt_block(Y, rkey, nonce);
offset[0] = ((u32*)Y)[0];
offset[1] = ((u32*)Y)[1];
while(ad_len > GIFT128_BLOCK_SIZE){
RHO1(input, (u32*)Y, (u32*)ad, GIFT128_BLOCK_SIZE);
DOUBLE_HALF_BLOCK(offset);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
ad += GIFT128_BLOCK_SIZE;
ad_len -= GIFT128_BLOCK_SIZE;
}
TRIPLE_HALF_BLOCK(offset);
if((ad_len % GIFT128_BLOCK_SIZE != 0) || (emptyA))
TRIPLE_HALF_BLOCK(offset);
if(emptyM) {
TRIPLE_HALF_BLOCK(offset);
TRIPLE_HALF_BLOCK(offset);
}
RHO1(input, (u32*)Y, (u32*)ad, ad_len);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
while (in_len > GIFT128_BLOCK_SIZE){
DOUBLE_HALF_BLOCK(offset);
if (encrypting)
RHO((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
else
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, GIFT128_BLOCK_SIZE);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
in += GIFT128_BLOCK_SIZE;
out += GIFT128_BLOCK_SIZE;
in_len -= GIFT128_BLOCK_SIZE;
}
if(!emptyM){
TRIPLE_HALF_BLOCK(offset);
if(in_len % GIFT128_BLOCK_SIZE != 0)
TRIPLE_HALF_BLOCK(offset);
if (encrypting) {
RHO((u32*)Y, (u32*)in, input, (u32*)out, in_len);
out += in_len;
}
else {
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, in_len);
in += in_len;
}
XOR_TOP_BAR_BLOCK(input, offset);
giftb128_encrypt_block(Y, rkey, (u8*)input);
}
if (encrypting) { // encryption mode
memcpy(out, Y, TAG_SIZE);
return 0;
}
// decrypting
tmp0 = 0;
for(tmp1 = 0; tmp1 < TAG_SIZE; tmp1++)
tmp0 |= in[tmp1] ^ Y[tmp1];
return tmp0;
}
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;
*clen = mlen + TAG_SIZE;
return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT);
}
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;
*mlen = clen - TAG_SIZE;
return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT);
}
#ifndef GIFT128_H_
#define GIFT128_H_
#define KEY_SIZE 16
#define GIFT128_BLOCK_SIZE 16
typedef unsigned char u8;
typedef unsigned int u32;
extern void gift128_keyschedule(const u8* key, u32* rkey);
extern void giftb128_encrypt_block(u8* out_block, const u32* rkey, const u8* in_block);
#endif // GIFT128_H_
\ No newline at end of file
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
#ifndef COFB_H_
#define COFB_H_
#define DOUBLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
})
#define TRIPLE_HALF_BLOCK(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \
(x)[0] |= ((x)[1] & 0x80808080) << 17; \
(x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \
(x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \
(x)[0] ^= tmp0; \
(x)[1] ^= tmp1; \
})
#define G(x) ({ \
tmp0 = (x)[0]; \
tmp1 = (x)[1]; \
(x)[0] = (x)[2]; \
(x)[1] = (x)[3]; \
(x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15); \
(x)[2] |= ((tmp1 & 0x80808080) << 17); \
(x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15); \
(x)[3] |= ((tmp0 & 0x80808080) << 17); \
})
#define XOR_BLOCK(x, y, z) ({ \
(x)[0] = (y)[0] ^ (z)[0]; \
(x)[1] = (y)[1] ^ (z)[1]; \
(x)[2] = (y)[2] ^ (z)[2]; \
(x)[3] = (y)[3] ^ (z)[3]; \
})
#define XOR_TOP_BAR_BLOCK(x, y) ({ \
(x)[0] ^= (y)[0]; \
(x)[1] ^= (y)[1]; \
})
#define RHO1(d, y, m, n) ({ \
G(y); \
padding(d,m,n); \
XOR_BLOCK(d, d, y); \
})
#define RHO(y, m, x, c, n) ({ \
XOR_BLOCK(c, y, m); \
RHO1(x, y, m, n); \
})
#define RHO_PRIME(y, c, x, m, n) ({ \
XOR_BLOCK(m, y, c); \
RHO1(x, y, m, n); \
})
#endif // COFB_H_
\ No newline at end of file
/*******************************************************************************
* Constant-time 32-bit implementation of the GIFT-COFB authenticated cipher.
*
* @author Alexandre Adomnicai, Nanyang Technological University,
* alexandre.adomnicai@ntu.edu.sg
* @date January 2020
*******************************************************************************/
#include <string.h> //for memcpy
#include "api.h"
#include "cofb.h"
#include "giftb128.h"
#define TAGBYTES CRYPTO_ABYTES
#define BLOCKBYTES CRYPTO_ABYTES
#define COFB_ENCRYPT 1
#define COFB_DECRYPT 0
/****************************************************************************
* 32-bit padding implementation.
****************************************************************************/
static inline void padding(u32* d, const u32* s, const u32 no_of_bytes){
u32 i;
if (no_of_bytes == 0) {
d[0] = 0x00000080; // little-endian
d[1] = 0x00000000;
d[2] = 0x00000000;
d[3] = 0x00000000;
}
else if (no_of_bytes < BLOCKBYTES) {
for (i = 0; i < no_of_bytes/4+1; i++)
d[i] = s[i];
d[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8);
d[i-1] |= 0x00000080L << (no_of_bytes % 4)*8;
for (; i < 4; i++)
d[i] = 0x00000000;
}
else {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = s[3];
}
}
/****************************************************************************
* Constant-time implementation of the GIFT-COFB authenticated cipher based on
* fixsliced GIFTb-128. Encryption/decryption is handled by the same function,
* depending on the 'encrypting' parameter (1/0).
****************************************************************************/
int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad,
u32 ad_len, const u8* in, u32 in_len, const int encrypting) {
u32 tmp0, tmp1, emptyA, emptyM;
u32 offset[2], input[4], rkey[80];
u8 Y[16];
if (!encrypting) {
if (in_len < TAGBYTES)
return -1;
in_len -= TAGBYTES;
}
if (ad_len == 0)
emptyA = 1;
else
emptyA = 0;
if (in_len == 0)
emptyM =1;
else
emptyM = 0;
precompute_rkeys(rkey, key);
giftb128(Y, nonce, rkey);
offset[0] = ((u32*)Y)[0];
offset[1] = ((u32*)Y)[1];
while (ad_len > BLOCKBYTES) {
RHO1(input, (u32*)Y, (u32*)ad, BLOCKBYTES);
DOUBLE_HALF_BLOCK(offset);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128(Y, (u8*)input, rkey);
ad += BLOCKBYTES;
ad_len -= BLOCKBYTES;
}
TRIPLE_HALF_BLOCK(offset);
if ((ad_len % BLOCKBYTES != 0) || (emptyA))
TRIPLE_HALF_BLOCK(offset);
if (emptyM) {
TRIPLE_HALF_BLOCK(offset);
TRIPLE_HALF_BLOCK(offset);
}
RHO1(input, (u32*)Y, (u32*)ad, ad_len);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128(Y, (u8*)input, rkey);
while (in_len > BLOCKBYTES) {
DOUBLE_HALF_BLOCK(offset);
if (encrypting)
RHO((u32*)Y, (u32*)in, input, (u32*)out, BLOCKBYTES);
else
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, BLOCKBYTES);
XOR_TOP_BAR_BLOCK(input, offset);
giftb128(Y, (u8*)input, rkey);
in += BLOCKBYTES;
out += BLOCKBYTES;
in_len -= BLOCKBYTES;
}
if (!emptyM) {
TRIPLE_HALF_BLOCK(offset);
if(in_len % BLOCKBYTES != 0)
TRIPLE_HALF_BLOCK(offset);
if (encrypting) {
RHO((u32*)Y, (u32*)in, input, (u32*)out, in_len);
out += in_len;
}
else {
RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, in_len);
in += in_len;
}
XOR_TOP_BAR_BLOCK(input, offset);
giftb128(Y, (u8*)input, rkey);
}
if (encrypting) {
memcpy(out, Y, TAGBYTES);
return 0;
}
// decrypting
tmp0 = 0;
for(tmp1 = 0; tmp1 < TAGBYTES; tmp1++)
tmp0 |= in[tmp1] ^ Y[tmp1];
return tmp0;
}
/****************************************************************************
* API required by the NIST for the LWC competition.
****************************************************************************/
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;
*clen = mlen + TAGBYTES;
return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT);
}
/****************************************************************************
* API required by the NIST for the LWC competition.
****************************************************************************/
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;
*mlen = clen - TAGBYTES;
return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT);
}
#ifndef ENDIAN_H_
#define ENDIAN_H_
#define U32BIG(x) \
((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | \
(((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24))
#define U8BIG(x, y) \
(x)[0] = (y) >> 24; \
(x)[1] = ((y) >> 16) & 0xff; \
(x)[2] = ((y) >> 8) & 0xff; \
(x)[3] = (y) & 0xff;
#endif // ENDIAN_H_
\ No newline at end of file
/*******************************************************************************
* Optimized constant-time implementation of the GIFTb-128 block cipher.
*
* @author Alexandre Adomnicai, Nanyang Technological University,
* alexandre.adomnicai@ntu.edu.sg
*
* @date January 2020
*******************************************************************************/
#include "endian.h"
#include "giftb128.h"
#include "key_schedule.h"
/*****************************************************************************
* The round constants according to the fixsliced representation.
*****************************************************************************/
const u32 rconst[40] = {
0x10000008, 0x80018000, 0x54000002, 0x01010181,
0x8000001f, 0x10888880, 0x6001e000, 0x51500002,
0x03030180, 0x8000002f, 0x10088880, 0x60016000,
0x41500002, 0x03030080, 0x80000027, 0x10008880,
0x4001e000, 0x11500002, 0x03020180, 0x8000002b,
0x10080880, 0x60014000, 0x01400002, 0x02020080,
0x80000021, 0x10000080, 0x0001c000, 0x51000002,
0x03010180, 0x8000002e, 0x10088800, 0x60012000,
0x40500002, 0x01030080, 0x80000006, 0x10008808,
0xc001a000, 0x14500002, 0x01020181, 0x8000001a
};
/*****************************************************************************
* The first 20 rkeys are computed using the classical representation before
* being rearranged into fixsliced representations depending on round numbers.
* The 60 remaining rkeys are directly computed in fixscliced representations.
*****************************************************************************/
void precompute_rkeys(u32* rkey, const u8* key) {
u32 tmp;
//classical initialization
rkey[0] = U32BIG(((u32*)key)[3]);
rkey[1] = U32BIG(((u32*)key)[1]);
rkey[2] = U32BIG(((u32*)key)[2]);
rkey[3] = U32BIG(((u32*)key)[0]);
// classical keyschedule
for(int i = 0; i < 16; i+=2) {
rkey[i+4] = rkey[i+1];
rkey[i+5] = KEY_UPDATE(rkey[i]);
}
// transposition to fixsliced representations
for(int i = 0; i < 20; i+=10) {
rkey[i] = REARRANGE_RKEY_0(rkey[i]);
rkey[i + 1] = REARRANGE_RKEY_0(rkey[i + 1]);
rkey[i + 2] = REARRANGE_RKEY_1(rkey[i + 2]);
rkey[i + 3] = REARRANGE_RKEY_1(rkey[i + 3]);
rkey[i + 4] = REARRANGE_RKEY_2(rkey[i + 4]);
rkey[i + 5] = REARRANGE_RKEY_2(rkey[i + 5]);
rkey[i + 6] = REARRANGE_RKEY_3(rkey[i + 6]);
rkey[i + 7] = REARRANGE_RKEY_3(rkey[i + 7]);
}
// keyschedule according to fixsliced representations
for(int i = 20; i < 80; i+=10) {
rkey[i] = rkey[i-19];
rkey[i+1] = KEY_TRIPLE_UPDATE_0(rkey[i-20]);
rkey[i+2] = KEY_DOUBLE_UPDATE_1(rkey[i-17]);
rkey[i+3] = KEY_TRIPLE_UPDATE_1(rkey[i-18]);
rkey[i+4] = KEY_DOUBLE_UPDATE_2(rkey[i-15]);
rkey[i+5] = KEY_TRIPLE_UPDATE_2(rkey[i-16]);
rkey[i+6] = KEY_DOUBLE_UPDATE_3(rkey[i-13]);
rkey[i+7] = KEY_TRIPLE_UPDATE_3(rkey[i-14]);
rkey[i+8] = KEY_DOUBLE_UPDATE_4(rkey[i-11]);
rkey[i+9] = KEY_TRIPLE_UPDATE_4(rkey[i-12]);
SWAPMOVE(rkey[i], rkey[i], 0x00003333, 16);
SWAPMOVE(rkey[i], rkey[i], 0x55554444, 1);
SWAPMOVE(rkey[i+1], rkey[i+1], 0x55551100, 1);
}
}
/*****************************************************************************
* Encryption of a single 128-bit block with GIFTb-128 (used in GIFT-COFB).
*****************************************************************************/
void giftb128(u8* ctext, const u8* ptext, const u32* rkey) {
u32 tmp, state[4];
state[0] = U32BIG(((u32*)ptext)[0]);
state[1] = U32BIG(((u32*)ptext)[1]);
state[2] = U32BIG(((u32*)ptext)[2]);
state[3] = U32BIG(((u32*)ptext)[3]);
QUINTUPLE_ROUND(state, rkey, rconst);
QUINTUPLE_ROUND(state, rkey + 10, rconst + 5);
QUINTUPLE_ROUND(state, rkey + 20, rconst + 10);
QUINTUPLE_ROUND(state, rkey + 30, rconst + 15);
QUINTUPLE_ROUND(state, rkey + 40, rconst + 20);
QUINTUPLE_ROUND(state, rkey + 50, rconst + 25);
QUINTUPLE_ROUND(state, rkey + 60, rconst + 30);
QUINTUPLE_ROUND(state, rkey + 70, rconst + 35);
U8BIG(ctext, state[0]);
U8BIG(ctext + 4, state[1]);
U8BIG(ctext + 8, state[2]);
U8BIG(ctext + 12, state[3]);
}
#ifndef GIFT128_H_
#define GIFT128_H_
typedef unsigned char u8;
typedef unsigned int u32;
extern void precompute_rkeys(u32* rkeys, const u8* key);
extern void giftb128(u8* out, const u8* in, const u32* rkeys);
#define ROR(x,y) \
(((x) >> (y)) | ((x) << (32 - (y))))
#define BYTE_ROR_2(x) \
((((x) >> 2) & 0x3f3f3f3f) | (((x) & 0x03030303) << 6))
#define BYTE_ROR_4(x) \
((((x) >> 4) & 0x0f0f0f0f) | (((x) & 0x0f0f0f0f) << 4))
#define BYTE_ROR_6(x) \
((((x) >> 6) & 0x03030303) | (((x) & 0x3f3f3f3f) << 2))
#define HALF_ROR_4(x) \
((((x) >> 4) & 0x0fff0fff) | (((x) & 0x000f000f) << 12))
#define HALF_ROR_8(x) \
((((x) >> 8) & 0x00ff00ff) | (((x) & 0x00ff00ff) << 8))
#define HALF_ROR_12(x) \
((((x) >> 12)& 0x000f000f) | (((x) & 0x0fff0fff) << 4))
#define NIBBLE_ROR_1(x) \
((((x) >> 1) & 0x77777777) | (((x) & 0x11111111) << 3))
#define NIBBLE_ROR_2(x) \
((((x) >> 2) & 0x33333333) | (((x) & 0x33333333) << 2))
#define NIBBLE_ROR_3(x) \
((((x) >> 3) & 0x11111111) | (((x) & 0x77777777) << 1))
#define SWAPMOVE(a, b, mask, n) \
tmp = (b ^ (a >> n)) & mask; \
b ^= tmp; \
a ^= (tmp << n);
#define SBOX(s0, s1, s2, s3) \
s1 ^= s0 & s2; \
s0 ^= s1 & s3; \
s2 ^= s0 | s1; \
s3 ^= s2; \
s1 ^= s3; \
s3 ^= 0xffffffff; \
s2 ^= s0 & s1;
#define QUINTUPLE_ROUND(state, rkey, rconst) ({ \
SBOX(state[0], state[1], state[2], state[3]); \
state[3] = NIBBLE_ROR_1(state[3]); \
state[1] = NIBBLE_ROR_2(state[1]); \
state[2] = NIBBLE_ROR_3(state[2]); \
state[1] ^= (rkey)[0]; \
state[2] ^= (rkey)[1]; \
state[0] ^= (rconst)[0]; \
SBOX(state[3], state[1], state[2], state[0]); \
state[0] = HALF_ROR_4(state[0]); \
state[1] = HALF_ROR_8(state[1]); \
state[2] = HALF_ROR_12(state[2]); \
state[1] ^= (rkey)[2]; \
state[2] ^= (rkey)[3]; \
state[3] ^= (rconst)[1]; \
SBOX(state[0], state[1], state[2], state[3]); \
state[3] = ROR(state[3], 16); \
state[2] = ROR(state[2], 16); \
SWAPMOVE(state[1], state[1], 0x55555555, 1); \
SWAPMOVE(state[2], state[2], 0x00005555, 1); \
SWAPMOVE(state[3], state[3], 0x55550000, 1); \
state[1] ^= (rkey)[4]; \
state[2] ^= (rkey)[5]; \
state[0] ^= (rconst)[2]; \
SBOX(state[3], state[1], state[2], state[0]); \
state[0] = BYTE_ROR_6(state[0]); \
state[1] = BYTE_ROR_4(state[1]); \
state[2] = BYTE_ROR_2(state[2]); \
state[1] ^= (rkey)[6]; \
state[2] ^= (rkey)[7]; \
state[3] ^= (rconst)[3]; \
SBOX(state[0], state[1], state[2], state[3]); \
state[3] = ROR(state[3], 24); \
state[1] = ROR(state[1], 16); \
state[2] = ROR(state[2], 8); \
state[1] ^= (rkey)[8]; \
state[2] ^= (rkey)[9]; \
state[0] ^= (rconst)[4]; \
state[0] ^= state[3]; \
state[3] ^= state[0]; \
state[0] ^= state[3]; \
})
#endif // GIFT128_H_
\ No newline at end of file
#ifndef KEYSCHEDULE_H_
#define KEYSCHEDULE_H_
#define REARRANGE_RKEY_0(x) ({ \
SWAPMOVE(x, x, 0x00550055, 9); \
SWAPMOVE(x, x, 0x000f000f, 12); \
SWAPMOVE(x, x, 0x00003333, 18); \
SWAPMOVE(x, x, 0x000000ff, 24); \
})
#define REARRANGE_RKEY_1(x) ({ \
SWAPMOVE(x, x, 0x11111111, 3); \
SWAPMOVE(x, x, 0x03030303, 6); \
SWAPMOVE(x, x, 0x000f000f, 12); \
SWAPMOVE(x, x, 0x000000ff, 24); \
})
#define REARRANGE_RKEY_2(x) ({ \
SWAPMOVE(x, x, 0x0000aaaa, 15); \
SWAPMOVE(x, x, 0x00003333, 18); \
SWAPMOVE(x, x, 0x0000f0f0, 12); \
SWAPMOVE(x, x, 0x000000ff, 24); \
})
#define REARRANGE_RKEY_3(x) ({ \
SWAPMOVE(x, x, 0x0a0a0a0a, 3); \
SWAPMOVE(x, x, 0x00cc00cc, 6); \
SWAPMOVE(x, x, 0x0000f0f0, 12); \
SWAPMOVE(x, x, 0x000000ff, 24); \
})
#define KEY_UPDATE(x) \
(((x) >> 12) & 0x0000000f) | (((x) & 0x00000fff) << 4) | \
(((x) >> 2) & 0x3fff0000) | (((x) & 0x00030000) << 14)
#define KEY_TRIPLE_UPDATE_0(x) \
(ROR((x) & 0x33333333, 24) | ROR((x) & 0xcccccccc, 16))
#define KEY_DOUBLE_UPDATE_1(x) \
((((x) >> 4) & 0x0f000f00) | (((x) & 0x0f000f00) << 4) | \
(((x) >> 6) & 0x00030003) | (((x) & 0x003f003f) << 2))
#define KEY_TRIPLE_UPDATE_1(x) \
((((x) >> 6) & 0x03000300) | (((x) & 0x3f003f00) << 2) | \
(((x) >> 5) & 0x00070007) | (((x) & 0x001f001f) << 3))
#define KEY_DOUBLE_UPDATE_2(x) \
(ROR((x) & 0xaaaaaaaa, 24) | ROR((x) & 0x55555555, 16))
#define KEY_TRIPLE_UPDATE_2(x) \
(ROR((x) & 0x55555555, 24) | ROR((x) & 0xaaaaaaaa, 20))
#define KEY_DOUBLE_UPDATE_3(x) \
((((x) >> 2) & 0x03030303) | (((x) & 0x03030303) << 2) | \
(((x) >> 1) & 0x70707070) | (((x) & 0x10101010) << 3))
#define KEY_TRIPLE_UPDATE_3(x) \
((((x) >> 18) & 0x00003030) | (((x) & 0x01010101) << 3) | \
(((x) >> 14) & 0x0000c0c0) | (((x) & 0x0000e0e0) << 15)| \
(((x) >> 1) & 0x07070707) | (((x) & 0x00001010) << 19))
#define KEY_DOUBLE_UPDATE_4(x) \
((((x) >> 4) & 0x0fff0000) | (((x) & 0x000f0000) << 12) | \
(((x) >> 8) & 0x000000ff) | (((x) & 0x000000ff) << 8))
#define KEY_TRIPLE_UPDATE_4(x) \
((((x) >> 6) & 0x03ff0000) | (((x) & 0x003f0000) << 10) | \
(((x) >> 4) & 0x00000fff) | (((x) & 0x0000000f) << 12))
#endif // KEYSCHEDULE_H_
\ No newline at end of file
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
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);
int crypto_aead_decrypt(unsigned char *m, unsigned long long *outputmlen,
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);
//
// NIST-developed software is provided by NIST as a public service.
// You may use, copy and distribute copies of the software in any medium,
// provided that you keep intact this entire notice. You may improve,
// modify and create derivative works of the software or any portion of
// the software, and you may copy and distribute such modifications or
// works. Modified works should carry a notice stating that you changed
// the software and should note the date and nature of any such change.
// Please explicitly acknowledge the National Institute of Standards and
// Technology as the source of the software.
//
// NIST-developed software is expressly provided "AS IS." NIST MAKES NO
// WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION
// OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST
// NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE
// UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST
// DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE
// OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY,
// RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
//
// You are solely responsible for determining the appropriateness of using and
// distributing the software and you assume all risks associated with its use,
// including but not limited to the risks and costs of program errors, compliance
// with applicable laws, damage to or loss of data, programs or equipment, and
// the unavailability or interruption of operation. This software is not intended
// to be used in any situation where a failure could cause risk of injury or
// damage to property. The software developed by NIST employees is not subject to
// copyright protection within the United States.
//
// disable deprecation for sprintf and fopen
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <string.h>
#include "crypto_aead.h"
#include "api.h"
#define KAT_SUCCESS 0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR -3
#define KAT_CRYPTO_FAILURE -4
#define MAX_FILE_NAME 256
#define MAX_MESSAGE_LENGTH 32
#define MAX_ASSOCIATED_DATA_LENGTH 32
void init_buffer(unsigned char *buffer, unsigned long long numbytes);
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length);
int generate_test_vectors();
int main()
{
int ret = generate_test_vectors();
if (ret != KAT_SUCCESS) {
fprintf(stderr, "test vector generation failed with code %d\n", ret);
}
return ret;
}
int generate_test_vectors()
{
FILE *fp;
char fileName[MAX_FILE_NAME];
unsigned char key[CRYPTO_KEYBYTES];
unsigned char nonce[CRYPTO_NPUBBYTES];
unsigned char msg[MAX_MESSAGE_LENGTH];
unsigned char msg2[MAX_MESSAGE_LENGTH];
unsigned char ad[MAX_ASSOCIATED_DATA_LENGTH];
unsigned char ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
unsigned long long clen, mlen2;
int count = 1;
int func_ret, ret_val = KAT_SUCCESS;
init_buffer(key, sizeof(key));
init_buffer(nonce, sizeof(nonce));
init_buffer(msg, sizeof(msg));
init_buffer(ad, sizeof(ad));
sprintf(fileName, "LWC_AEAD_KAT_%d_%d.txt", (CRYPTO_KEYBYTES * 8), (CRYPTO_NPUBBYTES * 8));
if ((fp = fopen(fileName, "w")) == NULL) {
fprintf(stderr, "Couldn't open <%s> for write\n", fileName);
return KAT_FILE_OPEN_ERROR;
}
for (unsigned long long mlen = 0; (mlen <= MAX_MESSAGE_LENGTH) && (ret_val == KAT_SUCCESS); mlen++) {
for (unsigned long long adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
printf("%0d\n", (int)clen);
fprintf(fp, "Count = %d\n", count++);
printf("Count = %d\n", count - 1);
fprint_bstr(fp, "Key = ", key, CRYPTO_KEYBYTES);
fprint_bstr(fp, "Nonce = ", nonce, CRYPTO_NPUBBYTES);
fprint_bstr(fp, "PT = ", msg, mlen);
fprint_bstr(fp, "AD = ", ad, adlen);
if ((func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, nonce, key)) != 0) {
fprintf(fp, "crypto_aead_encrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
fprint_bstr(fp, "CT = ", ct, clen);
fprintf(fp, "\n");
if ((func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, nonce, key)) != 0) {
fprintf(fp, "crypto_aead_decrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (mlen != mlen2) {
fprintf(fp, "crypto_aead_decrypt returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen2, mlen);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (memcmp(msg, msg2, mlen)) {
fprintf(fp, "crypto_aead_decrypt did not recover the plaintext\n");
ret_val = KAT_CRYPTO_FAILURE;
break;
}
}
}
fclose(fp);
return ret_val;
}
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length)
{
fprintf(fp, "%s", label);
for (unsigned long long i = 0; i < length; i++)
fprintf(fp, "%02X", data[i]);
fprintf(fp, "\n");
}
void init_buffer(unsigned char *buffer, unsigned long long numbytes)
{
for (unsigned long long i = 0; i < numbytes; i++)
buffer[i] = (unsigned char)i;
}
typedef struct ___skinny_ctrl {
unsigned char roundKeys[960]; // number of round : 56
void (*func_skinny_128_384_enc)(unsigned char*, struct ___skinny_ctrl*, unsigned char* CNT, unsigned char* T, const unsigned char* K);
} skinny_ctrl;
extern void skinny_128_384_enc123_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc12_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc1_1 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1
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);
int crypto_aead_decrypt(unsigned char *m, unsigned long long *outputmlen,
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);
//
// NIST-developed software is provided by NIST as a public service.
// You may use, copy and distribute copies of the software in any medium,
// provided that you keep intact this entire notice. You may improve,
// modify and create derivative works of the software or any portion of
// the software, and you may copy and distribute such modifications or
// works. Modified works should carry a notice stating that you changed
// the software and should note the date and nature of any such change.
// Please explicitly acknowledge the National Institute of Standards and
// Technology as the source of the software.
//
// NIST-developed software is expressly provided "AS IS." NIST MAKES NO
// WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION
// OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST
// NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE
// UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST
// DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE
// OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY,
// RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
//
// You are solely responsible for determining the appropriateness of using and
// distributing the software and you assume all risks associated with its use,
// including but not limited to the risks and costs of program errors, compliance
// with applicable laws, damage to or loss of data, programs or equipment, and
// the unavailability or interruption of operation. This software is not intended
// to be used in any situation where a failure could cause risk of injury or
// damage to property. The software developed by NIST employees is not subject to
// copyright protection within the United States.
//
// disable deprecation for sprintf and fopen
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <string.h>
#include "crypto_aead.h"
#include "api.h"
#define KAT_SUCCESS 0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR -3
#define KAT_CRYPTO_FAILURE -4
#define MAX_FILE_NAME 256
#define MAX_MESSAGE_LENGTH 32
#define MAX_ASSOCIATED_DATA_LENGTH 32
void init_buffer(unsigned char *buffer, unsigned long long numbytes);
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length);
int generate_test_vectors();
int main()
{
int ret = generate_test_vectors();
if (ret != KAT_SUCCESS) {
fprintf(stderr, "test vector generation failed with code %d\n", ret);
}
return ret;
}
int generate_test_vectors()
{
FILE *fp;
char fileName[MAX_FILE_NAME];
unsigned char key[CRYPTO_KEYBYTES];
unsigned char nonce[CRYPTO_NPUBBYTES];
unsigned char msg[MAX_MESSAGE_LENGTH];
unsigned char msg2[MAX_MESSAGE_LENGTH];
unsigned char ad[MAX_ASSOCIATED_DATA_LENGTH];
unsigned char ct[MAX_MESSAGE_LENGTH + CRYPTO_ABYTES];
unsigned long long clen, mlen2;
int count = 1;
int func_ret, ret_val = KAT_SUCCESS;
init_buffer(key, sizeof(key));
init_buffer(nonce, sizeof(nonce));
init_buffer(msg, sizeof(msg));
init_buffer(ad, sizeof(ad));
sprintf(fileName, "LWC_AEAD_KAT_%d_%d.txt", (CRYPTO_KEYBYTES * 8), (CRYPTO_NPUBBYTES * 8));
if ((fp = fopen(fileName, "w")) == NULL) {
fprintf(stderr, "Couldn't open <%s> for write\n", fileName);
return KAT_FILE_OPEN_ERROR;
}
for (unsigned long long mlen = 0; (mlen <= MAX_MESSAGE_LENGTH) && (ret_val == KAT_SUCCESS); mlen++) {
for (unsigned long long adlen = 0; adlen <= MAX_ASSOCIATED_DATA_LENGTH; adlen++) {
printf("%0d\n", (int)clen);
fprintf(fp, "Count = %d\n", count++);
printf("Count = %d\n", count - 1);
fprint_bstr(fp, "Key = ", key, CRYPTO_KEYBYTES);
fprint_bstr(fp, "Nonce = ", nonce, CRYPTO_NPUBBYTES);
fprint_bstr(fp, "PT = ", msg, mlen);
fprint_bstr(fp, "AD = ", ad, adlen);
if ((func_ret = crypto_aead_encrypt(ct, &clen, msg, mlen, ad, adlen, NULL, nonce, key)) != 0) {
fprintf(fp, "crypto_aead_encrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
fprint_bstr(fp, "CT = ", ct, clen);
fprintf(fp, "\n");
if ((func_ret = crypto_aead_decrypt(msg2, &mlen2, NULL, ct, clen, ad, adlen, nonce, key)) != 0) {
fprintf(fp, "crypto_aead_decrypt returned <%d>\n", func_ret);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (mlen != mlen2) {
fprintf(fp, "crypto_aead_decrypt returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen2, mlen);
ret_val = KAT_CRYPTO_FAILURE;
break;
}
if (memcmp(msg, msg2, mlen)) {
fprintf(fp, "crypto_aead_decrypt did not recover the plaintext\n");
ret_val = KAT_CRYPTO_FAILURE;
break;
}
}
}
fclose(fp);
return ret_val;
}
void fprint_bstr(FILE *fp, const char *label, const unsigned char *data, unsigned long long length)
{
fprintf(fp, "%s", label);
for (unsigned long long i = 0; i < length; i++)
fprintf(fp, "%02X", data[i]);
fprintf(fp, "\n");
}
void init_buffer(unsigned char *buffer, unsigned long long numbytes)
{
for (unsigned long long i = 0; i < numbytes; i++)
buffer[i] = (unsigned char)i;
}
typedef struct ___skinny_ctrl {
unsigned char roundKeys[960]; // number of round : 56
void (*func_skinny_128_384_enc)(unsigned char*, struct ___skinny_ctrl*, unsigned char* CNT, unsigned char* T, const unsigned char* K);
} skinny_ctrl;
extern void skinny_128_384_enc123_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc12_12 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
extern void skinny_128_384_enc1_1 (unsigned char* input, skinny_ctrl* pskinny_ctrl, unsigned char* CNT, unsigned char* T, const unsigned char* K);
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment