2
0

chacha_enc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright 2015-2020 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/endian.h"
  12. #include "crypto/chacha.h"
  13. #include "crypto/ctype.h"
  14. typedef unsigned int u32;
  15. typedef unsigned char u8;
  16. typedef union {
  17. u32 u[16];
  18. u8 c[64];
  19. } chacha_buf;
  20. # define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
  21. # define U32TO8_LITTLE(p, v) do { \
  22. (p)[0] = (u8)(v >> 0); \
  23. (p)[1] = (u8)(v >> 8); \
  24. (p)[2] = (u8)(v >> 16); \
  25. (p)[3] = (u8)(v >> 24); \
  26. } while(0)
  27. /* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
  28. # define QUARTERROUND(a,b,c,d) ( \
  29. x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \
  30. x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \
  31. x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \
  32. x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7) )
  33. /* chacha_core performs 20 rounds of ChaCha on the input words in
  34. * |input| and writes the 64 output bytes to |output|. */
  35. static void chacha20_core(chacha_buf *output, const u32 input[16])
  36. {
  37. u32 x[16];
  38. int i;
  39. DECLARE_IS_ENDIAN;
  40. memcpy(x, input, sizeof(x));
  41. for (i = 20; i > 0; i -= 2) {
  42. QUARTERROUND(0, 4, 8, 12);
  43. QUARTERROUND(1, 5, 9, 13);
  44. QUARTERROUND(2, 6, 10, 14);
  45. QUARTERROUND(3, 7, 11, 15);
  46. QUARTERROUND(0, 5, 10, 15);
  47. QUARTERROUND(1, 6, 11, 12);
  48. QUARTERROUND(2, 7, 8, 13);
  49. QUARTERROUND(3, 4, 9, 14);
  50. }
  51. if (IS_LITTLE_ENDIAN) {
  52. for (i = 0; i < 16; ++i)
  53. output->u[i] = x[i] + input[i];
  54. } else {
  55. for (i = 0; i < 16; ++i)
  56. U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i]));
  57. }
  58. }
  59. void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
  60. size_t len, const unsigned int key[8],
  61. const unsigned int counter[4])
  62. {
  63. u32 input[16];
  64. chacha_buf buf;
  65. size_t todo, i;
  66. /* sigma constant "expand 32-byte k" in little-endian encoding */
  67. input[0] = ((u32)ossl_toascii('e')) | ((u32)ossl_toascii('x') << 8)
  68. | ((u32)ossl_toascii('p') << 16)
  69. | ((u32)ossl_toascii('a') << 24);
  70. input[1] = ((u32)ossl_toascii('n')) | ((u32)ossl_toascii('d') << 8)
  71. | ((u32)ossl_toascii(' ') << 16)
  72. | ((u32)ossl_toascii('3') << 24);
  73. input[2] = ((u32)ossl_toascii('2')) | ((u32)ossl_toascii('-') << 8)
  74. | ((u32)ossl_toascii('b') << 16)
  75. | ((u32)ossl_toascii('y') << 24);
  76. input[3] = ((u32)ossl_toascii('t')) | ((u32)ossl_toascii('e') << 8)
  77. | ((u32)ossl_toascii(' ') << 16)
  78. | ((u32)ossl_toascii('k') << 24);
  79. input[4] = key[0];
  80. input[5] = key[1];
  81. input[6] = key[2];
  82. input[7] = key[3];
  83. input[8] = key[4];
  84. input[9] = key[5];
  85. input[10] = key[6];
  86. input[11] = key[7];
  87. input[12] = counter[0];
  88. input[13] = counter[1];
  89. input[14] = counter[2];
  90. input[15] = counter[3];
  91. while (len > 0) {
  92. todo = sizeof(buf);
  93. if (len < todo)
  94. todo = len;
  95. chacha20_core(&buf, input);
  96. for (i = 0; i < todo; i++)
  97. out[i] = inp[i] ^ buf.c[i];
  98. out += todo;
  99. inp += todo;
  100. len -= todo;
  101. /*
  102. * Advance 32-bit counter. Note that as subroutine is so to
  103. * say nonce-agnostic, this limited counter width doesn't
  104. * prevent caller from implementing wider counter. It would
  105. * simply take two calls split on counter overflow...
  106. */
  107. input[12]++;
  108. }
  109. }