chacha20_ref.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. chacha-merged.c version 20080118
  3. D. J. Bernstein
  4. Public domain.
  5. */
  6. #include <stdint.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "core.h"
  10. #include "crypto_stream_chacha20.h"
  11. #include "private/common.h"
  12. #include "utils.h"
  13. #include "../stream_chacha20.h"
  14. #include "chacha20_ref.h"
  15. struct chacha_ctx {
  16. uint32_t input[16];
  17. };
  18. typedef struct chacha_ctx chacha_ctx;
  19. #define U32C(v) (v##U)
  20. #define U32V(v) ((uint32_t)(v) &U32C(0xFFFFFFFF))
  21. #define ROTATE(v, c) (ROTL32(v, c))
  22. #define XOR(v, w) ((v) ^ (w))
  23. #define PLUS(v, w) (U32V((v) + (w)))
  24. #define PLUSONE(v) (PLUS((v), 1))
  25. #define QUARTERROUND(a, b, c, d) \
  26. a = PLUS(a, b); \
  27. d = ROTATE(XOR(d, a), 16); \
  28. c = PLUS(c, d); \
  29. b = ROTATE(XOR(b, c), 12); \
  30. a = PLUS(a, b); \
  31. d = ROTATE(XOR(d, a), 8); \
  32. c = PLUS(c, d); \
  33. b = ROTATE(XOR(b, c), 7);
  34. static void
  35. chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
  36. {
  37. ctx->input[0] = U32C(0x61707865);
  38. ctx->input[1] = U32C(0x3320646e);
  39. ctx->input[2] = U32C(0x79622d32);
  40. ctx->input[3] = U32C(0x6b206574);
  41. ctx->input[4] = LOAD32_LE(k + 0);
  42. ctx->input[5] = LOAD32_LE(k + 4);
  43. ctx->input[6] = LOAD32_LE(k + 8);
  44. ctx->input[7] = LOAD32_LE(k + 12);
  45. ctx->input[8] = LOAD32_LE(k + 16);
  46. ctx->input[9] = LOAD32_LE(k + 20);
  47. ctx->input[10] = LOAD32_LE(k + 24);
  48. ctx->input[11] = LOAD32_LE(k + 28);
  49. }
  50. static void
  51. chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
  52. {
  53. ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
  54. ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
  55. ctx->input[14] = LOAD32_LE(iv + 0);
  56. ctx->input[15] = LOAD32_LE(iv + 4);
  57. }
  58. static void
  59. chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
  60. {
  61. ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
  62. ctx->input[13] = LOAD32_LE(iv + 0);
  63. ctx->input[14] = LOAD32_LE(iv + 4);
  64. ctx->input[15] = LOAD32_LE(iv + 8);
  65. }
  66. static void
  67. chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
  68. unsigned long long bytes)
  69. {
  70. uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
  71. x15;
  72. uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14,
  73. j15;
  74. uint8_t *ctarget = NULL;
  75. uint8_t tmp[64];
  76. unsigned int i;
  77. if (!bytes) {
  78. return; /* LCOV_EXCL_LINE */
  79. }
  80. j0 = ctx->input[0];
  81. j1 = ctx->input[1];
  82. j2 = ctx->input[2];
  83. j3 = ctx->input[3];
  84. j4 = ctx->input[4];
  85. j5 = ctx->input[5];
  86. j6 = ctx->input[6];
  87. j7 = ctx->input[7];
  88. j8 = ctx->input[8];
  89. j9 = ctx->input[9];
  90. j10 = ctx->input[10];
  91. j11 = ctx->input[11];
  92. j12 = ctx->input[12];
  93. j13 = ctx->input[13];
  94. j14 = ctx->input[14];
  95. j15 = ctx->input[15];
  96. for (;;) {
  97. if (bytes < 64) {
  98. memset(tmp, 0, 64);
  99. for (i = 0; i < bytes; ++i) {
  100. tmp[i] = m[i];
  101. }
  102. m = tmp;
  103. ctarget = c;
  104. c = tmp;
  105. }
  106. x0 = j0;
  107. x1 = j1;
  108. x2 = j2;
  109. x3 = j3;
  110. x4 = j4;
  111. x5 = j5;
  112. x6 = j6;
  113. x7 = j7;
  114. x8 = j8;
  115. x9 = j9;
  116. x10 = j10;
  117. x11 = j11;
  118. x12 = j12;
  119. x13 = j13;
  120. x14 = j14;
  121. x15 = j15;
  122. for (i = 20; i > 0; i -= 2) {
  123. QUARTERROUND(x0, x4, x8, x12)
  124. QUARTERROUND(x1, x5, x9, x13)
  125. QUARTERROUND(x2, x6, x10, x14)
  126. QUARTERROUND(x3, x7, x11, x15)
  127. QUARTERROUND(x0, x5, x10, x15)
  128. QUARTERROUND(x1, x6, x11, x12)
  129. QUARTERROUND(x2, x7, x8, x13)
  130. QUARTERROUND(x3, x4, x9, x14)
  131. }
  132. x0 = PLUS(x0, j0);
  133. x1 = PLUS(x1, j1);
  134. x2 = PLUS(x2, j2);
  135. x3 = PLUS(x3, j3);
  136. x4 = PLUS(x4, j4);
  137. x5 = PLUS(x5, j5);
  138. x6 = PLUS(x6, j6);
  139. x7 = PLUS(x7, j7);
  140. x8 = PLUS(x8, j8);
  141. x9 = PLUS(x9, j9);
  142. x10 = PLUS(x10, j10);
  143. x11 = PLUS(x11, j11);
  144. x12 = PLUS(x12, j12);
  145. x13 = PLUS(x13, j13);
  146. x14 = PLUS(x14, j14);
  147. x15 = PLUS(x15, j15);
  148. x0 = XOR(x0, LOAD32_LE(m + 0));
  149. x1 = XOR(x1, LOAD32_LE(m + 4));
  150. x2 = XOR(x2, LOAD32_LE(m + 8));
  151. x3 = XOR(x3, LOAD32_LE(m + 12));
  152. x4 = XOR(x4, LOAD32_LE(m + 16));
  153. x5 = XOR(x5, LOAD32_LE(m + 20));
  154. x6 = XOR(x6, LOAD32_LE(m + 24));
  155. x7 = XOR(x7, LOAD32_LE(m + 28));
  156. x8 = XOR(x8, LOAD32_LE(m + 32));
  157. x9 = XOR(x9, LOAD32_LE(m + 36));
  158. x10 = XOR(x10, LOAD32_LE(m + 40));
  159. x11 = XOR(x11, LOAD32_LE(m + 44));
  160. x12 = XOR(x12, LOAD32_LE(m + 48));
  161. x13 = XOR(x13, LOAD32_LE(m + 52));
  162. x14 = XOR(x14, LOAD32_LE(m + 56));
  163. x15 = XOR(x15, LOAD32_LE(m + 60));
  164. j12 = PLUSONE(j12);
  165. /* LCOV_EXCL_START */
  166. if (!j12) {
  167. j13 = PLUSONE(j13);
  168. }
  169. /* LCOV_EXCL_STOP */
  170. STORE32_LE(c + 0, x0);
  171. STORE32_LE(c + 4, x1);
  172. STORE32_LE(c + 8, x2);
  173. STORE32_LE(c + 12, x3);
  174. STORE32_LE(c + 16, x4);
  175. STORE32_LE(c + 20, x5);
  176. STORE32_LE(c + 24, x6);
  177. STORE32_LE(c + 28, x7);
  178. STORE32_LE(c + 32, x8);
  179. STORE32_LE(c + 36, x9);
  180. STORE32_LE(c + 40, x10);
  181. STORE32_LE(c + 44, x11);
  182. STORE32_LE(c + 48, x12);
  183. STORE32_LE(c + 52, x13);
  184. STORE32_LE(c + 56, x14);
  185. STORE32_LE(c + 60, x15);
  186. if (bytes <= 64) {
  187. if (bytes < 64) {
  188. for (i = 0; i < (unsigned int) bytes; ++i) {
  189. ctarget[i] = c[i]; /* ctarget cannot be NULL */
  190. }
  191. }
  192. ctx->input[12] = j12;
  193. ctx->input[13] = j13;
  194. return;
  195. }
  196. bytes -= 64;
  197. c += 64;
  198. m += 64;
  199. }
  200. }
  201. static int
  202. stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
  203. const unsigned char *k)
  204. {
  205. struct chacha_ctx ctx;
  206. if (!clen) {
  207. return 0;
  208. }
  209. COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
  210. chacha_keysetup(&ctx, k);
  211. chacha_ivsetup(&ctx, n, NULL);
  212. memset(c, 0, clen);
  213. chacha20_encrypt_bytes(&ctx, c, c, clen);
  214. sodium_memzero(&ctx, sizeof ctx);
  215. return 0;
  216. }
  217. static int
  218. stream_ietf_ext_ref(unsigned char *c, unsigned long long clen,
  219. const unsigned char *n, const unsigned char *k)
  220. {
  221. struct chacha_ctx ctx;
  222. if (!clen) {
  223. return 0;
  224. }
  225. COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
  226. chacha_keysetup(&ctx, k);
  227. chacha_ietf_ivsetup(&ctx, n, NULL);
  228. memset(c, 0, clen);
  229. chacha20_encrypt_bytes(&ctx, c, c, clen);
  230. sodium_memzero(&ctx, sizeof ctx);
  231. return 0;
  232. }
  233. static int
  234. stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
  235. unsigned long long mlen, const unsigned char *n, uint64_t ic,
  236. const unsigned char *k)
  237. {
  238. struct chacha_ctx ctx;
  239. uint8_t ic_bytes[8];
  240. uint32_t ic_high;
  241. uint32_t ic_low;
  242. if (!mlen) {
  243. return 0;
  244. }
  245. ic_high = U32V(ic >> 32);
  246. ic_low = U32V(ic);
  247. STORE32_LE(&ic_bytes[0], ic_low);
  248. STORE32_LE(&ic_bytes[4], ic_high);
  249. chacha_keysetup(&ctx, k);
  250. chacha_ivsetup(&ctx, n, ic_bytes);
  251. chacha20_encrypt_bytes(&ctx, m, c, mlen);
  252. sodium_memzero(&ctx, sizeof ctx);
  253. return 0;
  254. }
  255. static int
  256. stream_ietf_ext_ref_xor_ic(unsigned char *c, const unsigned char *m,
  257. unsigned long long mlen, const unsigned char *n,
  258. uint32_t ic, const unsigned char *k)
  259. {
  260. struct chacha_ctx ctx;
  261. uint8_t ic_bytes[4];
  262. if (!mlen) {
  263. return 0;
  264. }
  265. STORE32_LE(ic_bytes, ic);
  266. chacha_keysetup(&ctx, k);
  267. chacha_ietf_ivsetup(&ctx, n, ic_bytes);
  268. chacha20_encrypt_bytes(&ctx, m, c, mlen);
  269. sodium_memzero(&ctx, sizeof ctx);
  270. return 0;
  271. }
  272. struct crypto_stream_chacha20_implementation
  273. crypto_stream_chacha20_ref_implementation = {
  274. SODIUM_C99(.stream =) stream_ref,
  275. SODIUM_C99(.stream_ietf_ext =) stream_ietf_ext_ref,
  276. SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
  277. SODIUM_C99(.stream_ietf_ext_xor_ic =) stream_ietf_ext_ref_xor_ic
  278. };