chacha_enc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /* Adapted from the public domain code by D. Bernstein from SUPERCOP. */
  10. #include <string.h>
  11. #include "internal/chacha.h"
  12. typedef unsigned int u32;
  13. typedef unsigned char u8;
  14. typedef union {
  15. u32 u[16];
  16. u8 c[64];
  17. } chacha_buf;
  18. # define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
  19. # define U32TO8_LITTLE(p, v) do { \
  20. (p)[0] = (u8)(v >> 0); \
  21. (p)[1] = (u8)(v >> 8); \
  22. (p)[2] = (u8)(v >> 16); \
  23. (p)[3] = (u8)(v >> 24); \
  24. } while(0)
  25. /* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
  26. # define QUARTERROUND(a,b,c,d) ( \
  27. x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \
  28. x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \
  29. x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \
  30. x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7) )
  31. /* chacha_core performs 20 rounds of ChaCha on the input words in
  32. * |input| and writes the 64 output bytes to |output|. */
  33. static void chacha20_core(chacha_buf *output, const u32 input[16])
  34. {
  35. u32 x[16];
  36. int i;
  37. const union {
  38. long one;
  39. char little;
  40. } is_endian = { 1 };
  41. memcpy(x, input, sizeof(x));
  42. for (i = 20; i > 0; i -= 2) {
  43. QUARTERROUND(0, 4, 8, 12);
  44. QUARTERROUND(1, 5, 9, 13);
  45. QUARTERROUND(2, 6, 10, 14);
  46. QUARTERROUND(3, 7, 11, 15);
  47. QUARTERROUND(0, 5, 10, 15);
  48. QUARTERROUND(1, 6, 11, 12);
  49. QUARTERROUND(2, 7, 8, 13);
  50. QUARTERROUND(3, 4, 9, 14);
  51. }
  52. if (is_endian.little) {
  53. for (i = 0; i < 16; ++i)
  54. output->u[i] = x[i] + input[i];
  55. } else {
  56. for (i = 0; i < 16; ++i)
  57. U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i]));
  58. }
  59. }
  60. void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
  61. size_t len, const unsigned int key[8],
  62. const unsigned int counter[4])
  63. {
  64. u32 input[16];
  65. chacha_buf buf;
  66. size_t todo, i;
  67. /* sigma constant "expand 32-byte k" in little-endian encoding */
  68. input[0] = ((u32)'e') | ((u32)'x'<<8) | ((u32)'p'<<16) | ((u32)'a'<<24);
  69. input[1] = ((u32)'n') | ((u32)'d'<<8) | ((u32)' '<<16) | ((u32)'3'<<24);
  70. input[2] = ((u32)'2') | ((u32)'-'<<8) | ((u32)'b'<<16) | ((u32)'y'<<24);
  71. input[3] = ((u32)'t') | ((u32)'e'<<8) | ((u32)' '<<16) | ((u32)'k'<<24);
  72. input[4] = key[0];
  73. input[5] = key[1];
  74. input[6] = key[2];
  75. input[7] = key[3];
  76. input[8] = key[4];
  77. input[9] = key[5];
  78. input[10] = key[6];
  79. input[11] = key[7];
  80. input[12] = counter[0];
  81. input[13] = counter[1];
  82. input[14] = counter[2];
  83. input[15] = counter[3];
  84. while (len > 0) {
  85. todo = sizeof(buf);
  86. if (len < todo)
  87. todo = len;
  88. chacha20_core(&buf, input);
  89. for (i = 0; i < todo; i++)
  90. out[i] = inp[i] ^ buf.c[i];
  91. out += todo;
  92. inp += todo;
  93. len -= todo;
  94. /*
  95. * Advance 32-bit counter. Note that as subroutine is so to
  96. * say nonce-agnostic, this limited counter width doesn't
  97. * prevent caller from implementing wider counter. It would
  98. * simply take two calls split on counter overflow...
  99. */
  100. input[12]++;
  101. }
  102. }