chacha20_dolbeau-ssse3.c 4.3 KB

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