secretbox_xchacha20poly1305.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include <assert.h>
  2. #include <limits.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "core.h"
  7. #include "crypto_core_hchacha20.h"
  8. #include "crypto_onetimeauth_poly1305.h"
  9. #include "crypto_secretbox_xchacha20poly1305.h"
  10. #include "crypto_stream_chacha20.h"
  11. #include "private/common.h"
  12. #include "utils.h"
  13. #define crypto_secretbox_xchacha20poly1305_ZEROBYTES 32U
  14. int
  15. crypto_secretbox_xchacha20poly1305_detached(unsigned char *c,
  16. unsigned char *mac,
  17. const unsigned char *m,
  18. unsigned long long mlen,
  19. const unsigned char *n,
  20. const unsigned char *k)
  21. {
  22. crypto_onetimeauth_poly1305_state state;
  23. unsigned char block0[64U];
  24. unsigned char subkey[crypto_stream_chacha20_KEYBYTES];
  25. unsigned long long i;
  26. unsigned long long mlen0;
  27. crypto_core_hchacha20(subkey, n, k, NULL);
  28. if (((uintptr_t) c > (uintptr_t) m &&
  29. (uintptr_t) c - (uintptr_t) m < mlen) ||
  30. ((uintptr_t) m > (uintptr_t) c &&
  31. (uintptr_t) m - (uintptr_t) c < mlen)) { /* LCOV_EXCL_LINE */
  32. memmove(c, m, mlen);
  33. m = c;
  34. }
  35. memset(block0, 0U, crypto_secretbox_xchacha20poly1305_ZEROBYTES);
  36. COMPILER_ASSERT(64U >= crypto_secretbox_xchacha20poly1305_ZEROBYTES);
  37. mlen0 = mlen;
  38. if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
  39. mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
  40. }
  41. for (i = 0U; i < mlen0; i++) {
  42. block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES] = m[i];
  43. }
  44. crypto_stream_chacha20_xor(block0, block0,
  45. mlen0 + crypto_secretbox_xchacha20poly1305_ZEROBYTES,
  46. n + 16, subkey);
  47. COMPILER_ASSERT(crypto_secretbox_xchacha20poly1305_ZEROBYTES >=
  48. crypto_onetimeauth_poly1305_KEYBYTES);
  49. crypto_onetimeauth_poly1305_init(&state, block0);
  50. for (i = 0U; i < mlen0; i++) {
  51. c[i] = block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i];
  52. }
  53. sodium_memzero(block0, sizeof block0);
  54. if (mlen > mlen0) {
  55. crypto_stream_chacha20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
  56. n + 16, 1U, subkey);
  57. }
  58. sodium_memzero(subkey, sizeof subkey);
  59. crypto_onetimeauth_poly1305_update(&state, c, mlen);
  60. crypto_onetimeauth_poly1305_final(&state, mac);
  61. sodium_memzero(&state, sizeof state);
  62. return 0;
  63. }
  64. int
  65. crypto_secretbox_xchacha20poly1305_easy(unsigned char *c,
  66. const unsigned char *m,
  67. unsigned long long mlen,
  68. const unsigned char *n,
  69. const unsigned char *k)
  70. {
  71. if (mlen > crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX) {
  72. sodium_misuse();
  73. }
  74. return crypto_secretbox_xchacha20poly1305_detached
  75. (c + crypto_secretbox_xchacha20poly1305_MACBYTES, c, m, mlen, n, k);
  76. }
  77. int
  78. crypto_secretbox_xchacha20poly1305_open_detached(unsigned char *m,
  79. const unsigned char *c,
  80. const unsigned char *mac,
  81. unsigned long long clen,
  82. const unsigned char *n,
  83. const unsigned char *k)
  84. {
  85. unsigned char block0[64U];
  86. unsigned char subkey[crypto_stream_chacha20_KEYBYTES];
  87. unsigned long long i;
  88. unsigned long long mlen0;
  89. crypto_core_hchacha20(subkey, n, k, NULL);
  90. crypto_stream_chacha20(block0, crypto_stream_chacha20_KEYBYTES,
  91. n + 16, subkey);
  92. if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
  93. sodium_memzero(subkey, sizeof subkey);
  94. return -1;
  95. }
  96. if (m == NULL) {
  97. return 0;
  98. }
  99. if (((uintptr_t) c > (uintptr_t) m &&
  100. (uintptr_t) c - (uintptr_t) m < clen) ||
  101. ((uintptr_t) m > (uintptr_t) c &&
  102. (uintptr_t) m - (uintptr_t) c < clen)) { /* LCOV_EXCL_LINE */
  103. memmove(m, c, clen);
  104. c = m;
  105. }
  106. mlen0 = clen;
  107. if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) {
  108. mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES;
  109. }
  110. for (i = 0U; i < mlen0; i++) {
  111. block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i] = c[i];
  112. }
  113. crypto_stream_chacha20_xor(block0, block0,
  114. crypto_secretbox_xchacha20poly1305_ZEROBYTES + mlen0,
  115. n + 16, subkey);
  116. for (i = 0U; i < mlen0; i++) {
  117. m[i] = block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES];
  118. }
  119. if (clen > mlen0) {
  120. crypto_stream_chacha20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
  121. n + 16, 1U, subkey);
  122. }
  123. sodium_memzero(subkey, sizeof subkey);
  124. return 0;
  125. }
  126. int
  127. crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m,
  128. const unsigned char *c,
  129. unsigned long long clen,
  130. const unsigned char *n,
  131. const unsigned char *k)
  132. {
  133. if (clen < crypto_secretbox_xchacha20poly1305_MACBYTES) {
  134. return -1;
  135. }
  136. return crypto_secretbox_xchacha20poly1305_open_detached
  137. (m, c + crypto_secretbox_xchacha20poly1305_MACBYTES, c,
  138. clen - crypto_secretbox_xchacha20poly1305_MACBYTES, n, k);
  139. }
  140. size_t
  141. crypto_secretbox_xchacha20poly1305_keybytes(void)
  142. {
  143. return crypto_secretbox_xchacha20poly1305_KEYBYTES;
  144. }
  145. size_t
  146. crypto_secretbox_xchacha20poly1305_noncebytes(void)
  147. {
  148. return crypto_secretbox_xchacha20poly1305_NONCEBYTES;
  149. }
  150. size_t
  151. crypto_secretbox_xchacha20poly1305_macbytes(void)
  152. {
  153. return crypto_secretbox_xchacha20poly1305_MACBYTES;
  154. }
  155. size_t
  156. crypto_secretbox_xchacha20poly1305_messagebytes_max(void)
  157. {
  158. return crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX;
  159. }