From: Vsevolod Stakhov Date: Tue, 21 Apr 2015 22:17:26 +0000 (+0100) Subject: Add PBKDF2-HMAC-Blake2 function. X-Git-Tag: 0.9.0~178 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c6d26c6ded5bd55a6201f14b027308538c6bf24b;p=rspamd.git Add PBKDF2-HMAC-Blake2 function. --- diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index e1a3a2b8f..63ade4d1c 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -28,6 +28,7 @@ #include "curve25519/curve25519.h" #include "siphash/siphash.h" #include "ottery.h" +#include "blake2.h" #ifdef HAVE_CPUID_H #include #endif @@ -252,3 +253,61 @@ rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, { siphash24 (out, in, inlen, k); } + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +gboolean +rspamd_cryptobox_pbkdf(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]; + unsigned int i, j; + unsigned int count; + gsize r; + + if (rounds < 1 || key_len == 0) { + return FALSE; + } + if (salt_len == 0 || salt_len > G_MAXSIZE - 4) { + return FALSE; + } + + asalt = g_malloc (salt_len + 4); + memcpy (asalt, salt, salt_len); + + for (count = 1; key_len > 0; count++) { + asalt[salt_len + 0] = (count >> 24) & 0xff; + asalt[salt_len + 1] = (count >> 16) & 0xff; + asalt[salt_len + 2] = (count >> 8) & 0xff; + asalt[salt_len + 3] = count & 0xff; + blake2b (d1, asalt, pass, BLAKE2B_OUTBYTES, salt_len + 4, pass_len); + memcpy (obuf, d1, sizeof(obuf)); + + for (i = 1; i < rounds; i++) { + blake2b (d2, d1, pass, BLAKE2B_OUTBYTES, BLAKE2B_OUTBYTES, + pass_len); + memcpy (d1, d2, sizeof(d1)); + + for (j = 0; j < sizeof(obuf); j++) { + obuf[j] ^= d1[j]; + } + } + + r = MIN(key_len, BLAKE2B_OUTBYTES); + memcpy (key, obuf, r); + key += r; + key_len -= r; + } + + rspamd_explicit_memzero (asalt, salt_len + 4); + g_free (asalt); + rspamd_explicit_memzero (d1, sizeof (d1)); + rspamd_explicit_memzero (d2, sizeof (d2)); + rspamd_explicit_memzero (obuf, sizeof (obuf)); + + return TRUE; +} diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index b60af5619..57fb0d3ab 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -129,4 +129,19 @@ void rspamd_cryptobox_siphash (unsigned char *out, const unsigned char *in, unsigned long long inlen, const rspamd_sipkey_t k); +/** + * Derive key from password using PKCS#5 and HMAC-blake2 + * @param pass input password + * @param pass_len length of the password + * @param salt input salt + * @param salt_len length of salt + * @param key output key + * @param key_len size of the key + * @param rounds number of rounds (should be reasonably high) + * @return TRUE in case of success and FALSE if failed + */ +gboolean rspamd_cryptobox_pbkdf(const char *pass, gsize pass_len, + const guint8 *salt, gsize salt_len, guint8 *key, gsize key_len, + unsigned int rounds); + #endif /* CRYPTOBOX_H_ */