1 /* 2 * Copyright (C) 2017 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #ifndef __KECCAK_H__ 17 #define __KECCAK_H__ 18 19 #include <libecc/words/words.h> 20 21 #define _KECCAK_ROTL_(x, y) (((x) << (y)) | ((x) >> ((sizeof(u64) * 8) - (y)))) 22 23 /* We handle the case where one of the shifts is more than 64-bit: in this 24 * case, behaviour is undefined as per ANSI C definition. In this case, we 25 * return the untouched input. 26 */ 27 #define KECCAK_ROTL(x, y) ((((y) < (sizeof(u64) * 8)) && ((y) > 0)) ? (_KECCAK_ROTL_(x, y)) : (x)) 28 29 /* 30 * Round transformation of the state. Notations are the 31 * same as the ones used in: 32 * http://keccak.noekeon.org/specs_summary.html 33 */ 34 #define KECCAK_WORD_LOG 6 35 #define KECCAK_ROUNDS (12 + (2 * KECCAK_WORD_LOG)) 36 #define KECCAK_SLICES 5 37 38 static const u64 keccak_rc[KECCAK_ROUNDS] = 39 { 40 0x0000000000000001ULL, 0x0000000000008082ULL, 41 0x800000000000808AULL, 0x8000000080008000ULL, 42 0x000000000000808BULL, 0x0000000080000001ULL, 43 0x8000000080008081ULL, 0x8000000000008009ULL, 44 0x000000000000008AULL, 0x0000000000000088ULL, 45 0x0000000080008009ULL, 0x000000008000000AULL, 46 0x000000008000808BULL, 0x800000000000008BULL, 47 0x8000000000008089ULL, 0x8000000000008003ULL, 48 0x8000000000008002ULL, 0x8000000000000080ULL, 49 0x000000000000800AULL, 0x800000008000000AULL, 50 0x8000000080008081ULL, 0x8000000000008080ULL, 51 0x0000000080000001ULL, 0x8000000080008008ULL 52 }; 53 54 static const u8 keccak_rot[KECCAK_SLICES][KECCAK_SLICES] = 55 { 56 { 0, 36, 3, 41, 18 }, 57 { 1, 44, 10, 45, 2 }, 58 { 62, 6, 43, 15, 61 }, 59 { 28, 55, 25, 21, 56 }, 60 { 27, 20, 39, 8, 14 }, 61 }; 62 63 64 /* Macro to handle endianness conversion */ 65 #define SWAP64_Idx(a) ((sizeof(u64) * ((u8)(a) / sizeof(u64))) + (sizeof(u64) - 1 - ((u8)(a) % sizeof(u64)))) 66 67 #define Idx_slices(x, y) ((x) + (KECCAK_SLICES * (y))) 68 #define Idx(A, x, y) ((A)[Idx_slices(x, y)]) 69 70 #define KECCAKROUND(A, RC) do { \ 71 int x, y; \ 72 u64 tmp; \ 73 /* Temporary B, C and D arrays */ \ 74 u64 BCD[KECCAK_SLICES * KECCAK_SLICES]; \ 75 /* Theta step */ \ 76 for(x = 0; x < KECCAK_SLICES; x++){ \ 77 Idx(BCD, x, 0) = Idx(A, x, 0) ^ Idx(A, x, 1) ^ Idx(A, x, 2) ^ \ 78 Idx(A, x, 3) ^ Idx(A, x, 4); \ 79 } \ 80 for(x = 0; x < KECCAK_SLICES; x++){ \ 81 tmp = Idx(BCD, (x + 4) % 5, 0) ^ \ 82 KECCAK_ROTL(Idx(BCD, (x + 1) % 5, 0), 1); \ 83 for(y = 0; y < KECCAK_SLICES; y++){ \ 84 Idx(A, x, y) ^= tmp; \ 85 } \ 86 } \ 87 /* Rho and Pi steps */ \ 88 for(x = 0; x < KECCAK_SLICES; x++){ \ 89 for(y = 0; y < KECCAK_SLICES; y++){ \ 90 Idx(BCD, y, ((2*x)+(3*y)) % 5) = \ 91 KECCAK_ROTL(Idx(A, x, y), keccak_rot[x][y]); \ 92 } \ 93 } \ 94 /* Chi step */ \ 95 for(x = 0; x < KECCAK_SLICES; x++){ \ 96 for(y = 0; y < KECCAK_SLICES; y++){ \ 97 Idx(A, x, y) = Idx(BCD, x, y) ^ \ 98 (~Idx(BCD, (x+1) % 5, y) & Idx(BCD, (x+2)%5, y)); \ 99 } \ 100 } \ 101 /* Iota step */ \ 102 Idx(A, 0, 0) ^= (RC); \ 103 } while(0) 104 105 #define KECCAKF(A) do { \ 106 int round; \ 107 for(round = 0; round < KECCAK_ROUNDS; round++){ \ 108 KECCAKROUND(A, keccak_rc[round]); \ 109 } \ 110 } while(0) 111 112 #endif /* __KECCAK_H__ */ 113