drygascon_le32.h 6.5 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
/**
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 = (uint32_t*)&in;
    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);
    }
    return in;
}
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