You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

725 lines
21 KiB

  1. /**
  2. * @cond internal
  3. * @file shake.c
  4. * @copyright
  5. * Uses public domain code by Mathias Panzenböck \n
  6. * Uses CC0 code by David Leon Gil, 2015 \n
  7. * Copyright (c) 2015 Cryptography Research, Inc. \n
  8. * Released under the MIT License. See LICENSE.txt for license information.
  9. * @author Mike Hamburg
  10. * @brief SHA-3-n and SHAKE-n instances.
  11. * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change.
  12. */
  13. #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
  14. #define _BSD_SOURCE 1 /* for endian */
  15. #include <assert.h>
  16. #include <stdint.h>
  17. #include <string.h>
  18. /* to open and read from /dev/urandom */
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include <errno.h>
  23. #include <unistd.h>
  24. /* Subset of Mathias Panzenböck's portable endian code, public domain */
  25. #if defined(__linux__) || defined(__CYGWIN__)
  26. # include <endian.h>
  27. #elif defined(__OpenBSD__)
  28. # include <sys/endian.h>
  29. #elif defined(__APPLE__)
  30. # include <libkern/OSByteOrder.h>
  31. # define htole64(x) OSSwapHostToLittleInt64(x)
  32. # define le64toh(x) OSSwapLittleToHostInt64(x)
  33. #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  34. # include <sys/endian.h>
  35. # define le64toh(x) letoh64(x)
  36. #elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
  37. # include <winsock2.h>
  38. # include <sys/param.h>
  39. # if BYTE_ORDER == LITTLE_ENDIAN
  40. # define htole64(x) (x)
  41. # define le64toh(x) (x)
  42. # elif BYTE_ORDER == BIG_ENDIAN
  43. # define htole64(x) __builtin_bswap64(x)
  44. # define le64toh(x) __builtin_bswap64(x)
  45. # else
  46. # error byte order not supported
  47. # endif
  48. #else
  49. # error platform not supported
  50. #endif
  51. /* The internal, non-opaque definition of the sponge struct. */
  52. typedef union {
  53. uint64_t w[25]; uint8_t b[25*8];
  54. } kdomain_t[1];
  55. typedef struct kparams_s {
  56. uint8_t position, flags, rate, startRound, pad, ratePad, maxOut, client;
  57. } kparams_t[1];
  58. typedef struct keccak_sponge_s {
  59. kdomain_t state;
  60. kparams_t params;
  61. } keccak_sponge_t[1];
  62. #define INTERNAL_SPONGE_STRUCT 1
  63. #include "shake.h"
  64. #define FLAG_ABSORBING 'A'
  65. #define FLAG_SQUEEZING 'Z'
  66. #define FLAG_RNG_SQU 'R'
  67. #define FLAG_DET_SQU 'D'
  68. #define FLAG_RNG_ABS 'r'
  69. #define FLAG_DET_ABS 'd'
  70. #define FLAG_RNG_UNI 'u'
  71. #define FLAG_DET_UNI 'g'
  72. /** Constants. **/
  73. static const uint8_t pi[24] = {
  74. 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
  75. 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
  76. };
  77. #define RC_B(x,n) ((((x##ull)>>n)&1)<<((1<<n)-1))
  78. #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))
  79. static const uint64_t RC[24] = {
  80. RC_X(0x01), RC_X(0x1a), RC_X(0x5e), RC_X(0x70), RC_X(0x1f), RC_X(0x21),
  81. RC_X(0x79), RC_X(0x55), RC_X(0x0e), RC_X(0x0c), RC_X(0x35), RC_X(0x26),
  82. RC_X(0x3f), RC_X(0x4f), RC_X(0x5d), RC_X(0x53), RC_X(0x52), RC_X(0x48),
  83. RC_X(0x16), RC_X(0x66), RC_X(0x79), RC_X(0x58), RC_X(0x21), RC_X(0x74)
  84. };
  85. static inline uint64_t rol(uint64_t x, int s) {
  86. return (x << s) | (x >> (64 - s));
  87. }
  88. /* Helper macros to unroll the permutation. */
  89. #define REPEAT5(e) e e e e e
  90. #define FOR51(v, e) v = 0; REPEAT5(e; v += 1;)
  91. #ifndef SHAKE_NO_UNROLL_LOOPS
  92. # define FOR55(v, e) v = 0; REPEAT5(e; v += 5;)
  93. # 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
  94. #else
  95. # define FOR55(v, e) for (v=0; v<25; v+= 5) { e; }
  96. # define REPEAT24(e) {int _j=0; for (_j=0; _j<24; _j++) { e }}
  97. #endif
  98. /*** The Keccak-f[1600] permutation ***/
  99. static void
  100. __attribute__((noinline))
  101. keccakf(kdomain_t state, uint8_t startRound) {
  102. uint64_t* a = state->w;
  103. uint64_t b[5] = {0}, t, u;
  104. uint8_t x, y, i;
  105. for (i=0; i<25; i++) a[i] = le64toh(a[i]);
  106. for (i = startRound; i < 24; i++) {
  107. FOR51(x, b[x] = 0; FOR55(y, b[x] ^= a[x + y];))
  108. FOR51(x, FOR55(y,
  109. a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1);
  110. ))
  111. // Rho and pi
  112. t = a[1];
  113. x = y = 0;
  114. REPEAT24(u = a[pi[x]]; y += x+1; a[pi[x]] = rol(t, y % 64); t = u; x++; )
  115. // Chi
  116. FOR55(y,
  117. FOR51(x, b[x] = a[y + x];)
  118. FOR51(x, a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]);)
  119. )
  120. // Iota
  121. a[0] ^= RC[i];
  122. }
  123. for (i=0; i<25; i++) a[i] = htole64(a[i]);
  124. }
  125. static inline void dokeccak (keccak_sponge_t sponge) {
  126. keccakf(sponge->state, sponge->params->startRound);
  127. sponge->params->position = 0;
  128. }
  129. void sha3_update (
  130. struct keccak_sponge_s * __restrict__ sponge,
  131. const uint8_t *in,
  132. size_t len
  133. ) {
  134. if (!len) return;
  135. assert(sponge->params->position < sponge->params->rate);
  136. assert(sponge->params->rate < sizeof(sponge->state));
  137. assert(sponge->params->flags == FLAG_ABSORBING);
  138. while (len) {
  139. size_t cando = sponge->params->rate - sponge->params->position, i;
  140. uint8_t* state = &sponge->state->b[sponge->params->position];
  141. if (cando > len) {
  142. for (i = 0; i < len; i += 1) state[i] ^= in[i];
  143. sponge->params->position += len;
  144. return;
  145. } else {
  146. for (i = 0; i < cando; i += 1) state[i] ^= in[i];
  147. dokeccak(sponge);
  148. len -= cando;
  149. in += cando;
  150. }
  151. }
  152. }
  153. void sha3_output (
  154. keccak_sponge_t sponge,
  155. uint8_t * __restrict__ out,
  156. size_t len
  157. ) {
  158. assert(sponge->params->position < sponge->params->rate);
  159. assert(sponge->params->rate < sizeof(sponge->state));
  160. if (sponge->params->maxOut != 0xFF) {
  161. assert(sponge->params->maxOut >= len);
  162. sponge->params->maxOut -= len;
  163. }
  164. switch (sponge->params->flags) {
  165. case FLAG_SQUEEZING: break;
  166. case FLAG_ABSORBING:
  167. {
  168. uint8_t* state = sponge->state->b;
  169. state[sponge->params->position] ^= sponge->params->pad;
  170. state[sponge->params->rate - 1] ^= sponge->params->ratePad;
  171. dokeccak(sponge);
  172. break;
  173. }
  174. default:
  175. assert(0);
  176. }
  177. while (len) {
  178. size_t cando = sponge->params->rate - sponge->params->position;
  179. uint8_t* state = &sponge->state->b[sponge->params->position];
  180. if (cando > len) {
  181. memcpy(out, state, len);
  182. sponge->params->position += len;
  183. return;
  184. } else {
  185. memcpy(out, state, cando);
  186. dokeccak(sponge);
  187. len -= cando;
  188. out += cando;
  189. }
  190. }
  191. }
  192. void sponge_destroy (keccak_sponge_t sponge) { decaf_bzero(sponge, sizeof(keccak_sponge_t)); }
  193. void sponge_init (
  194. keccak_sponge_t sponge,
  195. const struct kparams_s *params
  196. ) {
  197. memset(sponge->state, 0, sizeof(sponge->state));
  198. sponge->params[0] = params[0];
  199. }
  200. void sponge_hash (
  201. const uint8_t *in,
  202. size_t inlen,
  203. uint8_t *out,
  204. size_t outlen,
  205. const struct kparams_s *params
  206. ) {
  207. keccak_sponge_t sponge;
  208. sponge_init(sponge, params);
  209. sha3_update(sponge, in, inlen);
  210. sha3_output(sponge, out, outlen);
  211. sponge_destroy(sponge);
  212. }
  213. #define DEFSHAKE(n) \
  214. const struct kparams_s SHAKE##n##_params_s = \
  215. { 0, FLAG_ABSORBING, 200-n/4, 0, 0x1f, 0x80, 0xFF, 0 };
  216. #define DEFSHA3(n) \
  217. const struct kparams_s SHA3_##n##_params_s = \
  218. { 0, FLAG_ABSORBING, 200-n/4, 0, 0x06, 0x80, n/8, 0 };
  219. size_t sponge_default_output_bytes (
  220. const keccak_sponge_t s
  221. ) {
  222. return (s->params->maxOut == 0xFF)
  223. ? (200-s->params->rate)
  224. : ((200-s->params->rate)/2);
  225. }
  226. DEFSHAKE(128)
  227. DEFSHAKE(256)
  228. DEFSHA3(224)
  229. DEFSHA3(256)
  230. DEFSHA3(384)
  231. DEFSHA3(512)
  232. /** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */
  233. static void get_cpu_entropy(uint8_t *entropy, size_t len) {
  234. # if (defined(__i386__) || defined(__x86_64__))
  235. static char tested = 0, have_rdrand = 0;
  236. if (!tested) {
  237. u_int32_t a,b,c,d;
  238. a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
  239. have_rdrand = (c>>30)&1;
  240. tested = 1;
  241. }
  242. if (have_rdrand) {
  243. # if defined(__x86_64__)
  244. uint64_t out, a=0, *eo = (uint64_t *)entropy;
  245. # elif defined(__i386__)
  246. uint32_t out, a=0, *eo = (uint64_t *)entropy;
  247. #endif
  248. len /= sizeof(out);
  249. uint32_t tries;
  250. for (tries = 100+len; tries && len; len--, eo++) {
  251. for (a = 0; tries && !a; tries--) {
  252. __asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" );
  253. }
  254. *eo ^= out;
  255. }
  256. } else if (len>8) {
  257. uint64_t out;
  258. __asm__ __volatile__ ("rdtsc" : "=A"(out));
  259. *(uint64_t*) entropy ^= out;
  260. }
  261. #else
  262. (void) entropy;
  263. (void) len;
  264. #endif
  265. }
  266. void spongerng_next (
  267. keccak_sponge_t sponge,
  268. uint8_t * __restrict__ out,
  269. size_t len
  270. ) {
  271. assert(sponge->params->position < sponge->params->rate);
  272. assert(sponge->params->rate < sizeof(sponge->state));
  273. switch(sponge->params->flags) {
  274. case FLAG_DET_SQU: case FLAG_RNG_SQU: break;
  275. case FLAG_DET_ABS: case FLAG_RNG_ABS:
  276. {
  277. uint8_t* state = sponge->state->b;
  278. state[sponge->params->position] ^= sponge->params->pad;
  279. state[sponge->params->rate - 1] ^= sponge->params->ratePad;
  280. dokeccak(sponge);
  281. sponge->params->flags = (sponge->params->flags == FLAG_DET_ABS) ? FLAG_DET_SQU : FLAG_RNG_SQU;
  282. break;
  283. }
  284. default: assert(0);
  285. };
  286. while (len) {
  287. size_t cando = sponge->params->rate - sponge->params->position;
  288. uint8_t* state = &sponge->state->b[sponge->params->position];
  289. if (cando > len) {
  290. memcpy(out, state, len);
  291. memset(state, 0, len);
  292. sponge->params->position += len;
  293. return;
  294. } else {
  295. memcpy(out, state, cando);
  296. memset(state, 0, cando);
  297. if (sponge->params->flags == FLAG_RNG_SQU)
  298. get_cpu_entropy(sponge->state->b, 32);
  299. dokeccak(sponge);
  300. len -= cando;
  301. out += cando;
  302. }
  303. }
  304. /* Anti-rollback */
  305. if (sponge->params->position < 32) {
  306. memset(&sponge->state->b, 0, 32);
  307. sponge->params->position = 32;
  308. }
  309. }
  310. void spongerng_stir (
  311. keccak_sponge_t sponge,
  312. const uint8_t * __restrict__ in,
  313. size_t len
  314. ) {
  315. assert(sponge->params->position < sponge->params->rate);
  316. assert(sponge->params->rate < sizeof(sponge->state));
  317. switch(sponge->params->flags) {
  318. case FLAG_RNG_SQU:
  319. get_cpu_entropy(sponge->state->b, 32);
  320. /* fall through */
  321. case FLAG_DET_SQU:
  322. sponge->params->flags = (sponge->params->flags == FLAG_DET_SQU) ? FLAG_DET_ABS : FLAG_RNG_ABS;
  323. dokeccak(sponge);
  324. break;
  325. case FLAG_DET_ABS: case FLAG_RNG_ABS: break;
  326. case FLAG_DET_UNI: case FLAG_RNG_UNI: break;
  327. default: assert(0);
  328. };
  329. while (len) {
  330. size_t i;
  331. size_t cando = sponge->params->rate - sponge->params->position;
  332. uint8_t* state = &sponge->state->b[sponge->params->position];
  333. if (cando > len) {
  334. for (i = 0; i < len; i += 1) state[i] ^= in[i];
  335. sponge->params->position += len;
  336. return;
  337. } else {
  338. for (i = 0; i < cando; i += 1) state[i] ^= in[i];
  339. dokeccak(sponge);
  340. len -= cando;
  341. in += cando;
  342. }
  343. }
  344. }
  345. static const struct kparams_s spongerng_params = {
  346. 0, FLAG_RNG_UNI, 200-256/4, 0, 0x06, 0x80, 0xFF, 0
  347. };
  348. void spongerng_init_from_buffer (
  349. keccak_sponge_t sponge,
  350. const uint8_t * __restrict__ in,
  351. size_t len,
  352. int deterministic
  353. ) {
  354. sponge_init(sponge, &spongerng_params);
  355. sponge->params->flags = deterministic ? FLAG_DET_ABS : FLAG_RNG_ABS;
  356. spongerng_stir(sponge, in, len);
  357. }
  358. int spongerng_init_from_file (
  359. keccak_sponge_t sponge,
  360. const char *file,
  361. size_t len,
  362. int deterministic
  363. ) {
  364. sponge_init(sponge, &spongerng_params);
  365. sponge->params->flags = deterministic ? FLAG_DET_UNI : FLAG_RNG_UNI;
  366. if (!len) return -2;
  367. int fd = open(file, O_RDONLY);
  368. if (fd < 0) return errno ? errno : -1;
  369. uint8_t buffer[128];
  370. while (len) {
  371. ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len);
  372. if (red <= 0) {
  373. close(fd);
  374. return errno ? errno : -1;
  375. }
  376. spongerng_stir(sponge,buffer,red);
  377. len -= red;
  378. };
  379. close(fd);
  380. sponge->params->flags = deterministic ? FLAG_DET_ABS : FLAG_RNG_ABS;
  381. return 0;
  382. }
  383. int spongerng_init_from_dev_urandom (
  384. keccak_sponge_t sponge
  385. ) {
  386. return spongerng_init_from_file(sponge, "/dev/urandom", 64, 0);
  387. }
  388. const struct kparams_s STROBE_128 = { 0, 0, 200-128/4, 0, 0, 0, 0, 0 };
  389. const struct kparams_s STROBE_256 = { 0, 0, 200-256/4, 0, 0, 0, 0, 0 };
  390. const struct kparams_s STROBE_KEYED_256 = { 0, 0, 200-256/4, 12, 0, 0, 0, 0 };
  391. const struct kparams_s STROBE_KEYED_128 = { 0, 0, 200-128/4, 12, 0, 0, 0, 0 };
  392. /* Strobe is different in that its rate is padded by one byte. */
  393. void strobe_init(
  394. keccak_sponge_t sponge,
  395. const struct kparams_s *params,
  396. uint8_t am_client
  397. ) {
  398. sponge_init(sponge,params);
  399. sponge->params->client = !!am_client;
  400. }
  401. static void strobe_duplex (
  402. keccak_sponge_t sponge,
  403. unsigned char *out,
  404. const unsigned char *in,
  405. size_t len
  406. ) {
  407. unsigned j;
  408. while (len) {
  409. assert(sponge->params->rate >= sponge->params->position);
  410. size_t cando = sponge->params->rate - sponge->params->position;
  411. uint8_t* state = &sponge->state->b[sponge->params->position];
  412. if (cando >= len) {
  413. for (j=0; in && j<len; j++) state[j]^=in[j];
  414. if (out) memcpy(out, state, len);
  415. sponge->params->position += len;
  416. return;
  417. } else {
  418. if (in) {
  419. for (j=0; j<cando; j++) state[j]^=in[j];
  420. in += cando;
  421. }
  422. if (out) {
  423. memcpy(out, state, cando);
  424. out += cando;
  425. }
  426. state[cando] ^= 0x1;
  427. dokeccak(sponge);
  428. len -= cando;
  429. }
  430. }
  431. }
  432. static void strobe_forget (
  433. keccak_sponge_t sponge,
  434. size_t len
  435. ) {
  436. assert(sponge->params->rate < sizeof(sponge->state));
  437. assert(sponge->params->position <= sponge->params->rate);
  438. if (sizeof(sponge->state) - sponge->params->rate < len) {
  439. /** Tiny case */
  440. unsigned char tmp[len];
  441. strobe_duplex(sponge,tmp,NULL,len);
  442. if (sponge->params->position) dokeccak(sponge);
  443. strobe_duplex(sponge,tmp,NULL,len);
  444. decaf_bzero(tmp,len);
  445. } else {
  446. if (sponge->params->rate < len + sponge->params->position) {
  447. dokeccak(sponge);
  448. }
  449. memset(sponge->state->b, 0, len);
  450. sponge->params->position = len;
  451. }
  452. }
  453. static void strobe_unduplex (
  454. keccak_sponge_t sponge,
  455. unsigned char *out,
  456. const unsigned char *in,
  457. size_t len
  458. ) {
  459. unsigned j;
  460. while (len) {
  461. assert(sponge->params->rate >= sponge->params->position);
  462. size_t cando = sponge->params->rate - sponge->params->position;
  463. uint8_t* state = &sponge->state->b[sponge->params->position];
  464. if (cando >= len) {
  465. for (j=0; in && j<len; j++) {
  466. unsigned char c = in[j];
  467. out[j] = in[j] ^ state[j];
  468. state[j] = c;
  469. }
  470. sponge->params->position += len;
  471. return;
  472. } else {
  473. for (j=0; in && j<cando; j++) {
  474. unsigned char c = in[j];
  475. out[j] = in[j] ^ state[j];
  476. state[j] = c;
  477. }
  478. state[j] ^= 0x1;
  479. dokeccak(sponge);
  480. len -= cando;
  481. }
  482. }
  483. }
  484. enum { KEY=1, NONCE, AD, PLAINTEXT, CIPHERTEXT, TAGFORGET, DIVERSIFIER, PRNG, FORK, JOIN, RESPEC };
  485. #define CLIENT_TO_SERVER 0
  486. #define SERVER_TO_CLIENT 0x80
  487. static decaf_bool_t strobe_control_word (
  488. keccak_sponge_t sponge,
  489. const unsigned char *control,
  490. size_t len,
  491. uint8_t more
  492. ) {
  493. assert(sponge->params->rate < sizeof(sponge->state));
  494. decaf_bool_t ret = DECAF_SUCCESS;
  495. if (!more) {
  496. strobe_duplex(sponge,NULL,control,len);
  497. sponge->state->b[sponge->params->position] ^= 0x1;
  498. sponge->state->b[sponge->params->rate] ^= 0x2;
  499. dokeccak(sponge);
  500. sponge->params->flags = control[len-1];
  501. } else if (sponge->params->flags && sponge->params->flags != control[len-1]) {
  502. ret = DECAF_FAILURE;
  503. }
  504. sponge->params->flags = control[len-1];
  505. return ret;
  506. }
  507. decaf_bool_t strobe_encrypt (
  508. keccak_sponge_t sponge,
  509. unsigned char *out,
  510. const unsigned char *in,
  511. size_t len,
  512. uint8_t more
  513. ) {
  514. unsigned char control[] = { CIPHERTEXT |
  515. (sponge->params->client ? CLIENT_TO_SERVER : SERVER_TO_CLIENT)
  516. };
  517. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  518. strobe_duplex(sponge, out, in, len);
  519. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  520. return ret;
  521. }
  522. decaf_bool_t strobe_decrypt (
  523. keccak_sponge_t sponge,
  524. unsigned char *out,
  525. const unsigned char *in,
  526. size_t len,
  527. uint8_t more
  528. ) {
  529. unsigned char control[] = { CIPHERTEXT |
  530. (sponge->params->client ? SERVER_TO_CLIENT : CLIENT_TO_SERVER)
  531. };
  532. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  533. strobe_unduplex(sponge, out, in, len);
  534. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  535. return ret;
  536. }
  537. decaf_bool_t strobe_plaintext (
  538. keccak_sponge_t sponge,
  539. const unsigned char *in,
  540. size_t len,
  541. uint8_t iSent,
  542. uint8_t more
  543. ) {
  544. unsigned char control[] = { PLAINTEXT |
  545. ((sponge->params->client == !!iSent) ? CLIENT_TO_SERVER : SERVER_TO_CLIENT)
  546. };
  547. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  548. strobe_duplex(sponge, NULL, in, len);
  549. return ret;
  550. }
  551. decaf_bool_t strobe_key (
  552. keccak_sponge_t sponge,
  553. const unsigned char *in,
  554. size_t len,
  555. uint8_t more
  556. ) {
  557. unsigned char control[] = { KEY };
  558. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  559. strobe_duplex(sponge, NULL, in, len);
  560. sponge->params->pad/*=keyed*/ = 1;
  561. return ret;
  562. }
  563. decaf_bool_t strobe_nonce (
  564. keccak_sponge_t sponge,
  565. const unsigned char *in,
  566. size_t len,
  567. uint8_t more
  568. ) {
  569. unsigned char control[] = { NONCE };
  570. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  571. strobe_duplex(sponge, NULL, in, len);
  572. return ret;
  573. }
  574. decaf_bool_t strobe_ad (
  575. keccak_sponge_t sponge,
  576. const unsigned char *in,
  577. size_t len,
  578. uint8_t more
  579. ) {
  580. unsigned char control[] = { AD };
  581. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  582. strobe_duplex(sponge, NULL, in, len);
  583. return ret;
  584. }
  585. #define STROBE_FORGET_BYTES 32
  586. decaf_bool_t strobe_produce_auth (
  587. keccak_sponge_t sponge,
  588. unsigned char *out,
  589. size_t len
  590. ) {
  591. unsigned char control[] = {
  592. (unsigned char)len,
  593. (unsigned char)STROBE_FORGET_BYTES,
  594. TAGFORGET | (sponge->params->client ? CLIENT_TO_SERVER : SERVER_TO_CLIENT)
  595. };
  596. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), 0);
  597. strobe_duplex(sponge, out, NULL, len);
  598. strobe_forget(sponge, STROBE_FORGET_BYTES);
  599. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  600. return ret;
  601. }
  602. decaf_bool_t strobe_prng (
  603. keccak_sponge_t sponge,
  604. unsigned char *out,
  605. size_t len,
  606. uint8_t more
  607. ) {
  608. unsigned char control[9] = { PRNG };
  609. int i;
  610. for (i=0; i<8; i++) control[i+1] = len>>(8*i);
  611. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), more);
  612. strobe_duplex(sponge, out, NULL, len);
  613. // TODO: forget as follows? this breaks "more"
  614. // unsigned char control2[] = { 0, STROBE_FORGET_BYTES, TAGFORGET };
  615. // ret &= strobe_control_word(sponge, control2, sizeof(control2));
  616. // strobe_forget(sponge, STROBE_FORGET_BYTES);
  617. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  618. return ret;
  619. }
  620. decaf_bool_t strobe_verify_auth (
  621. keccak_sponge_t sponge,
  622. const unsigned char *in,
  623. size_t len
  624. ) {
  625. unsigned char control[] = {
  626. (unsigned char)len,
  627. (unsigned char)STROBE_FORGET_BYTES,
  628. TAGFORGET | (sponge->params->client ? SERVER_TO_CLIENT : CLIENT_TO_SERVER)
  629. };
  630. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), 0);
  631. unsigned char zero[len];
  632. strobe_unduplex(sponge, zero, in, len);
  633. strobe_forget(sponge, STROBE_FORGET_BYTES);
  634. /* Check for 0 */
  635. decaf_bool_t chain=0;
  636. unsigned i;
  637. for (i=0; i<len; i++) {
  638. chain |= zero[i];
  639. }
  640. ret &= ((decaf_dword_t)chain-1)>>(8*sizeof(decaf_word_t));
  641. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  642. return ret;
  643. }
  644. decaf_bool_t strobe_respec (
  645. keccak_sponge_t sponge,
  646. const struct kparams_s *params
  647. ) {
  648. unsigned char control[] = { params->rate, params->startRound, RESPEC };
  649. decaf_bool_t ret = strobe_control_word(sponge, control, sizeof(control), 0);
  650. if (!sponge->params->pad/*keyed*/) ret = DECAF_FAILURE;
  651. sponge->params->rate = params->rate;
  652. sponge->params->startRound = params->startRound;
  653. return ret;
  654. }
  655. /* FUTURE: Keyak instances, etc */