From 2ace041fd9011d5ea81db5bc0673eb649136dd6f Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 26 Nov 2016 19:45:24 +0100 Subject: [PATCH] Add secretbox_xchacha20poly1305_easy --- src/libsodium/Makefile.am | 1 + .../secretbox_xchacha20poly1305_easy.c | 150 ++++++++++++++++++ .../crypto_secretbox_xchacha20poly1305.h | 37 ++++- 3 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/libsodium/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_easy.c diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 37caeb76..7591972b 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -176,6 +176,7 @@ libsodium_la_SOURCES += \ crypto_core/salsa208/ref/core_salsa208.c \ crypto_core/salsa208/core_salsa208_api.c \ crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_api.c \ + crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_easy.c \ crypto_secretbox/xchacha20poly1305/sodium/secretbox_xchacha20poly1305.c \ crypto_sign/ed25519/ref10/obsolete.c \ crypto_stream/aes128ctr/portable/afternm_aes128ctr.c \ diff --git a/src/libsodium/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_easy.c b/src/libsodium/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_easy.c new file mode 100644 index 00000000..e528f530 --- /dev/null +++ b/src/libsodium/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305_easy.c @@ -0,0 +1,150 @@ + +#include +#include +#include +#include +#include + +#include "crypto_core_hchacha20.h" +#include "crypto_onetimeauth_poly1305.h" +#include "crypto_secretbox_xchacha20poly1305.h" +#include "crypto_stream_chacha20.h" +#include "utils.h" + +int +crypto_secretbox_xchacha20poly1305_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]; + unsigned char subkey[crypto_stream_chacha20_KEYBYTES]; + unsigned long long i; + unsigned long long mlen0; + + crypto_core_hchacha20(subkey, n, k, NULL); + + if (((uintptr_t) c >= (uintptr_t) m && + (uintptr_t) c - (uintptr_t) m < mlen) || + ((uintptr_t) m >= (uintptr_t) c && + (uintptr_t) m - (uintptr_t) c < mlen)) { + memmove(c, m, mlen); + m = c; + } + memset(block0, 0U, crypto_secretbox_xchacha20poly1305_ZEROBYTES); + (void) sizeof(int[64U >= crypto_secretbox_xchacha20poly1305_ZEROBYTES ? + 1 : -1]); + mlen0 = mlen; + if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) { + mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES; + } + for (i = 0U; i < mlen0; i++) { + block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES] = m[i]; + } + crypto_stream_chacha20_xor(block0, block0, + mlen0 + crypto_secretbox_xchacha20poly1305_ZEROBYTES, + n + 16, subkey); + (void) sizeof(int[crypto_secretbox_xchacha20poly1305_ZEROBYTES >= + crypto_onetimeauth_poly1305_KEYBYTES ? 1 : -1]); + crypto_onetimeauth_poly1305_init(&state, block0); + + for (i = 0U; i < mlen0; i++) { + c[i] = block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i]; + } + sodium_memzero(block0, sizeof block0); + if (mlen > mlen0) { + crypto_stream_chacha20_xor_ic(c + mlen0, m + mlen0, mlen - mlen0, + n + 16, 1U, subkey); + } + sodium_memzero(subkey, sizeof subkey); + + crypto_onetimeauth_poly1305_update(&state, c, mlen); + crypto_onetimeauth_poly1305_final(&state, mac); + sodium_memzero(&state, sizeof state); + + return 0; +} + +int +crypto_secretbox_xchacha20poly1305_easy(unsigned char *c, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, + const unsigned char *k) +{ + if (mlen > SIZE_MAX - crypto_secretbox_xchacha20poly1305_MACBYTES) { + return -1; + } + return crypto_secretbox_xchacha20poly1305_detached + (c + crypto_secretbox_xchacha20poly1305_MACBYTES, c, m, mlen, n, k); +} + +int +crypto_secretbox_xchacha20poly1305_open_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_chacha20_KEYBYTES]; + unsigned long long i; + unsigned long long mlen0; + + crypto_core_hchacha20(subkey, n, k, NULL); + crypto_stream_chacha20(block0, crypto_stream_chacha20_KEYBYTES, + n + 16, subkey); + if (crypto_onetimeauth_poly1305_verify(mac, c, clen, block0) != 0) { + sodium_memzero(subkey, sizeof subkey); + return -1; + } + if (m == NULL) { + return 0; + } + if (((uintptr_t) c >= (uintptr_t) m && + (uintptr_t) c - (uintptr_t) m < clen) || + ((uintptr_t) m >= (uintptr_t) c && + (uintptr_t) m - (uintptr_t) c < clen)) { + memmove(m, c, clen); + c = m; + } + mlen0 = clen; + if (mlen0 > 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES) { + mlen0 = 64U - crypto_secretbox_xchacha20poly1305_ZEROBYTES; + } + for (i = 0U; i < mlen0; i++) { + block0[crypto_secretbox_xchacha20poly1305_ZEROBYTES + i] = c[i]; + } + crypto_stream_chacha20_xor(block0, block0, + crypto_secretbox_xchacha20poly1305_ZEROBYTES + mlen0, + n + 16, subkey); + for (i = 0U; i < mlen0; i++) { + m[i] = block0[i + crypto_secretbox_xchacha20poly1305_ZEROBYTES]; + } + if (clen > mlen0) { + crypto_stream_chacha20_xor_ic(m + mlen0, c + mlen0, clen - mlen0, + n + 16, 1U, subkey); + } + sodium_memzero(subkey, sizeof subkey); + + return 0; +} + +int +crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m, + const unsigned char *c, + unsigned long long clen, + const unsigned char *n, + const unsigned char *k) +{ + if (clen < crypto_secretbox_xchacha20poly1305_MACBYTES) { + return -1; + } + return crypto_secretbox_xchacha20poly1305_open_detached + (m, c + crypto_secretbox_xchacha20poly1305_MACBYTES, c, + clen - crypto_secretbox_xchacha20poly1305_MACBYTES, n, k); +} diff --git a/src/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h b/src/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h index 3129cd1f..40f490a1 100644 --- a/src/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h +++ b/src/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h @@ -23,6 +23,40 @@ size_t crypto_secretbox_xchacha20poly1305_noncebytes(void); SODIUM_EXPORT size_t crypto_secretbox_xchacha20poly1305_macbytes(void); +SODIUM_EXPORT +int crypto_secretbox_xchacha20poly1305_easy(unsigned char *c, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, + const unsigned char *k); + +SODIUM_EXPORT +int crypto_secretbox_xchacha20poly1305_open_easy(unsigned char *m, + const unsigned char *c, + unsigned long long clen, + const unsigned char *n, + const unsigned char *k) + __attribute__ ((warn_unused_result)); + +SODIUM_EXPORT +int crypto_secretbox_xchacha20poly1305_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_xchacha20poly1305_open_detached(unsigned char *m, + const unsigned char *c, + const unsigned char *mac, + unsigned long long clen, + const unsigned char *n, + const unsigned char *k) + __attribute__ ((warn_unused_result)); + +/* -- NaCl-like interface ; Requires padding -- */ + #define crypto_secretbox_xchacha20poly1305_BOXZEROBYTES 16U SODIUM_EXPORT size_t crypto_secretbox_xchacha20poly1305_boxzerobytes(void); @@ -45,7 +79,8 @@ int crypto_secretbox_xchacha20poly1305_open(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, - const unsigned char *k); + const unsigned char *k) + __attribute__ ((warn_unused_result)); #ifdef __cplusplus }