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.
 
 
 
 
 

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