secretstream_xchacha20poly1305.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <string.h>
  5. #include "core.h"
  6. #include "crypto_aead_chacha20poly1305.h"
  7. #include "crypto_aead_xchacha20poly1305.h"
  8. #include "crypto_core_hchacha20.h"
  9. #include "crypto_onetimeauth_poly1305.h"
  10. #include "crypto_secretstream_xchacha20poly1305.h"
  11. #include "randombytes.h"
  12. #include "utils.h"
  13. #include "private/common.h"
  14. #define crypto_secretstream_xchacha20poly1305_COUNTERBYTES 4U
  15. #define crypto_secretstream_xchacha20poly1305_INONCEBYTES 8U
  16. #define STATE_COUNTER(STATE) ((STATE)->nonce)
  17. #define STATE_INONCE(STATE) ((STATE)->nonce + \
  18. crypto_secretstream_xchacha20poly1305_COUNTERBYTES)
  19. static const unsigned char _pad0[16] = { 0 };
  20. static inline void
  21. _crypto_secretstream_xchacha20poly1305_counter_reset
  22. (crypto_secretstream_xchacha20poly1305_state *state)
  23. {
  24. memset(STATE_COUNTER(state), 0,
  25. crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
  26. STATE_COUNTER(state)[0] = 1;
  27. }
  28. void
  29. crypto_secretstream_xchacha20poly1305_keygen
  30. (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
  31. {
  32. randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES);
  33. }
  34. int
  35. crypto_secretstream_xchacha20poly1305_init_push
  36. (crypto_secretstream_xchacha20poly1305_state *state,
  37. unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
  38. const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
  39. {
  40. COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
  41. crypto_core_hchacha20_INPUTBYTES +
  42. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  43. COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
  44. crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
  45. COMPILER_ASSERT(sizeof state->nonce ==
  46. crypto_secretstream_xchacha20poly1305_INONCEBYTES +
  47. crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
  48. randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
  49. crypto_core_hchacha20(state->k, out, k, NULL);
  50. _crypto_secretstream_xchacha20poly1305_counter_reset(state);
  51. memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
  52. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  53. memset(state->_pad, 0, sizeof state->_pad);
  54. return 0;
  55. }
  56. int
  57. crypto_secretstream_xchacha20poly1305_init_pull
  58. (crypto_secretstream_xchacha20poly1305_state *state,
  59. const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
  60. const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
  61. {
  62. crypto_core_hchacha20(state->k, in, k, NULL);
  63. _crypto_secretstream_xchacha20poly1305_counter_reset(state);
  64. memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
  65. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  66. memset(state->_pad, 0, sizeof state->_pad);
  67. return 0;
  68. }
  69. void
  70. crypto_secretstream_xchacha20poly1305_rekey
  71. (crypto_secretstream_xchacha20poly1305_state *state)
  72. {
  73. unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
  74. crypto_secretstream_xchacha20poly1305_INONCEBYTES];
  75. size_t i;
  76. for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
  77. new_key_and_inonce[i] = state->k[i];
  78. }
  79. for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
  80. new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
  81. STATE_INONCE(state)[i];
  82. }
  83. crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
  84. sizeof new_key_and_inonce,
  85. state->nonce, state->k);
  86. for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
  87. state->k[i] = new_key_and_inonce[i];
  88. }
  89. for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
  90. STATE_INONCE(state)[i] =
  91. new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
  92. }
  93. _crypto_secretstream_xchacha20poly1305_counter_reset(state);
  94. }
  95. int
  96. crypto_secretstream_xchacha20poly1305_push
  97. (crypto_secretstream_xchacha20poly1305_state *state,
  98. unsigned char *out, unsigned long long *outlen_p,
  99. const unsigned char *m, unsigned long long mlen,
  100. const unsigned char *ad, unsigned long long adlen, unsigned char tag)
  101. {
  102. crypto_onetimeauth_poly1305_state poly1305_state;
  103. unsigned char block[64U];
  104. unsigned char slen[8U];
  105. unsigned char *c;
  106. unsigned char *mac;
  107. if (outlen_p != NULL) {
  108. *outlen_p = 0U;
  109. }
  110. COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX
  111. <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
  112. if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
  113. sodium_misuse();
  114. }
  115. crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
  116. crypto_onetimeauth_poly1305_init(&poly1305_state, block);
  117. sodium_memzero(block, sizeof block);
  118. crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
  119. crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
  120. (0x10 - adlen) & 0xf);
  121. memset(block, 0, sizeof block);
  122. block[0] = tag;
  123. crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
  124. state->nonce, 1U, state->k);
  125. crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
  126. out[0] = block[0];
  127. c = out + (sizeof tag);
  128. crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
  129. crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
  130. crypto_onetimeauth_poly1305_update
  131. (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
  132. STORE64_LE(slen, (uint64_t) adlen);
  133. crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  134. STORE64_LE(slen, (sizeof block) + mlen);
  135. crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  136. mac = c + mlen;
  137. crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
  138. sodium_memzero(&poly1305_state, sizeof poly1305_state);
  139. COMPILER_ASSERT(crypto_onetimeauth_poly1305_BYTES >=
  140. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  141. XOR_BUF(STATE_INONCE(state), mac,
  142. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  143. sodium_increment(STATE_COUNTER(state),
  144. crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
  145. if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
  146. sodium_is_zero(STATE_COUNTER(state),
  147. crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
  148. crypto_secretstream_xchacha20poly1305_rekey(state);
  149. }
  150. if (outlen_p != NULL) {
  151. *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
  152. }
  153. return 0;
  154. }
  155. int
  156. crypto_secretstream_xchacha20poly1305_pull
  157. (crypto_secretstream_xchacha20poly1305_state *state,
  158. unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
  159. const unsigned char *in, unsigned long long inlen,
  160. const unsigned char *ad, unsigned long long adlen)
  161. {
  162. crypto_onetimeauth_poly1305_state poly1305_state;
  163. unsigned char block[64U];
  164. unsigned char slen[8U];
  165. unsigned char mac[crypto_onetimeauth_poly1305_BYTES];
  166. const unsigned char *c;
  167. const unsigned char *stored_mac;
  168. unsigned long long mlen;
  169. unsigned char tag;
  170. if (mlen_p != NULL) {
  171. *mlen_p = 0U;
  172. }
  173. if (tag_p != NULL) {
  174. *tag_p = 0xff;
  175. }
  176. if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) {
  177. return -1;
  178. }
  179. mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
  180. if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
  181. sodium_misuse();
  182. }
  183. crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
  184. crypto_onetimeauth_poly1305_init(&poly1305_state, block);
  185. sodium_memzero(block, sizeof block);
  186. crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
  187. crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
  188. (0x10 - adlen) & 0xf);
  189. memset(block, 0, sizeof block);
  190. block[0] = in[0];
  191. crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
  192. state->nonce, 1U, state->k);
  193. tag = block[0];
  194. block[0] = in[0];
  195. crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
  196. c = in + (sizeof tag);
  197. crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
  198. crypto_onetimeauth_poly1305_update
  199. (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
  200. STORE64_LE(slen, (uint64_t) adlen);
  201. crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  202. STORE64_LE(slen, (sizeof block) + mlen);
  203. crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  204. crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
  205. sodium_memzero(&poly1305_state, sizeof poly1305_state);
  206. stored_mac = c + mlen;
  207. if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
  208. sodium_memzero(mac, sizeof mac);
  209. return -1;
  210. }
  211. crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
  212. XOR_BUF(STATE_INONCE(state), mac,
  213. crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  214. sodium_increment(STATE_COUNTER(state),
  215. crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
  216. if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
  217. sodium_is_zero(STATE_COUNTER(state),
  218. crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
  219. crypto_secretstream_xchacha20poly1305_rekey(state);
  220. }
  221. if (mlen_p != NULL) {
  222. *mlen_p = mlen;
  223. }
  224. if (tag_p != NULL) {
  225. *tag_p = tag;
  226. }
  227. return 0;
  228. }
  229. size_t
  230. crypto_secretstream_xchacha20poly1305_statebytes(void)
  231. {
  232. return sizeof(crypto_secretstream_xchacha20poly1305_state);
  233. }
  234. size_t
  235. crypto_secretstream_xchacha20poly1305_abytes(void)
  236. {
  237. return crypto_secretstream_xchacha20poly1305_ABYTES;
  238. }
  239. size_t
  240. crypto_secretstream_xchacha20poly1305_headerbytes(void)
  241. {
  242. return crypto_secretstream_xchacha20poly1305_HEADERBYTES;
  243. }
  244. size_t
  245. crypto_secretstream_xchacha20poly1305_keybytes(void)
  246. {
  247. return crypto_secretstream_xchacha20poly1305_KEYBYTES;
  248. }
  249. size_t
  250. crypto_secretstream_xchacha20poly1305_messagebytes_max(void)
  251. {
  252. return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX;
  253. }
  254. unsigned char
  255. crypto_secretstream_xchacha20poly1305_tag_message(void)
  256. {
  257. return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
  258. }
  259. unsigned char
  260. crypto_secretstream_xchacha20poly1305_tag_push(void)
  261. {
  262. return crypto_secretstream_xchacha20poly1305_TAG_PUSH;
  263. }
  264. unsigned char
  265. crypto_secretstream_xchacha20poly1305_tag_rekey(void)
  266. {
  267. return crypto_secretstream_xchacha20poly1305_TAG_REKEY;
  268. }
  269. unsigned char
  270. crypto_secretstream_xchacha20poly1305_tag_final(void)
  271. {
  272. return crypto_secretstream_xchacha20poly1305_TAG_FINAL;
  273. }