crypto_secretbox_easy.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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_hsalsa20.h"
  8. #include "crypto_onetimeauth_poly1305.h"
  9. #include "crypto_secretbox.h"
  10. #include "crypto_stream_salsa20.h"
  11. #include "private/common.h"
  12. #include "utils.h"
  13. int
  14. crypto_secretbox_detached(unsigned char *c, unsigned char *mac,
  15. const unsigned char *m,
  16. unsigned long long mlen, const unsigned char *n,
  17. const unsigned char *k)
  18. {
  19. crypto_onetimeauth_poly1305_state state;
  20. unsigned char block0[64U];
  21. unsigned char subkey[crypto_stream_salsa20_KEYBYTES];
  22. unsigned long long i;
  23. unsigned long long mlen0;
  24. crypto_core_hsalsa20(subkey, n, k, NULL);
  25. if (((uintptr_t) c > (uintptr_t) m &&
  26. (uintptr_t) c - (uintptr_t) m < mlen) ||
  27. ((uintptr_t) m > (uintptr_t) c &&
  28. (uintptr_t) m - (uintptr_t) c < mlen)) { /* LCOV_EXCL_LINE */
  29. memmove(c, m, mlen);
  30. m = c;
  31. }
  32. memset(block0, 0U, crypto_secretbox_ZEROBYTES);
  33. COMPILER_ASSERT(64U >= crypto_secretbox_ZEROBYTES);
  34. mlen0 = mlen;
  35. if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
  36. mlen0 = 64U - crypto_secretbox_ZEROBYTES;
  37. }
  38. for (i = 0U; i < mlen0; i++) {
  39. block0[i + crypto_secretbox_ZEROBYTES] = m[i];
  40. }
  41. crypto_stream_salsa20_xor(block0, block0,
  42. mlen0 + crypto_secretbox_ZEROBYTES,
  43. n + 16, subkey);
  44. COMPILER_ASSERT(crypto_secretbox_ZEROBYTES >=
  45. crypto_onetimeauth_poly1305_KEYBYTES);
  46. crypto_onetimeauth_poly1305_init(&state, block0);
  47. for (i = 0U; i < mlen0; i++) {
  48. c[i] = block0[crypto_secretbox_ZEROBYTES + i];
  49. }
  50. sodium_memzero(block0, sizeof block0);
  51. if (mlen > mlen0) {
  52. crypto_stream_salsa20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0,
  53. n + 16, 1U, subkey);
  54. }
  55. sodium_memzero(subkey, sizeof subkey);
  56. crypto_onetimeauth_poly1305_update(&state, c, mlen);
  57. crypto_onetimeauth_poly1305_final(&state, mac);
  58. sodium_memzero(&state, sizeof state);
  59. return 0;
  60. }
  61. int
  62. crypto_secretbox_easy(unsigned char *c, const unsigned char *m,
  63. unsigned long long mlen, const unsigned char *n,
  64. const unsigned char *k)
  65. {
  66. if (mlen > crypto_secretbox_MESSAGEBYTES_MAX) {
  67. sodium_misuse();
  68. }
  69. return crypto_secretbox_detached(c + crypto_secretbox_MACBYTES,
  70. c, m, mlen, n, k);
  71. }
  72. int
  73. crypto_secretbox_open_detached(unsigned char *m, const unsigned char *c,
  74. const unsigned char *mac,
  75. unsigned long long clen,
  76. const unsigned char *n,
  77. const unsigned char *k)
  78. {
  79. unsigned char block0[64U];
  80. unsigned char subkey[crypto_stream_salsa20_KEYBYTES];
  81. unsigned long long i;
  82. unsigned long long mlen0;
  83. crypto_core_hsalsa20(subkey, n, k, NULL);
  84. crypto_stream_salsa20(block0, crypto_stream_salsa20_KEYBYTES,
  85. n + 16, subkey);
  86. if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) {
  87. sodium_memzero(subkey, sizeof subkey);
  88. return -1;
  89. }
  90. if (m == NULL) {
  91. return 0;
  92. }
  93. if (((uintptr_t) c > (uintptr_t) m &&
  94. (uintptr_t) c - (uintptr_t) m < clen) ||
  95. ((uintptr_t) m > (uintptr_t) c &&
  96. (uintptr_t) m - (uintptr_t) c < clen)) { /* LCOV_EXCL_LINE */
  97. memmove(m, c, clen);
  98. c = m;
  99. }
  100. mlen0 = clen;
  101. if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) {
  102. mlen0 = 64U - crypto_secretbox_ZEROBYTES;
  103. }
  104. for (i = 0U; i < mlen0; i++) {
  105. block0[crypto_secretbox_ZEROBYTES + i] = c[i];
  106. }
  107. crypto_stream_salsa20_xor(block0, block0,
  108. crypto_secretbox_ZEROBYTES + mlen0,
  109. n + 16, subkey);
  110. for (i = 0U; i < mlen0; i++) {
  111. m[i] = block0[i + crypto_secretbox_ZEROBYTES];
  112. }
  113. if (clen > mlen0) {
  114. crypto_stream_salsa20_xor_ic(m + mlen0, c + mlen0, clen - mlen0,
  115. n + 16, 1U, subkey);
  116. }
  117. sodium_memzero(subkey, sizeof subkey);
  118. return 0;
  119. }
  120. int
  121. crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c,
  122. unsigned long long clen, const unsigned char *n,
  123. const unsigned char *k)
  124. {
  125. if (clen < crypto_secretbox_MACBYTES) {
  126. return -1;
  127. }
  128. return crypto_secretbox_open_detached(m, c + crypto_secretbox_MACBYTES, c,
  129. clen - crypto_secretbox_MACBYTES,
  130. n, k);
  131. }