70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* -------------------------------------------------------------------------
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Works when compiled for either 32-bit or 64-bit targets, optimized for
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Based on code from http://keccak.noekeon.org/ .
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * I place the code that I wrote into public domain, free to use.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * I would appreciate if you give credits to this work if you used it to
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * write or test * your code.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Aug 2015. Andrey Jivsov. crypto@brainhub.org
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Modified for Dovecot oy use
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Oct 2016. Aki Tuomi <aki.tuomi@dovecot.fi>
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * ---------------------------------------------------------------------- */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* The following state definition should normally be in a separate
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * header file
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (((x) << (y)) | ((x) >> ((sizeof(uint64_t)*8) - (y))))
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x0000000000000001UL), SHA3_CONST(0x0000000000008082UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x800000000000808aUL), SHA3_CONST(0x8000000080008000UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x000000000000808bUL), SHA3_CONST(0x0000000080000001UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008009UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x000000000000008aUL), SHA3_CONST(0x0000000000000088UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x0000000080008009UL), SHA3_CONST(0x000000008000000aUL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x000000008000808bUL), SHA3_CONST(0x800000000000008bUL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x8000000000008089UL), SHA3_CONST(0x8000000000008003UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x8000000000008002UL), SHA3_CONST(0x8000000000000080UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x000000000000800aUL), SHA3_CONST(0x800000008000000aUL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008080UL),
70ee483d320a270993b56c713e350b736edd753fAki Tuomi SHA3_CONST(0x0000000080000001UL), SHA3_CONST(0x8000000080008008UL)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* generally called after SHA3_KECCAK_SPONGE_WORDS-ctx->capacityWords words
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * are XORed into the state s
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < 5; i++)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < 5; i++) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi s[j + i] ^= t;
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* Rho Pi */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < 24; i++) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < 5; i++)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi bc[i] = s[j + i];
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < 5; i++)
211c638d81d382517d196ad47565e0d85012c927klemens/* *************************** Public Interface ************************ */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi ctx->capacityWords = 2 * 256 / (8 * sizeof(uint64_t));
70ee483d320a270993b56c713e350b736edd753fAki Tuomi ctx->capacityWords = 2 * 512 / (8 * sizeof(uint64_t));
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid sha3_loop(void *context, const void *data, size_t len)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* 0...7 -- how much is needed to have a word */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi i_assert(ctx->wordIndex < sizeof(ctx->s) / sizeof(ctx->s[0]));
70ee483d320a270993b56c713e350b736edd753fAki Tuomi if(len < old_tail) { /* have no complete word or haven't started
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * the word yet */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* endian-independent code follows: */
a05819736f348d0c5ac8b4966ac6b04c21e1a391Timo Sirainen while (len > 0) {
34742a4b92c16c300e3d75731685b678712340b2Timo Sirainen if(old_tail != 0) { /* will have one word to process */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* endian-independent code follows: */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* now ready to add saved to the sponge */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* now work in full words directly from input */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < words; i++, buf += sizeof(uint64_t)) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords)) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* finally, save the partial word */
a05819736f348d0c5ac8b4966ac6b04c21e1a391Timo Sirainen while (tail > 0) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi/* This is simply the 'update' with the padding block.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * bytes are always present, but they can be the same byte.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * use 1<<2 below. The 0x02 below corresponds to the suffix 01.
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * Overall, we feed 0, then 1, and finally 1 to start padding. Without
70ee483d320a270993b56c713e350b736edd753fAki Tuomi * M || 01, we would simply use 1 to start padding. */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi /* SHA3 version */
70ee483d320a270993b56c713e350b736edd753fAki Tuomi (ctx->saved ^ ((uint64_t) ((uint64_t) (0x02 | (1 << 2)) <<
70ee483d320a270993b56c713e350b736edd753fAki Tuomi ctx->s[SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords - 1] ^=
70ee483d320a270993b56c713e350b736edd753fAki Tuomi for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
70ee483d320a270993b56c713e350b736edd753fAki Tuomi const unsigned t2 = (uint32_t) ((ctx->s[i] >> 16) >> 16);
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned char digest[STATIC_ARRAY SHA256_RESULTLEN])
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned char digest[STATIC_ARRAY SHA512_RESULTLEN])
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid sha3_256_get_digest(const void *data, size_t size,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned char digest[STATIC_ARRAY SHA256_RESULTLEN])
70ee483d320a270993b56c713e350b736edd753fAki Tuomivoid sha3_512_get_digest(const void *data, size_t size,
70ee483d320a270993b56c713e350b736edd753fAki Tuomi unsigned char digest[STATIC_ARRAY SHA512_RESULTLEN])
70ee483d320a270993b56c713e350b736edd753fAki Tuomistatic void hash_method_init_sha3_256(void *context)
70ee483d320a270993b56c713e350b736edd753fAki Tuomistatic void hash_method_loop_sha3(void *context, const void *data, size_t size)
70ee483d320a270993b56c713e350b736edd753fAki Tuomistatic void hash_method_result_sha3_256(void *context, unsigned char *result_r)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi sizeof(struct sha3_ctx),
70ee483d320a270993b56c713e350b736edd753fAki Tuomistatic void hash_method_init_sha3_512(void *context)
70ee483d320a270993b56c713e350b736edd753fAki Tuomistatic void hash_method_result_sha3_512(void *context, unsigned char *result_r)
70ee483d320a270993b56c713e350b736edd753fAki Tuomi sizeof(struct sha3_ctx),