modernc.org/ccgo/v3@v3.16.14/lib/testdata/CompCert-3.6/test/c/sha3.c (about) 1 /* SHA-3 (Keccak) cryptographic hash function */ 2 /* Code adapted from the "readable" implementation written by 3 Markku-Juhani O. Saarinen <mjos@iki.fi> */ 4 5 #include <stdio.h> 6 #include <string.h> 7 8 typedef unsigned long long uint64; 9 typedef unsigned char uint8; 10 11 #define KECCAK_ROUNDS 24 12 13 #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) 14 15 const uint64 keccakf_rndc[24] = 16 { 17 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 18 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 19 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 20 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 21 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 22 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 23 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 24 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 25 }; 26 27 const int keccakf_rotc[24] = 28 { 29 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 30 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 31 }; 32 33 const int keccakf_piln[24] = 34 { 35 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 36 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 37 }; 38 39 // update the state with KECCAK_ROUND rounds 40 41 void keccakf(uint64 st[25]) 42 { 43 int j, round; 44 uint64 t, bc[5]; 45 46 for (round = 0; round < KECCAK_ROUNDS; round++) { 47 48 // Theta 49 #define THETA1(i) \ 50 bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20] 51 52 THETA1(0); THETA1(1); THETA1(2); THETA1(3); THETA1(4); 53 54 #define THETA2(i) \ 55 t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \ 56 st[0 + i] ^= t; \ 57 st[5 + i] ^= t; \ 58 st[10 + i] ^= t; \ 59 st[15 + i] ^= t; \ 60 st[20 + i] ^= t 61 62 THETA2(0); THETA2(1); THETA2(2); THETA2(3); THETA2(4); 63 64 65 // Rho Pi 66 67 #define RHOPI(i, rotc) \ 68 j = keccakf_piln[i]; \ 69 bc[0] = st[j]; \ 70 st[j] = ROTL64(t, rotc); \ 71 t = bc[0] 72 73 t = st[1]; 74 RHOPI(0, 1); RHOPI(1, 3); RHOPI(2, 6); RHOPI(3, 10); 75 RHOPI(4, 15); RHOPI(5, 21); RHOPI(6, 28); RHOPI(7, 36); 76 RHOPI(8, 45); RHOPI(9, 55); RHOPI(10, 2); RHOPI(11, 14); 77 RHOPI(12, 27); RHOPI(13, 41); RHOPI(14, 56); RHOPI(15, 8); 78 RHOPI(16, 25); RHOPI(17, 43); RHOPI(18, 62); RHOPI(19, 18); 79 RHOPI(20, 39); RHOPI(21, 61); RHOPI(22, 20); RHOPI(23, 44); 80 81 // Chi 82 83 #define CHI1(i,j) \ 84 bc[i] = st[j + i] 85 #define CHI2(i,j) \ 86 st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5] 87 88 for (j = 0; j < 25; j += 5) { 89 CHI1(0,j); CHI1(1,j); CHI1(2,j); CHI1(3,j); CHI1(4,j); 90 CHI2(0,j); CHI2(1,j); CHI2(2,j); CHI2(3,j); CHI2(4,j); 91 } 92 93 // Iota 94 st[0] ^= keccakf_rndc[round]; 95 } 96 } 97 98 // read a 64-bit integer in little endian at the given address 99 100 static inline uint64 get64le(const uint8 *p) 101 { 102 unsigned int l = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 103 unsigned int h = p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24); 104 return l | ((uint64) h << 32); 105 } 106 107 // write a 64-bit integer in little endian at the given address 108 109 static inline void set64le(uint8 * p, uint64 x) 110 { 111 p[0] = x; p[1] = x >> 8; p[2] = x >> 16; p[3] = x >> 24; 112 p[4] = x >> 32; p[5] = x >> 40; p[6] = x >> 48; p[7] = x >> 56; 113 } 114 115 // compute a keccak hash (md) of the given byte length from "in" 116 117 void keccak(const uint8 *in, int inlen, uint8 *md, int mdlen) 118 { 119 uint64 st[25]; 120 uint8 temp[144]; 121 int i, rsiz, rsizw; 122 123 rsiz = 200 - 2 * mdlen; 124 rsizw = rsiz / 8; 125 126 memset(st, 0, sizeof(st)); 127 128 for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { 129 for (i = 0; i < rsizw; i++) 130 st[i] ^= get64le(in + i * 8); 131 keccakf(st); 132 } 133 134 // last block and padding 135 memcpy(temp, in, inlen); 136 temp[inlen++] = 1; 137 memset(temp + inlen, 0, rsiz - inlen); 138 temp[rsiz - 1] |= 0x80; 139 140 for (i = 0; i < rsizw; i++) 141 st[i] ^= get64le(temp + i * 8); 142 143 keccakf(st); 144 145 for(i = 0; i < 8; i++) 146 set64le(temp + i * 8, st[i]); 147 148 memcpy (md, temp, mdlen); 149 } 150 151 // test vectors 152 153 typedef struct { 154 int mdlen; 155 char *msgstr; 156 uint8 md[64]; 157 } test_triplet_t; 158 159 test_triplet_t testvec[4] = { 160 { 161 28, "Keccak-224 Test Hash", { 162 0x30, 0x04, 0x5B, 0x34, 0x94, 0x6E, 0x1B, 0x2E, 163 0x09, 0x16, 0x13, 0x36, 0x2F, 0xD2, 0x2A, 0xA0, 164 0x8E, 0x2B, 0xEA, 0xFE, 0xC5, 0xE8, 0xDA, 0xEE, 165 0x42, 0xC2, 0xE6, 0x65 } 166 }, { 167 32, "Keccak-256 Test Hash", { 168 0xA8, 0xD7, 0x1B, 0x07, 0xF4, 0xAF, 0x26, 0xA4, 169 0xFF, 0x21, 0x02, 0x7F, 0x62, 0xFF, 0x60, 0x26, 170 0x7F, 0xF9, 0x55, 0xC9, 0x63, 0xF0, 0x42, 0xC4, 171 0x6D, 0xA5, 0x2E, 0xE3, 0xCF, 0xAF, 0x3D, 0x3C } 172 }, { 173 48, "Keccak-384 Test Hash", { 174 0xE2, 0x13, 0xFD, 0x74, 0xAF, 0x0C, 0x5F, 0xF9, 175 0x1B, 0x42, 0x3C, 0x8B, 0xCE, 0xEC, 0xD7, 0x01, 176 0xF8, 0xDD, 0x64, 0xEC, 0x18, 0xFD, 0x6F, 0x92, 177 0x60, 0xFC, 0x9E, 0xC1, 0xED, 0xBD, 0x22, 0x30, 178 0xA6, 0x90, 0x86, 0x65, 0xBC, 0xD9, 0xFB, 0xF4, 179 0x1A, 0x99, 0xA1, 0x8A, 0x7D, 0x9E, 0x44, 0x6E } 180 }, { 181 64, "Keccak-512 Test Hash", { 182 0x96, 0xEE, 0x47, 0x18, 0xDC, 0xBA, 0x3C, 0x74, 183 0x61, 0x9B, 0xA1, 0xFA, 0x7F, 0x57, 0xDF, 0xE7, 184 0x76, 0x9D, 0x3F, 0x66, 0x98, 0xA8, 0xB3, 0x3F, 185 0xA1, 0x01, 0x83, 0x89, 0x70, 0xA1, 0x31, 0xE6, 186 0x21, 0xCC, 0xFD, 0x05, 0xFE, 0xFF, 0xBC, 0x11, 187 0x80, 0xF2, 0x63, 0xC2, 0x7F, 0x1A, 0xDA, 0xB4, 188 0x60, 0x95, 0xD6, 0xF1, 0x25, 0x33, 0x14, 0x72, 189 0x4B, 0x5C, 0xBF, 0x78, 0x28, 0x65, 0x8E, 0x6A } 190 } 191 }; 192 193 #define DATALEN 100000 194 #define NITER 25 195 196 int main() 197 { 198 static uint8 data[DATALEN]; 199 int i; 200 uint8 md[64]; 201 202 // test 203 204 for (i = 0; i < 4; i++) { 205 206 keccak((uint8 *) testvec[i].msgstr, 207 strlen(testvec[i].msgstr), 208 md, testvec[i].mdlen); 209 210 printf("SHA-3 %d %s\n", 211 testvec[i].mdlen * 8, 212 memcmp(md, testvec[i].md, testvec[i].mdlen) == 0 ? "passed" : "FAILED"); 213 214 } 215 216 // benchmark 217 for (i = 0; i < DATALEN; i++) data[i] = i; 218 for (i = 0; i < NITER; i++) 219 keccak(data, DATALEN, md, 64); 220 221 return 0; 222 } 223