chacha20.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * cifra - embedded cryptography library
  3. * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
  4. *
  5. * To the extent possible under law, the author(s) have dedicated all
  6. * copyright and related and neighboring rights to this software to the
  7. * public domain worldwide. This software is distributed without any
  8. * warranty.
  9. *
  10. * You should have received a copy of the CC0 Public Domain Dedication
  11. * along with this software. If not, see
  12. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  13. */
  14. #include "bitops.h"
  15. #include "salsa20.h"
  16. #include "blockwise.h"
  17. #include "tassert.h"
  18. #include <string.h>
  19. #include <stdlib.h>
  20. void cf_chacha20_core(const uint8_t key0[16],
  21. const uint8_t key1[16],
  22. const uint8_t nonce[16],
  23. const uint8_t constant[16],
  24. uint8_t out[64])
  25. {
  26. uint32_t z0, z1, z2, z3, z4, z5, z6, z7,
  27. z8, z9, za, zb, zc, zd, ze, zf;
  28. uint32_t x0 = z0 = read32_le(constant + 0),
  29. x1 = z1 = read32_le(constant + 4),
  30. x2 = z2 = read32_le(constant + 8),
  31. x3 = z3 = read32_le(constant + 12),
  32. x4 = z4 = read32_le(key0 + 0),
  33. x5 = z5 = read32_le(key0 + 4),
  34. x6 = z6 = read32_le(key0 + 8),
  35. x7 = z7 = read32_le(key0 + 12),
  36. x8 = z8 = read32_le(key1 + 0),
  37. x9 = z9 = read32_le(key1 + 4),
  38. xa = za = read32_le(key1 + 8),
  39. xb = zb = read32_le(key1 + 12),
  40. xc = zc = read32_le(nonce + 0),
  41. xd = zd = read32_le(nonce + 4),
  42. xe = ze = read32_le(nonce + 8),
  43. xf = zf = read32_le(nonce + 12);
  44. #define QUARTER(a, b, c, d) \
  45. a += b; d = rotl32(d ^ a, 16); \
  46. c += d; b = rotl32(b ^ c, 12); \
  47. a += b; d = rotl32(d ^ a, 8); \
  48. c += d; b = rotl32(b ^ c, 7);
  49. int i;
  50. for (i = 0; i < 10; i++)
  51. {
  52. QUARTER(z0, z4, z8, zc);
  53. QUARTER(z1, z5, z9, zd);
  54. QUARTER(z2, z6, za, ze);
  55. QUARTER(z3, z7, zb, zf);
  56. QUARTER(z0, z5, za, zf);
  57. QUARTER(z1, z6, zb, zc);
  58. QUARTER(z2, z7, z8, zd);
  59. QUARTER(z3, z4, z9, ze);
  60. }
  61. x0 += z0;
  62. x1 += z1;
  63. x2 += z2;
  64. x3 += z3;
  65. x4 += z4;
  66. x5 += z5;
  67. x6 += z6;
  68. x7 += z7;
  69. x8 += z8;
  70. x9 += z9;
  71. xa += za;
  72. xb += zb;
  73. xc += zc;
  74. xd += zd;
  75. xe += ze;
  76. xf += zf;
  77. write32_le(x0, out + 0);
  78. write32_le(x1, out + 4);
  79. write32_le(x2, out + 8);
  80. write32_le(x3, out + 12);
  81. write32_le(x4, out + 16);
  82. write32_le(x5, out + 20);
  83. write32_le(x6, out + 24);
  84. write32_le(x7, out + 28);
  85. write32_le(x8, out + 32);
  86. write32_le(x9, out + 36);
  87. write32_le(xa, out + 40);
  88. write32_le(xb, out + 44);
  89. write32_le(xc, out + 48);
  90. write32_le(xd, out + 52);
  91. write32_le(xe, out + 56);
  92. write32_le(xf, out + 60);
  93. }
  94. static const uint8_t *chacha20_tau = (const uint8_t *) "expand 16-byte k";
  95. static const uint8_t *chacha20_sigma = (const uint8_t *) "expand 32-byte k";
  96. static void set_key(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey)
  97. {
  98. switch (nkey)
  99. {
  100. case 16:
  101. memcpy(ctx->key0, key, 16);
  102. memcpy(ctx->key1, key, 16);
  103. ctx->constant = chacha20_tau;
  104. break;
  105. case 32:
  106. memcpy(ctx->key0, key, 16);
  107. memcpy(ctx->key1, key + 16, 16);
  108. ctx->constant = chacha20_sigma;
  109. break;
  110. default:
  111. abort();
  112. }
  113. }
  114. void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8])
  115. {
  116. set_key(ctx, key, nkey);
  117. memset(ctx->nonce, 0, sizeof ctx->nonce);
  118. memcpy(ctx->nonce + 8, nonce, 8);
  119. ctx->nblock = 0;
  120. ctx->ncounter = 8;
  121. }
  122. void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey,
  123. const uint8_t nonce[16], size_t ncounter)
  124. {
  125. assert(ncounter > 0);
  126. set_key(ctx, key, nkey);
  127. memcpy(ctx->nonce, nonce, sizeof ctx->nonce);
  128. ctx->nblock = 0;
  129. ctx->ncounter = ncounter;
  130. }
  131. static void cf_chacha20_next_block(void *vctx, uint8_t *out)
  132. {
  133. cf_chacha20_ctx *ctx = vctx;
  134. cf_chacha20_core(ctx->key0,
  135. ctx->key1,
  136. ctx->nonce,
  137. ctx->constant,
  138. out);
  139. incr_le(ctx->nonce, ctx->ncounter);
  140. }
  141. void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes)
  142. {
  143. cf_blockwise_xor(ctx->block, &ctx->nblock, 64,
  144. input, output, bytes,
  145. cf_chacha20_next_block,
  146. ctx);
  147. }