diff options
Diffstat (limited to 'src/libcryptobox/cryptobox.c')
-rw-r--r-- | src/libcryptobox/cryptobox.c | 236 |
1 files changed, 112 insertions, 124 deletions
diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index 4d42ddb38..c8560925d 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -23,11 +23,6 @@ #include "cryptobox.h" #include "platform_config.h" #include "chacha20/chacha.h" -#include "poly1305/poly1305.h" -#include "curve25519/curve25519.h" -#include "ed25519/ed25519.h" -#include "blake2/blake2.h" -#include "siphash/siphash.h" #include "catena/catena.h" #include "base64/base64.h" #include "ottery.h" @@ -58,6 +53,9 @@ #include <signal.h> #include <setjmp.h> +#include <stdalign.h> + +#include <sodium.h> unsigned long cpu_config = 0; @@ -69,78 +67,6 @@ static const guchar n0[16] = {0}; #define cryptobox_align_ptr(p, a) \ (void *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1)) -#ifdef HAVE_WEAK_SYMBOLS -__attribute__((weak)) void -_dummy_symbol_to_prevent_lto_memzero(void * const pnt, const size_t len); -__attribute__((weak)) void -_dummy_symbol_to_prevent_lto_memzero(void * const pnt, const size_t len) -{ - (void) pnt; - (void) len; -} - -__attribute__((weak)) void -_dummy_symbol_to_prevent_lto_memcmp(const unsigned char *b1, - const unsigned char *b2, - const size_t len); -__attribute__((weak)) void -_dummy_symbol_to_prevent_lto_memcmp(const unsigned char *b1, - const unsigned char *b2, - const size_t len) -{ - (void) b1; - (void) b2; - (void) len; -} -#endif - -void -rspamd_explicit_memzero(void * const pnt, const gsize len) -{ -#if defined(HAVE_MEMSET_S) - if (memset_s (pnt, (rsize_t) len, 0, (rsize_t) len) != 0) { - g_assert (0); - } -#elif defined(HAVE_EXPLICIT_BZERO) - explicit_bzero (pnt, len); -#elif defined(HAVE_WEAK_SYMBOLS) - memset (pnt, 0, len); - _dummy_symbol_to_prevent_lto_memzero (pnt, len); -#else - volatile unsigned char *pnt_ = (volatile unsigned char *) pnt; - gsize i = (gsize) 0U; - while (i < len) { - pnt_[i++] = 0U; - } -#endif -} - -gint -rspamd_cryptobox_memcmp (const void *const b1_, const void *const b2_, gsize len) -{ -#ifdef HAVE_WEAK_SYMBOLS - const unsigned char *b1 = (const unsigned char *) b1_; - const unsigned char *b2 = (const unsigned char *) b2_; -#else - const volatile unsigned char *volatile b1 = - (const volatile unsigned char *volatile) b1_; - const volatile unsigned char *volatile b2 = - (const volatile unsigned char *volatile) b2_; -#endif - gsize i; - volatile unsigned char d = 0U; - -#if HAVE_WEAK_SYMBOLS - _dummy_symbol_to_prevent_lto_memcmp (b1, b2, len); -#endif - - for (i = 0U; i < len; i++) { - d |= b1[i] ^ b2[i]; - } - - return (1 & ((d - 1) >> 8)) - 1; -} - static void rspamd_cryptobox_cpuid (gint cpu[4], gint info) { @@ -370,13 +296,9 @@ rspamd_cryptobox_init (void) ctx->cpu_extensions = buf->str; g_string_free (buf, FALSE); ctx->cpu_config = cpu_config; + g_assert (sodium_init () != -1); ctx->chacha20_impl = chacha_load (); - ctx->poly1305_impl = poly1305_load (); - ctx->siphash_impl = siphash_load (); - ctx->curve25519_impl = curve25519_load (); - ctx->blake2_impl = blake2b_load (); - ctx->ed25519_impl = ed25519_load (); ctx->base64_impl = base64_load (); #if defined(HAVE_USABLE_OPENSSL) && (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)) /* Needed for old openssl api, not sure about LibreSSL */ @@ -398,7 +320,7 @@ rspamd_cryptobox_keypair (rspamd_pk_t pk, rspamd_sk_t sk, sk[31] &= 127; sk[31] |= 64; - curve25519_base (pk, sk); + crypto_scalarmult_base (pk, sk); } else { #ifndef HAVE_USABLE_OPENSSL @@ -438,7 +360,7 @@ rspamd_cryptobox_keypair_sig (rspamd_sig_pk_t pk, rspamd_sig_sk_t sk, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - ed25519_keypair (pk, sk); + crypto_sign_keypair (pk, sk); } else { #ifndef HAVE_USABLE_OPENSSL @@ -487,8 +409,9 @@ rspamd_cryptobox_nm (rspamd_nm_t nm, e[31] &= 127; e[31] |= 64; - curve25519 (s, e, pk); - hchacha (s, n0, nm, 20); + if (crypto_scalarmult (s, e, pk) != -1) { + hchacha (s, n0, nm, 20); + } rspamd_explicit_memzero (e, 32); } @@ -517,7 +440,7 @@ rspamd_cryptobox_nm (rspamd_nm_t nm, g_assert (len == sizeof (s)); /* Still do hchacha iteration since we are not using SHA1 KDF */ - hchacha (s, n0, nm, 20); + crypto_core_hchacha20 (nm, n0, s, NULL); EC_KEY_free (lk); EC_POINT_free (ec_pub); @@ -528,13 +451,13 @@ rspamd_cryptobox_nm (rspamd_nm_t nm, } void -rspamd_cryptobox_sign (guchar *sig, gsize *siglen_p, +rspamd_cryptobox_sign (guchar *sig, unsigned long long *siglen_p, const guchar *m, gsize mlen, const rspamd_sk_t sk, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - ed25519_sign (sig, siglen_p, m, mlen, sk); + crypto_sign (sig, siglen_p, m, mlen, sk); } else { #ifndef HAVE_USABLE_OPENSSL @@ -591,7 +514,7 @@ rspamd_cryptobox_verify (const guchar *sig, if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { if (siglen == rspamd_cryptobox_signature_bytes (RSPAMD_CRYPTOBOX_MODE_25519)) { - ret = ed25519_verify (sig, m, mlen, pk); + ret = (crypto_sign_verify_detached (sig, m, mlen, pk) == 0); } } else { @@ -653,7 +576,7 @@ static gsize rspamd_cryptobox_auth_ctx_len (enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - return sizeof (poly1305_state) + CRYPTOBOX_ALIGNMENT; + return sizeof (crypto_onetimeauth_state) + alignof (crypto_onetimeauth_state); } else { #ifndef HAVE_USABLE_OPENSSL @@ -708,13 +631,13 @@ rspamd_cryptobox_auth_init (void *auth_ctx, void *enc_ctx, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - poly1305_state *mac_ctx; + crypto_onetimeauth_state *mac_ctx; guchar RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES]; mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); memset (subkey, 0, sizeof (subkey)); chacha_update (enc_ctx, subkey, subkey, sizeof (subkey)); - poly1305_init (mac_ctx, (const poly1305_key *) subkey); + crypto_onetimeauth_init (mac_ctx, subkey); rspamd_explicit_memzero (subkey, sizeof (subkey)); return mac_ctx; @@ -739,8 +662,11 @@ rspamd_cryptobox_encrypt_update (void *enc_ctx, const guchar *in, gsize inlen, { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { gsize r; + chacha_state *s; - r = chacha_update (enc_ctx, in, out, inlen); + s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT); + + r = chacha_update (s, in, out, inlen); if (outlen != NULL) { *outlen = r; @@ -774,7 +700,10 @@ rspamd_cryptobox_auth_update (void *auth_ctx, const guchar *in, gsize inlen, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - poly1305_update (auth_ctx, in, inlen); + crypto_onetimeauth_state *mac_ctx; + + mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); + crypto_onetimeauth_update (mac_ctx, in, inlen); return TRUE; } @@ -794,7 +723,10 @@ rspamd_cryptobox_encrypt_final (void *enc_ctx, guchar *out, gsize remain, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - return chacha_final (enc_ctx, out); + chacha_state *s; + + s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT); + return chacha_final (s, out); } else { #ifndef HAVE_USABLE_OPENSSL @@ -817,7 +749,10 @@ rspamd_cryptobox_auth_final (void *auth_ctx, rspamd_mac_t sig, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - poly1305_finish (auth_ctx, sig); + crypto_onetimeauth_state *mac_ctx; + + mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); + crypto_onetimeauth_final (mac_ctx, sig); return TRUE; } @@ -880,13 +815,13 @@ rspamd_cryptobox_auth_verify_init (void *auth_ctx, void *enc_ctx, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - poly1305_state *mac_ctx; + crypto_onetimeauth_state *mac_ctx; guchar RSPAMD_ALIGNED(32) subkey[CHACHA_BLOCKBYTES]; mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); memset (subkey, 0, sizeof (subkey)); chacha_update (enc_ctx, subkey, subkey, sizeof (subkey)); - poly1305_init (mac_ctx, (const poly1305_key *) subkey); + crypto_onetimeauth_init (mac_ctx, subkey); rspamd_explicit_memzero (subkey, sizeof (subkey)); return mac_ctx; @@ -911,8 +846,10 @@ rspamd_cryptobox_decrypt_update (void *enc_ctx, const guchar *in, gsize inlen, { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { gsize r; + chacha_state *s; - r = chacha_update (enc_ctx, in, out, inlen); + s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT); + r = chacha_update (s, in, out, inlen); if (outlen != NULL) { *outlen = r; @@ -945,7 +882,10 @@ rspamd_cryptobox_auth_verify_update (void *auth_ctx, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - poly1305_update (auth_ctx, in, inlen); + crypto_onetimeauth_state *mac_ctx; + + mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); + crypto_onetimeauth_update (mac_ctx, in, inlen); return TRUE; } @@ -965,7 +905,10 @@ rspamd_cryptobox_decrypt_final (void *enc_ctx, guchar *out, gsize remain, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - chacha_final (enc_ctx, out); + chacha_state *s; + + s = cryptobox_align_ptr (enc_ctx, CRYPTOBOX_ALIGNMENT); + chacha_final (s, out); return TRUE; } @@ -993,10 +936,12 @@ rspamd_cryptobox_auth_verify_final (void *auth_ctx, const rspamd_mac_t sig, { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { rspamd_mac_t mac; + crypto_onetimeauth_state *mac_ctx; - poly1305_finish (auth_ctx, mac); + mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); + crypto_onetimeauth_final (mac_ctx, mac); - if (!poly1305_verify (mac, sig)) { + if (crypto_verify_16 (mac, sig) != 0) { return FALSE; } @@ -1025,7 +970,10 @@ rspamd_cryptobox_cleanup (void *enc_ctx, void *auth_ctx, enum rspamd_cryptobox_mode mode) { if (G_LIKELY (mode == RSPAMD_CRYPTOBOX_MODE_25519)) { - rspamd_explicit_memzero (auth_ctx, sizeof (poly1305_state)); + crypto_onetimeauth_state *mac_ctx; + + mac_ctx = cryptobox_align_ptr (auth_ctx, CRYPTOBOX_ALIGNMENT); + rspamd_explicit_memzero (mac_ctx, sizeof (*mac_ctx)); } else { #ifndef HAVE_USABLE_OPENSSL @@ -1272,7 +1220,7 @@ rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, unsigned long long inlen, const rspamd_sipkey_t k) { - siphash24 (out, in, inlen, k); + crypto_shorthash_siphash24 (out, in, inlen, k); } /* @@ -1284,8 +1232,9 @@ rspamd_cryptobox_pbkdf2 (const char *pass, gsize pass_len, const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, unsigned int rounds) { - guint8 *asalt, obuf[BLAKE2B_OUTBYTES]; - guint8 d1[BLAKE2B_OUTBYTES], d2[BLAKE2B_OUTBYTES]; + guint8 *asalt, obuf[crypto_generichash_blake2b_BYTES_MAX]; + guint8 d1[crypto_generichash_blake2b_BYTES_MAX], + d2[crypto_generichash_blake2b_BYTES_MAX]; unsigned int i, j; unsigned int count; gsize r; @@ -1305,11 +1254,44 @@ rspamd_cryptobox_pbkdf2 (const char *pass, gsize pass_len, asalt[salt_len + 1] = (count >> 16) & 0xff; asalt[salt_len + 2] = (count >> 8) & 0xff; asalt[salt_len + 3] = count & 0xff; - blake2b_keyed (d1, asalt, salt_len + 4, pass, pass_len); + + if (pass_len <= crypto_generichash_blake2b_KEYBYTES_MAX) { + crypto_generichash_blake2b (d1, sizeof (d1), asalt, salt_len + 4, + pass, pass_len); + } + else { + guint8 k[crypto_generichash_blake2b_BYTES_MAX]; + + /* + * We use additional blake2 iteration to store large key + * XXX: it is not compatible with the original implementation but safe + */ + crypto_generichash_blake2b (k, sizeof (k), pass, pass_len, + NULL, 0); + crypto_generichash_blake2b (d1, sizeof (d1), asalt, salt_len + 4, + k, sizeof (k)); + } + memcpy (obuf, d1, sizeof(obuf)); for (i = 1; i < rounds; i++) { - blake2b_keyed (d2, d1, BLAKE2B_OUTBYTES, pass, pass_len); + if (pass_len <= crypto_generichash_blake2b_KEYBYTES_MAX) { + crypto_generichash_blake2b (d2, sizeof (d2), d1, sizeof (d1), + pass, pass_len); + } + else { + guint8 k[crypto_generichash_blake2b_BYTES_MAX]; + + /* + * We use additional blake2 iteration to store large key + * XXX: it is not compatible with the original implementation but safe + */ + crypto_generichash_blake2b (k, sizeof (k), pass, pass_len, + NULL, 0); + crypto_generichash_blake2b (d2, sizeof (d2), d1, sizeof (d1), + k, sizeof (k)); + } + memcpy (d1, d2, sizeof(d1)); for (j = 0; j < sizeof(obuf); j++) { @@ -1317,7 +1299,7 @@ rspamd_cryptobox_pbkdf2 (const char *pass, gsize pass_len, } } - r = MIN(key_len, BLAKE2B_OUTBYTES); + r = MIN(key_len, crypto_generichash_blake2b_BYTES_MAX); memcpy (key, obuf, r); key += r; key_len -= r; @@ -1443,13 +1425,19 @@ rspamd_cryptobox_mac_bytes (enum rspamd_cryptobox_mode mode) } void -rspamd_cryptobox_hash_init (void *st, const guchar *key, gsize keylen) +rspamd_cryptobox_hash_init (void *p, const guchar *key, gsize keylen) { if (key != NULL && keylen > 0) { - blake2b_keyed_init (st, key, keylen); + crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p, + alignof(crypto_generichash_blake2b_state)); + crypto_generichash_blake2b_init (st, key, keylen, + crypto_generichash_blake2b_BYTES_MAX); } else { - blake2b_init (st); + crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p, + alignof(crypto_generichash_blake2b_state)); + crypto_generichash_blake2b_init (st, key, keylen, + crypto_generichash_blake2b_BYTES_MAX); } } @@ -1457,19 +1445,22 @@ rspamd_cryptobox_hash_init (void *st, const guchar *key, gsize keylen) * Update hash with data portion */ void -rspamd_cryptobox_hash_update (void *st, const guchar *data, gsize len) +rspamd_cryptobox_hash_update (void *p, const guchar *data, gsize len) { - blake2b_update (st, data, len); + crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p, + alignof(crypto_generichash_blake2b_state)); + crypto_generichash_blake2b_update (st, data, len); } /** * Output hash to the buffer of rspamd_cryptobox_HASHBYTES length */ void -rspamd_cryptobox_hash_final (void *st, guchar *out) +rspamd_cryptobox_hash_final (void *p, guchar *out) { - blake2b_final (st, out); - rspamd_explicit_memzero (st, rspamd_cryptobox_HASHSTATEBYTES); + crypto_generichash_blake2b_state *st = cryptobox_align_ptr (p, + alignof(crypto_generichash_blake2b_state)); + crypto_generichash_blake2b_final (st, out, crypto_generichash_blake2b_BYTES_MAX); } /** @@ -1481,11 +1472,8 @@ void rspamd_cryptobox_hash (guchar *out, const guchar *key, gsize keylen) { - blake2b_state RSPAMD_ALIGNED(32) st; - - rspamd_cryptobox_hash_init (&st, key, keylen); - rspamd_cryptobox_hash_update (&st, data, len); - rspamd_cryptobox_hash_final (&st, out); + crypto_generichash_blake2b (out, crypto_generichash_blake2b_BYTES_MAX, + data, len, key, keylen); } G_STATIC_ASSERT (sizeof (t1ha_context_t) <= |