From 44f7a9f3cb4dab0f62a68c86dc1d0b5e82e5f451 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 26 Jun 2014 15:18:39 -0700 Subject: [PATCH] Allow the authentication tag to be stored separately from the message. Encrypting in-place and storing the tag separately is a very common need. Instead of forcing people to do their own cuisine, let's provide simple variants of the _easy interfaces to do that. --- .../crypto_secretbox/crypto_secretbox_easy.c | 104 ++++++++++-------- .../include/sodium/crypto_secretbox.h | 14 +++ test/default/secretbox_easy.c | 12 ++ test/default/secretbox_easy.exp | 19 ++++ test/default/secretbox_easy2.c | 5 + test/default/secretbox_easy2.exp | 1 + 6 files changed, 110 insertions(+), 45 deletions(-) diff --git a/src/libsodium/crypto_secretbox/crypto_secretbox_easy.c b/src/libsodium/crypto_secretbox/crypto_secretbox_easy.c index 5e89e536..31bd3639 100644 --- a/src/libsodium/crypto_secretbox/crypto_secretbox_easy.c +++ b/src/libsodium/crypto_secretbox/crypto_secretbox_easy.c @@ -16,9 +16,10 @@ static const unsigned char sigma[16] = { }; int -crypto_secretbox_easy(unsigned char *c, const unsigned char *m, - unsigned long long mlen, const unsigned char *n, - const unsigned char *k) +crypto_secretbox_easy_detached(unsigned char *c, unsigned char *mac, + const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k) { crypto_onetimeauth_poly1305_state state; unsigned char block0[64U]; @@ -45,65 +46,78 @@ crypto_secretbox_easy(unsigned char *c, const unsigned char *m, n + 16, subkey); crypto_onetimeauth_poly1305_init(&state, block0); - memcpy(c + crypto_secretbox_MACBYTES, - block0 + crypto_secretbox_ZEROBYTES, mlen0); + memcpy(c, block0 + crypto_secretbox_ZEROBYTES, mlen0); sodium_memzero(block0, sizeof block0); if (mlen > mlen0) { - crypto_stream_salsa20_xor_ic(c + crypto_secretbox_MACBYTES + mlen0, - m + mlen0, mlen - mlen0, + crypto_stream_salsa20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0, n + 16, 1U, subkey); } sodium_memzero(subkey, sizeof subkey); - crypto_onetimeauth_poly1305_update - (&state, c + crypto_secretbox_MACBYTES, mlen); - crypto_onetimeauth_poly1305_final(&state, c); + crypto_onetimeauth_poly1305_update(&state, c, mlen); + crypto_onetimeauth_poly1305_final(&state, mac); sodium_memzero(&state, sizeof state); return 0; } +int +crypto_secretbox_easy(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k) +{ + return crypto_secretbox_easy_detached(c + crypto_secretbox_MACBYTES, + c, m, mlen, n, k); +} + +int +crypto_secretbox_open_easy_detached(unsigned char *m, const unsigned char *c, + const unsigned char *mac, + unsigned long long clen, + const unsigned char *n, + const unsigned char *k) +{ + unsigned char block0[64U]; + unsigned char subkey[crypto_stream_salsa20_KEYBYTES]; + unsigned long long i; + unsigned long long mlen0; + + crypto_core_hsalsa20(subkey, n, k, sigma); + crypto_stream_salsa20(block0, crypto_stream_salsa20_KEYBYTES, + n + 16, subkey); + if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) { + sodium_memzero(subkey, sizeof subkey); + return -1; + } + mlen0 = clen; + if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) { + mlen0 = 64U - crypto_secretbox_ZEROBYTES; + } + memcpy(block0 + crypto_secretbox_ZEROBYTES, c, mlen0); + crypto_stream_salsa20_xor(block0, block0, + crypto_secretbox_ZEROBYTES + mlen0, + n + 16, subkey); + for (i = 0U; i < mlen0; i++) { + m[i] = block0[i + crypto_secretbox_ZEROBYTES]; + } + if (clen > mlen0) { + crypto_stream_salsa20_xor_ic(m + mlen0, c + mlen0, clen - mlen0, + n + 16, 1U, subkey); + } + sodium_memzero(subkey, sizeof subkey); + + return 0; +} + int crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) { - unsigned char block0[64U]; - unsigned char subkey[crypto_stream_salsa20_KEYBYTES]; - unsigned long long i; - unsigned long long mlen0; - if (clen < crypto_secretbox_MACBYTES) { return -1; } - crypto_core_hsalsa20(subkey, n, k, sigma); - crypto_stream_salsa20(block0, crypto_stream_salsa20_KEYBYTES, - n + 16, subkey); - if (crypto_onetimeauth_poly1305_verify(c, c + crypto_secretbox_MACBYTES, - clen - crypto_secretbox_MACBYTES, - block0) != 0) { - sodium_memzero(subkey, sizeof subkey); - return -1; - } - mlen0 = clen - crypto_secretbox_MACBYTES; - if (mlen0 > 64U - crypto_secretbox_ZEROBYTES) { - mlen0 = 64U - crypto_secretbox_ZEROBYTES; - } - memcpy(block0 + crypto_secretbox_ZEROBYTES, - c + crypto_secretbox_MACBYTES, mlen0); - crypto_stream_salsa20_xor(block0, block0, - crypto_secretbox_ZEROBYTES + mlen0, - n + 16, subkey); - for (i = 0U; i < mlen0; i++) { - m[i] = block0[i + crypto_secretbox_ZEROBYTES]; - } - if (clen - crypto_secretbox_MACBYTES > mlen0) { - crypto_stream_salsa20_xor_ic(m + mlen0, - c + crypto_secretbox_MACBYTES + mlen0, - clen - crypto_secretbox_MACBYTES - mlen0, - n + 16, 1U, subkey); - } - sodium_memzero(subkey, sizeof subkey); - - return 0; + return crypto_secretbox_open_easy_detached + (m, c + crypto_secretbox_MACBYTES, c, + clen - crypto_secretbox_MACBYTES, n, k); } diff --git a/src/libsodium/include/sodium/crypto_secretbox.h b/src/libsodium/include/sodium/crypto_secretbox.h index 62709ad5..cd4f2dab 100644 --- a/src/libsodium/include/sodium/crypto_secretbox.h +++ b/src/libsodium/include/sodium/crypto_secretbox.h @@ -57,6 +57,20 @@ int crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k); +SODIUM_EXPORT +int crypto_secretbox_easy_detached(unsigned char *c, unsigned char *mac, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, + const unsigned char *k); + +SODIUM_EXPORT +int crypto_secretbox_open_easy_detached(unsigned char *m, + const unsigned char *c, + const unsigned char *mac, + unsigned long long clen, + const unsigned char *n, + const unsigned char *k); #ifdef __cplusplus } #endif diff --git a/test/default/secretbox_easy.c b/test/default/secretbox_easy.c index a7279ec7..29fe6b61 100644 --- a/test/default/secretbox_easy.c +++ b/test/default/secretbox_easy.c @@ -37,15 +37,27 @@ unsigned char m[131] = { } ; unsigned char c[147 + crypto_secretbox_MACBYTES]; +unsigned char mac[crypto_secretbox_MACBYTES]; int main(void) { int i; + crypto_secretbox_easy(c, m, 131, nonce, firstkey); for (i = 0;i < 131 + crypto_secretbox_MACBYTES; ++i) { printf(",0x%02x",(unsigned int) c[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); + + crypto_secretbox_easy_detached(c, mac, m, 131, nonce, firstkey); + for (i = 0;i < crypto_secretbox_MACBYTES; ++i) { + printf(",0x%02x",(unsigned int) mac[i]); + if (i % 8 == 7) printf("\n"); + } + for (i = 0;i < 131; ++i) { + printf(",0x%02x",(unsigned int) c[i]); + if (i % 8 == 7) printf("\n"); + } return 0; } diff --git a/test/default/secretbox_easy.exp b/test/default/secretbox_easy.exp index 2b6c51ea..c4b4066b 100644 --- a/test/default/secretbox_easy.exp +++ b/test/default/secretbox_easy.exp @@ -17,3 +17,22 @@ ,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 ,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74 ,0xe3,0x55,0xa5 +,0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5 +,0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9 +,0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73 +,0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce +,0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4 +,0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a +,0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b +,0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72 +,0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2 +,0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38 +,0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a +,0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae +,0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea +,0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda +,0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde +,0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3 +,0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6 +,0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74 +,0xe3,0x55,0xa5 \ No newline at end of file diff --git a/test/default/secretbox_easy2.c b/test/default/secretbox_easy2.c index 62663a30..6367cb63 100644 --- a/test/default/secretbox_easy2.c +++ b/test/default/secretbox_easy2.c @@ -9,6 +9,7 @@ unsigned char m2[10000]; unsigned char c[crypto_secretbox_MACBYTES + 10000]; unsigned char nonce[crypto_secretbox_NONCEBYTES]; unsigned char k[crypto_secretbox_KEYBYTES]; +unsigned char mac[crypto_secretbox_MACBYTES]; int main(void) { @@ -23,5 +24,9 @@ int main(void) nonce, k); printf("%d\n", memcmp(m, m2, mlen)); + crypto_secretbox_easy_detached(c, mac, m, mlen, nonce, k); + crypto_secretbox_open_easy_detached(m2, c, mac, mlen, nonce, k); + printf("%d\n", memcmp(m, m2, mlen)); + return 0; } diff --git a/test/default/secretbox_easy2.exp b/test/default/secretbox_easy2.exp index 573541ac..aa47d0d4 100644 --- a/test/default/secretbox_easy2.exp +++ b/test/default/secretbox_easy2.exp @@ -1 +1,2 @@ 0 +0