chacha20_dolbeau-avx2.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "core.h"
  5. #include "crypto_stream_chacha20.h"
  6. #include "private/common.h"
  7. #include "private/sse2_64_32.h"
  8. #include "utils.h"
  9. #if defined(HAVE_AVX2INTRIN_H) && defined(HAVE_EMMINTRIN_H) && \
  10. defined(HAVE_TMMINTRIN_H) && defined(HAVE_SMMINTRIN_H)
  11. # ifdef __GNUC__
  12. # pragma GCC target("sse2")
  13. # pragma GCC target("ssse3")
  14. # pragma GCC target("sse4.1")
  15. # pragma GCC target("avx2")
  16. # endif
  17. # include <emmintrin.h>
  18. # include <immintrin.h>
  19. # include <smmintrin.h>
  20. # include <tmmintrin.h>
  21. # include "../stream_chacha20.h"
  22. # include "chacha20_dolbeau-avx2.h"
  23. # define ROUNDS 20
  24. typedef struct chacha_ctx {
  25. uint32_t input[16];
  26. } chacha_ctx;
  27. static void
  28. chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
  29. {
  30. ctx->input[0] = 0x61707865;
  31. ctx->input[1] = 0x3320646e;
  32. ctx->input[2] = 0x79622d32;
  33. ctx->input[3] = 0x6b206574;
  34. ctx->input[4] = LOAD32_LE(k + 0);
  35. ctx->input[5] = LOAD32_LE(k + 4);
  36. ctx->input[6] = LOAD32_LE(k + 8);
  37. ctx->input[7] = LOAD32_LE(k + 12);
  38. ctx->input[8] = LOAD32_LE(k + 16);
  39. ctx->input[9] = LOAD32_LE(k + 20);
  40. ctx->input[10] = LOAD32_LE(k + 24);
  41. ctx->input[11] = LOAD32_LE(k + 28);
  42. }
  43. static void
  44. chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
  45. {
  46. ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
  47. ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
  48. ctx->input[14] = LOAD32_LE(iv + 0);
  49. ctx->input[15] = LOAD32_LE(iv + 4);
  50. }
  51. static void
  52. chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
  53. {
  54. ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
  55. ctx->input[13] = LOAD32_LE(iv + 0);
  56. ctx->input[14] = LOAD32_LE(iv + 4);
  57. ctx->input[15] = LOAD32_LE(iv + 8);
  58. }
  59. static void
  60. chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
  61. unsigned long long bytes)
  62. {
  63. uint32_t * const x = &ctx->input[0];
  64. if (!bytes) {
  65. return; /* LCOV_EXCL_LINE */
  66. }
  67. # include "u8.h"
  68. # include "u4.h"
  69. # include "u1.h"
  70. # include "u0.h"
  71. }
  72. static int
  73. stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
  74. const unsigned char *k)
  75. {
  76. struct chacha_ctx ctx;
  77. if (!clen) {
  78. return 0;
  79. }
  80. COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
  81. chacha_keysetup(&ctx, k);
  82. chacha_ivsetup(&ctx, n, NULL);
  83. memset(c, 0, clen);
  84. chacha20_encrypt_bytes(&ctx, c, c, clen);
  85. sodium_memzero(&ctx, sizeof ctx);
  86. return 0;
  87. }
  88. static int
  89. stream_ietf_ext_ref(unsigned char *c, unsigned long long clen,
  90. const unsigned char *n, const unsigned char *k)
  91. {
  92. struct chacha_ctx ctx;
  93. if (!clen) {
  94. return 0;
  95. }
  96. COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
  97. chacha_keysetup(&ctx, k);
  98. chacha_ietf_ivsetup(&ctx, n, NULL);
  99. memset(c, 0, clen);
  100. chacha20_encrypt_bytes(&ctx, c, c, clen);
  101. sodium_memzero(&ctx, sizeof ctx);
  102. return 0;
  103. }
  104. static int
  105. stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
  106. unsigned long long mlen, const unsigned char *n, uint64_t ic,
  107. const unsigned char *k)
  108. {
  109. struct chacha_ctx ctx;
  110. uint8_t ic_bytes[8];
  111. uint32_t ic_high;
  112. uint32_t ic_low;
  113. if (!mlen) {
  114. return 0;
  115. }
  116. ic_high = (uint32_t) (ic >> 32);
  117. ic_low = (uint32_t) ic;
  118. STORE32_LE(&ic_bytes[0], ic_low);
  119. STORE32_LE(&ic_bytes[4], ic_high);
  120. chacha_keysetup(&ctx, k);
  121. chacha_ivsetup(&ctx, n, ic_bytes);
  122. chacha20_encrypt_bytes(&ctx, m, c, mlen);
  123. sodium_memzero(&ctx, sizeof ctx);
  124. return 0;
  125. }
  126. static int
  127. stream_ietf_ext_ref_xor_ic(unsigned char *c, const unsigned char *m,
  128. unsigned long long mlen, const unsigned char *n,
  129. uint32_t ic, const unsigned char *k)
  130. {
  131. struct chacha_ctx ctx;
  132. uint8_t ic_bytes[4];
  133. if (!mlen) {
  134. return 0;
  135. }
  136. STORE32_LE(ic_bytes, ic);
  137. chacha_keysetup(&ctx, k);
  138. chacha_ietf_ivsetup(&ctx, n, ic_bytes);
  139. chacha20_encrypt_bytes(&ctx, m, c, mlen);
  140. sodium_memzero(&ctx, sizeof ctx);
  141. return 0;
  142. }
  143. struct crypto_stream_chacha20_implementation
  144. crypto_stream_chacha20_dolbeau_avx2_implementation = {
  145. SODIUM_C99(.stream =) stream_ref,
  146. SODIUM_C99(.stream_ietf_ext =) stream_ietf_ext_ref,
  147. SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
  148. SODIUM_C99(.stream_ietf_ext_xor_ic =) stream_ietf_ext_ref_xor_ic
  149. };
  150. #endif