shake.c 7.23 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/**
 * @cond internal
 * @file shake.c
 * @copyright
 *   Uses public domain code by Mathias Panzenböck \n
 *   Uses CC0 code by David Leon Gil, 2015 \n
 *   Copyright (c) 2015 Cryptography Research, Inc.  \n
 *   Released under the MIT License.  See LICENSE.txt for license information.
 * @author Mike Hamburg
 * @brief SHA-3-n and SHAKE-n instances.
 * @warning EXPERIMENTAL!  The names, parameter orders etc are likely to change.
 */

#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
15
#define _BSD_SOURCE 1 /* for endian */
16
#define _DEFAULT_SOURCE 1 /* for endian with glibc 2.20 */
17 18 19 20
#include <assert.h>
#include <stdint.h>
#include <string.h>

21
#include "portable_endian.h"
22
#include "keccak_internal.h"
23
#include <decaf/shake.h>
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

#define FLAG_ABSORBING 'A'
#define FLAG_SQUEEZING 'Z'

/** Constants. **/
static const uint8_t pi[24] = {
    10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
    15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
};

#define RC_B(x,n) ((((x##ull)>>n)&1)<<((1<<n)-1))
#define RC_X(x) (RC_B(x,0)|RC_B(x,1)|RC_B(x,2)|RC_B(x,3)|RC_B(x,4)|RC_B(x,5)|RC_B(x,6))
static const uint64_t RC[24] = {
    RC_X(0x01), RC_X(0x1a), RC_X(0x5e), RC_X(0x70), RC_X(0x1f), RC_X(0x21),
    RC_X(0x79), RC_X(0x55), RC_X(0x0e), RC_X(0x0c), RC_X(0x35), RC_X(0x26),
    RC_X(0x3f), RC_X(0x4f), RC_X(0x5d), RC_X(0x53), RC_X(0x52), RC_X(0x48),
    RC_X(0x16), RC_X(0x66), RC_X(0x79), RC_X(0x58), RC_X(0x21), RC_X(0x74)
};

static inline uint64_t rol(uint64_t x, int s) {
    return (x << s) | (x >> (64 - s));
}

47
/* Helper macros to unroll the permutation. */
48 49
#define REPEAT5(e) e e e e e
#define FOR51(v, e) v = 0; REPEAT5(e; v += 1;)
50
#ifndef SHAKE_NO_UNROLL_LOOPS
51 52
#    define FOR55(v, e) v = 0; REPEAT5(e; v += 5;)
#    define REPEAT24(e) e e e e e e e e e e e e e e e e e e e e e e e e
53 54 55 56
#else
#    define FOR55(v, e) for (v=0; v<25; v+= 5) { e; }
#    define REPEAT24(e) {int _j=0; for (_j=0; _j<24; _j++) { e }}
#endif
57 58

/*** The Keccak-f[1600] permutation ***/
59
void keccakf(kdomain_t state, uint8_t start_round) {
60 61 62 63 64 65
    uint64_t* a = state->w;
    uint64_t b[5] = {0}, t, u;
    uint8_t x, y, i;
    
    for (i=0; i<25; i++) a[i] = le64toh(a[i]);

66
    for (i = start_round; i < 24; i++) {
67 68 69
        FOR51(x, b[x] = 0; )
        FOR55(y, FOR51(x, b[x] ^= a[x + y]; ))
        FOR55(y, FOR51(x,
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
            a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1);
        ))
        // Rho and pi
        t = a[1];
        x = y = 0;
        REPEAT24(u = a[pi[x]]; y += x+1; a[pi[x]] = rol(t, y % 64); t = u; x++; )
        // Chi
        FOR55(y,
             FOR51(x, b[x] = a[y + x];)
             FOR51(x, a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]);)
        )
        // Iota
        a[0] ^= RC[i];
    }

    for (i=0; i<25; i++) a[i] = htole64(a[i]);
}

88
decaf_error_t decaf_sha3_update (
89
    struct decaf_keccak_sponge_s * __restrict__ decaf_sponge,
90 91 92
    const uint8_t *in,
    size_t len
) {
93 94 95
    assert(decaf_sponge->params->position < decaf_sponge->params->rate);
    assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state));
    assert(decaf_sponge->params->flags == FLAG_ABSORBING);
96
    while (len) {
97 98
        size_t cando = decaf_sponge->params->rate - decaf_sponge->params->position, i;
        uint8_t* state = &decaf_sponge->state->b[decaf_sponge->params->position];
99
        if (cando > len) {
Mike Hamburg's avatar
Mike Hamburg committed
100
            for (i = 0; i < len; i += 1) state[i] ^= in[i];
101
            decaf_sponge->params->position += len;
102
            break;
103
        } else {
Mike Hamburg's avatar
Mike Hamburg committed
104
            for (i = 0; i < cando; i += 1) state[i] ^= in[i];
105
            dokeccak(decaf_sponge);
106 107 108 109
            len -= cando;
            in += cando;
        }
    }
110
    return (decaf_sponge->params->flags == FLAG_ABSORBING) ? DECAF_SUCCESS : DECAF_FAILURE;
111 112
}

113
decaf_error_t decaf_sha3_output (
114
    decaf_keccak_sponge_t decaf_sponge,
115 116 117
    uint8_t * __restrict__ out,
    size_t len
) {
118
    decaf_error_t ret = DECAF_SUCCESS;
119 120
    assert(decaf_sponge->params->position < decaf_sponge->params->rate);
    assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state));
121
    
122
    if (decaf_sponge->params->max_out != 0xFF) {
123 124
        if (decaf_sponge->params->remaining >= len) {
            decaf_sponge->params->remaining -= len;
125
        } else {
126
            decaf_sponge->params->remaining = 0;
127 128
            ret = DECAF_FAILURE;
        }
129 130
    }
    
131
    switch (decaf_sponge->params->flags) {
132 133 134
    case FLAG_SQUEEZING: break;
    case FLAG_ABSORBING:
        {
135 136 137 138
            uint8_t* state = decaf_sponge->state->b;
            state[decaf_sponge->params->position] ^= decaf_sponge->params->pad;
            state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad;
            dokeccak(decaf_sponge);
139
            decaf_sponge->params->flags = FLAG_SQUEEZING;
140 141 142 143 144 145 146
            break;
        }
    default:
        assert(0);
    }
    
    while (len) {
147 148
        size_t cando = decaf_sponge->params->rate - decaf_sponge->params->position;
        uint8_t* state = &decaf_sponge->state->b[decaf_sponge->params->position];
149 150
        if (cando > len) {
            memcpy(out, state, len);
151
            decaf_sponge->params->position += len;
152
            return ret;
153 154
        } else {
            memcpy(out, state, cando);
155
            dokeccak(decaf_sponge);
156 157 158 159
            len -= cando;
            out += cando;
        }
    }
160
    return ret;
161 162
}

163
decaf_error_t decaf_sha3_final (
164
    decaf_keccak_sponge_t decaf_sponge,
165 166 167
    uint8_t * __restrict__ out,
    size_t len
) {
168
    decaf_error_t ret = decaf_sha3_output(decaf_sponge,out,len);
169
    decaf_sha3_reset(decaf_sponge);
170
    return ret;
171 172
}

173 174
void decaf_sha3_reset (
    decaf_keccak_sponge_t decaf_sponge
175
) {
176
    decaf_sponge_init(decaf_sponge, decaf_sponge->params);
177
    decaf_sponge->params->flags = FLAG_ABSORBING;
178
    decaf_sponge->params->remaining = decaf_sponge->params->max_out;
179 180
}

181
void decaf_sponge_destroy (decaf_keccak_sponge_t decaf_sponge) { decaf_bzero(decaf_sponge, sizeof(decaf_keccak_sponge_t)); }
182

183 184 185
void decaf_sponge_init (
    decaf_keccak_sponge_t decaf_sponge,
    const struct decaf_kparams_s *params
186
) {
187 188 189
    memset(decaf_sponge->state, 0, sizeof(decaf_sponge->state));
    decaf_sponge->params[0] = params[0];
    decaf_sponge->params->position = 0;
190 191
}

192
decaf_error_t decaf_sponge_hash (
193 194 195 196
    const uint8_t *in,
    size_t inlen,
    uint8_t *out,
    size_t outlen,
197
    const struct decaf_kparams_s *params
198
) {
199 200 201
    decaf_keccak_sponge_t decaf_sponge;
    decaf_sponge_init(decaf_sponge, params);
    decaf_sha3_update(decaf_sponge, in, inlen);
202
    decaf_error_t ret = decaf_sha3_output(decaf_sponge, out, outlen);
203
    decaf_sponge_destroy(decaf_sponge);
204
    return ret;
205 206 207
}

#define DEFSHAKE(n) \
208
    const struct decaf_kparams_s DECAF_SHAKE##n##_params_s = \
209
        { 0, FLAG_ABSORBING, 200-n/4, 0, 0x1f, 0x80, 0xFF, 0xFF };
210 211
    
#define DEFSHA3(n) \
212
    const struct decaf_kparams_s DECAF_SHA3_##n##_params_s = \
213
        { 0, FLAG_ABSORBING, 200-n/4, 0, 0x06, 0x80, n/8, n/8 };
214

215 216
size_t decaf_sponge_default_output_bytes (
    const decaf_keccak_sponge_t s
217
) {
218
    return (s->params->max_out == 0xFF)
219 220 221 222
        ? (200-s->params->rate)
        : ((200-s->params->rate)/2);
}

223 224
size_t decaf_sponge_max_output_bytes (
    const decaf_keccak_sponge_t s
225
) {
226
    return (s->params->max_out == 0xFF)
227
        ? SIZE_MAX
Mike Hamburg's avatar
Mike Hamburg committed
228
        : (size_t)((200-s->params->rate)/2);
229 230
}

231 232 233 234 235 236 237
DEFSHAKE(128)
DEFSHAKE(256)
DEFSHA3(224)
DEFSHA3(256)
DEFSHA3(384)
DEFSHA3(512)

Michael Hamburg's avatar
Michael Hamburg committed
238
/* FUTURE: Keyak instances, etc */