From 5e4e6d099e5355bd5db11b126acd0004b3722a26 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 13 Oct 2017 05:44:06 +0200 Subject: blake2s: modernize API and have faster _final --- src/crypto/blake2s.c | 52 +++++++++------------------------------------ src/crypto/blake2s.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/src/crypto/blake2s.c b/src/crypto/blake2s.c index 52d635c..1fe4600 100644 --- a/src/crypto/blake2s.c +++ b/src/crypto/blake2s.c @@ -17,7 +17,8 @@ typedef struct { u8 fanout; u8 depth; u32 leaf_length; - u8 node_offset[6]; + u32 node_offset; + u16 xof_length; u8 node_depth; u8 inner_length; u8 salt[8]; @@ -73,7 +74,7 @@ static inline void blake2s_init_param(struct blake2s_state *state, const blake2s state->h[i] ^= le32_to_cpu(p[i]); } -void blake2s_init(struct blake2s_state *state, const u8 outlen) +void blake2s_init(struct blake2s_state *state, const size_t outlen) { blake2s_param param __aligned(__alignof__(u32)) = { .digest_length = outlen, @@ -87,7 +88,7 @@ void blake2s_init(struct blake2s_state *state, const u8 outlen) blake2s_init_param(state, ¶m); } -void blake2s_init_key(struct blake2s_state *state, const u8 outlen, const void *key, const u8 keylen) +void blake2s_init_key(struct blake2s_state *state, const size_t outlen, const void *key, const size_t keylen) { blake2s_param param = { .digest_length = outlen, @@ -202,7 +203,7 @@ static inline void blake2s_compress(struct blake2s_state *state, const u8 *block } } -void blake2s_update(struct blake2s_state *state, const u8 *in, u64 inlen) +void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) { const size_t fill = BLAKE2S_BLOCKBYTES - state->buflen; if (unlikely(!inlen)) @@ -225,52 +226,19 @@ void blake2s_update(struct blake2s_state *state, const u8 *in, u64 inlen) state->buflen += inlen; } -void blake2s_final(struct blake2s_state *state, u8 *out, u8 outlen) +void __blake2s_final(struct blake2s_state *state) { - u8 buffer[BLAKE2S_OUTBYTES] __aligned(__alignof__(u32)) = { 0 }; - int i; - -#ifdef DEBUG - BUG_ON(!out || !outlen || outlen > BLAKE2S_OUTBYTES); -#endif - blake2s_set_lastblock(state); memset(state->buf + state->buflen, 0, BLAKE2S_BLOCKBYTES - state->buflen); /* Padding */ blake2s_compress(state, state->buf, 1, state->buflen); - - for (i = 0; i < 8; ++i) /* output full hash to temp buffer */ - *(__le32 *)(buffer + sizeof(state->h[i]) * i) = cpu_to_le32(state->h[i]); - - memcpy(out, buffer, outlen); - - /* Burn state from stack */ - memzero_explicit(buffer, BLAKE2S_OUTBYTES); - memzero_explicit(state, sizeof(struct blake2s_state)); -} - -void blake2s(u8 *out, const u8 *in, const u8 *key, const u8 outlen, u64 inlen, const u8 keylen) -{ - struct blake2s_state state; - -#ifdef DEBUG - BUG_ON((!in && inlen > 0) || !out || !outlen || outlen > BLAKE2S_OUTBYTES || keylen > BLAKE2S_KEYBYTES); -#endif - - if (keylen > 0 && key) - blake2s_init_key(&state, outlen, key, keylen); - else - blake2s_init(&state, outlen); - - blake2s_update(&state, in, inlen); - blake2s_final(&state, out, outlen); } -void blake2s_hmac(u8 *out, const u8 *in, const u8 *key, const u8 outlen, const u64 inlen, const u64 keylen) +void blake2s_hmac(u8 *out, const u8 *in, const u8 *key, const size_t outlen, const size_t inlen, const size_t keylen) { struct blake2s_state state; - u8 o_key[BLAKE2S_BLOCKBYTES] = { 0 }; - u8 i_key[BLAKE2S_BLOCKBYTES] = { 0 }; - u8 i_hash[BLAKE2S_OUTBYTES]; + u8 o_key[BLAKE2S_BLOCKBYTES] __aligned(__alignof__(u32)) = { 0 }; + u8 i_key[BLAKE2S_BLOCKBYTES] __aligned(__alignof__(u32)) = { 0 }; + u8 i_hash[BLAKE2S_OUTBYTES] __aligned(__alignof__(u32)); int i; if (keylen > BLAKE2S_BLOCKBYTES) { diff --git a/src/crypto/blake2s.h b/src/crypto/blake2s.h index 0b1d680..615010f 100644 --- a/src/crypto/blake2s.h +++ b/src/crypto/blake2s.h @@ -20,14 +20,62 @@ struct blake2s_state { u8 last_node; }; -void blake2s(u8 *out, const u8 *in, const u8 *key, const u8 outlen, const u64 inlen, const u8 keylen); +void blake2s_init(struct blake2s_state *state, const size_t outlen); +void blake2s_init_key(struct blake2s_state *state, const size_t outlen, const void *key, const size_t keylen); +void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen); +void __blake2s_final(struct blake2s_state *state); +static inline void blake2s_final(struct blake2s_state *state, u8 *out, size_t outlen) +{ + int i; -void blake2s_init(struct blake2s_state *state, const u8 outlen); -void blake2s_init_key(struct blake2s_state *state, const u8 outlen, const void *key, const u8 keylen); -void blake2s_update(struct blake2s_state *state, const u8 *in, u64 inlen); -void blake2s_final(struct blake2s_state *state, u8 *out, u8 outlen); +#ifdef DEBUG + BUG_ON(!out || !outlen || outlen > BLAKE2S_OUTBYTES); +#endif + __blake2s_final(state); + + if (__builtin_constant_p(outlen) && !(outlen % sizeof(u32))) { + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || IS_ALIGNED((unsigned long)out, __alignof__(u32))) { + __le32 *outwords = (__le32 *)out; + for (i = 0; i < outlen / sizeof(u32); ++i) + outwords[i] = cpu_to_le32(state->h[i]); + } else { + __le32 buffer[BLAKE2S_OUTBYTES]; + for (i = 0; i < outlen / sizeof(u32); ++i) + buffer[i] = cpu_to_le32(state->h[i]); + memcpy(out, buffer, outlen); + memzero_explicit(buffer, sizeof(buffer)); + } + } else { + u8 buffer[BLAKE2S_OUTBYTES] __aligned(__alignof__(u32)); + __le32 *outwords = (__le32 *)buffer; + for (i = 0; i < 8; ++i) + outwords[i] = cpu_to_le32(state->h[i]); + memcpy(out, buffer, outlen); + memzero_explicit(buffer, sizeof(buffer)); + } + + memzero_explicit(state, sizeof(struct blake2s_state)); +} + + +static inline void blake2s(u8 *out, const u8 *in, const u8 *key, const size_t outlen, size_t inlen, const size_t keylen) +{ + struct blake2s_state state; + +#ifdef DEBUG + BUG_ON((!in && inlen > 0) || !out || !outlen || outlen > BLAKE2S_OUTBYTES || keylen > BLAKE2S_KEYBYTES || (!key && keylen)); +#endif + + if (keylen) + blake2s_init_key(&state, outlen, key, keylen); + else + blake2s_init(&state, outlen); + + blake2s_update(&state, in, inlen); + blake2s_final(&state, out, outlen); +} -void blake2s_hmac(u8 *out, const u8 *in, const u8 *key, const u8 outlen, const u64 inlen, const u64 keylen); +void blake2s_hmac(u8 *out, const u8 *in, const u8 *key, const size_t outlen, const size_t inlen, const size_t keylen); void blake2s_fpu_init(void); -- cgit v1.2.3-59-g8ed1b