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