├── README.md ├── rebar ├── .gitignore ├── Makefile ├── src ├── blake2.app.src └── blake2.erl ├── c_src ├── makefile ├── erl_nif_compat.h ├── blake2-impl.h ├── blake2_nifs.c ├── blake2.h ├── genkat.c ├── blake2sp-ref.c ├── blake2bp-ref.c ├── blake2s-ref.c └── blake2b-ref.c └── rebar.config /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rebar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/b/blake2/master/rebar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | c_src/*.o 2 | .eunit 3 | ebin/ 4 | priv/*.so 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | ./rebar -v compile 3 | 4 | clean: 5 | ./rebar -v clean 6 | 7 | eunit: 8 | ./rebar -v eunit -------------------------------------------------------------------------------- /src/blake2.app.src: -------------------------------------------------------------------------------- 1 | {application, blake2, 2 | [ 3 | {description, "BLAKE2 hash function NIF"}, 4 | {vsn, "1.0.0"}, 5 | {modules, [ 6 | blake2, 7 | hex 8 | ]}, 9 | {registered, []}, 10 | {applications, [ 11 | kernel, 12 | stdlib 13 | ]}, 14 | {env, []} 15 | ]}. 16 | -------------------------------------------------------------------------------- /c_src/makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-std=c99 -Wall -pedantic 3 | 4 | all: blake2s blake2b blake2sp blake2bp 5 | 6 | blake2s: blake2s-ref.c 7 | $(CC) $^ -o $@ $(CFLAGS) -DBLAKE2S_SELFTEST 8 | 9 | blake2b: blake2b-ref.c 10 | $(CC) $^ -o $@ $(CFLAGS) -DBLAKE2B_SELFTEST 11 | 12 | blake2sp: blake2sp-ref.c blake2s-ref.c 13 | $(CC) $^ -o $@ $(CFLAGS) -DBLAKE2SP_SELFTEST 14 | 15 | blake2bp: blake2bp-ref.c blake2b-ref.c 16 | $(CC) $^ -o $@ $(CFLAGS) -DBLAKE2BP_SELFTEST 17 | 18 | kat: 19 | $(CC) $(CFLAGS) -o genkat genkat.c blake2b-ref.c blake2s-ref.c blake2sp-ref.c blake2bp-ref.c 20 | ./genkat > blake2-kat.h 21 | 22 | clean: 23 | rm -rf *.o genkat blake2s blake2b blake2sp blake2bp 24 | -------------------------------------------------------------------------------- /rebar.config: -------------------------------------------------------------------------------- 1 | {cover_enabled, true}. 2 | 3 | {lib_dirs,["deps"]}. 4 | 5 | {erl_opts, [warnings_as_errors]}. 6 | 7 | {deps, [ 8 | {hex, ".*", {git, "git://github.com/b/hex", "HEAD"}} 9 | ]}. 10 | 11 | {port_specs, [{"priv/blake2_nifs.so", ["c_src/*.c"]}]}. 12 | 13 | {port_env, [ 14 | %% OS X Leopard flags for 64-bit 15 | {"darwin9\.*-64-unix", "CFLAGS", "-m64 -std=c99 -Wall -pedantic"}, 16 | {"darwin9\.*-64-unix", "LDFLAGS", "-arch x86_64+"}, 17 | 18 | %% OS X Snow Leopard flags for 32-bit 19 | {"darwin1?\.*-32-unix", "CFLAGS", "-m32 -std=c99 -Wall -pedantic"}, 20 | {"darwin1?\.*-32-unix", "LDFLAGS", "-arch i386"}, 21 | 22 | %% OS X Snow Leopard/Lion flags for 64-bit 23 | {"darwin1?\.*-64-unix", "CFLAGS", "-m64 -std=c99 -Wall -pedantic"}, 24 | {"darwin1?\.*-64-unix", "LDFLAGS", "-arch x86_64"} 25 | ]}. 26 | -------------------------------------------------------------------------------- /src/blake2.erl: -------------------------------------------------------------------------------- 1 | -module(blake2). 2 | -author('b@b3k.us'). 3 | 4 | -export([init/1, 5 | update/2, 6 | final/1, 7 | hash/2, 8 | hexhash/2]). 9 | 10 | -on_load(init/0). 11 | 12 | init() -> 13 | case code:priv_dir(blake2) of 14 | {error, bad_name} -> 15 | SoName = filename:join("../priv", "blake2_nifs"); 16 | Dir -> 17 | SoName = filename:join(Dir, "blake2_nifs") 18 | end, 19 | case erlang:load_nif(SoName, 0) of 20 | ok -> ok; 21 | {error, {load, _}} -> ok; 22 | {error, {reload, _}} -> ok; 23 | {error, {upgrade, _}} -> ok; 24 | Error -> Error 25 | end. 26 | 27 | -spec init(non_neg_integer()) -> {ok, binary()} | {error, atom()}. 28 | init(_Bits) -> 29 | "NIF library not loaded". 30 | 31 | -spec update(binary(), binary()) -> {ok, binary()} | {error, atom()}. 32 | update(_State, _Data) -> 33 | "NIF library not loaded". 34 | 35 | -spec final(binary()) -> {ok, binary()} | {error, atom()}. 36 | final(_State) -> 37 | "NIF library not loaded". 38 | 39 | hexhash(Bits, Data) -> 40 | {ok, Hash} = hash(Bits, Data), 41 | list_to_binary(hex:bin_to_hexstr(Hash)). 42 | 43 | -spec hash(non_neg_integer(), binary()) -> {ok, binary()} | {error, atom()}. 44 | hash(_Bits, _Data) -> 45 | "NIF library not loaded". 46 | -------------------------------------------------------------------------------- /c_src/erl_nif_compat.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010-2011 Basho Technologies, Inc. 2 | * 3 | * This file is provided to you under the Apache License, 4 | * Version 2.0 (the "License"); you may not use this file 5 | * except in compliance with the License. You may obtain 6 | * a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, 11 | * software distributed under the License is distributed on an 12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 13 | * KIND, either express or implied. See the License for the 14 | * specific language governing permissions and limitations 15 | * under the License. 16 | */ 17 | 18 | #ifndef ERL_NIF_COMPAT_H_ 19 | #define ERL_NIF_COMPAT_H_ 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif /* __cplusplus */ 24 | 25 | #include "erl_nif.h" 26 | 27 | #if ERL_NIF_MAJOR_VERSION == 1 && ERL_NIF_MINOR_VERSION == 0 28 | 29 | #define enif_open_resource_type_compat enif_open_resource_type 30 | #define enif_alloc_resource_compat enif_alloc_resource 31 | #define enif_release_resource_compat enif_release_resource 32 | #define enif_alloc_binary_compat enif_alloc_binary 33 | #define enif_alloc_compat enif_alloc 34 | #define enif_free_compat enif_free 35 | #define enif_cond_create erl_drv_cond_create 36 | #define enif_cond_destroy erl_drv_cond_destroy 37 | #define enif_cond_signal erl_drv_cond_signal 38 | #define enif_cond_broadcast erl_drv_cond_broadcast 39 | #define enif_cond_wait erl_drv_cond_wait 40 | #define ErlNifCond ErlDrvCond 41 | #endif /* R13B04 */ 42 | 43 | #if ERL_NIF_MAJOR_VERSION == 2 && ERL_NIF_MINOR_VERSION >= 0 44 | 45 | #define enif_open_resource_type_compat(E, N, D, F, T) \ 46 | enif_open_resource_type(E, NULL, N, D, F, T) 47 | 48 | #define enif_alloc_resource_compat(E, T, S) \ 49 | enif_alloc_resource(T, S) 50 | 51 | #define enif_release_resource_compat(E, H) \ 52 | enif_release_resource(H) 53 | 54 | #define enif_alloc_binary_compat(E, S, B) \ 55 | enif_alloc_binary(S, B) 56 | 57 | #define enif_alloc_compat(E, S) \ 58 | enif_alloc(S) 59 | 60 | #define enif_free_compat(E, P) \ 61 | enif_free(P) 62 | 63 | #endif /* R14 */ 64 | 65 | 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif /* __cplusplus */ 70 | 71 | #endif /* ERL_NIF_COMPAT_H_ */ 72 | -------------------------------------------------------------------------------- /c_src/blake2-impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __BLAKE2_IMPL_H__ 3 | #define __BLAKE2_IMPL_H__ 4 | 5 | #include 6 | 7 | static inline uint32_t load32( const void *src ) 8 | { 9 | #if defined(NATIVE_LITTLE_ENDIAN) 10 | return *( uint32_t * )( src ); 11 | #else 12 | const uint8_t *p = ( uint8_t * )src; 13 | uint32_t w = *p++; 14 | w |= ( uint32_t )( *p++ ) << 8; 15 | w |= ( uint32_t )( *p++ ) << 16; 16 | w |= ( uint32_t )( *p++ ) << 24; 17 | return w; 18 | #endif 19 | } 20 | 21 | static inline uint64_t load64( const void *src ) 22 | { 23 | #if defined(NATIVE_LITTLE_ENDIAN) 24 | return *( uint64_t * )( src ); 25 | #else 26 | const uint8_t *p = ( uint8_t * )src; 27 | uint64_t w = *p++; 28 | w |= ( uint64_t )( *p++ ) << 8; 29 | w |= ( uint64_t )( *p++ ) << 16; 30 | w |= ( uint64_t )( *p++ ) << 24; 31 | w |= ( uint64_t )( *p++ ) << 32; 32 | w |= ( uint64_t )( *p++ ) << 40; 33 | w |= ( uint64_t )( *p++ ) << 48; 34 | w |= ( uint64_t )( *p++ ) << 56; 35 | return w; 36 | #endif 37 | } 38 | 39 | static inline void store32( void *dst, uint32_t w ) 40 | { 41 | #if defined(NATIVE_LITTLE_ENDIAN) 42 | *( uint32_t * )( dst ) = w; 43 | #else 44 | uint8_t *p = ( uint8_t * )dst; 45 | *p++ = ( uint8_t )w; w >>= 8; 46 | *p++ = ( uint8_t )w; w >>= 8; 47 | *p++ = ( uint8_t )w; w >>= 8; 48 | *p++ = ( uint8_t )w; 49 | #endif 50 | } 51 | 52 | static inline void store64( void *dst, uint64_t w ) 53 | { 54 | #if defined(NATIVE_LITTLE_ENDIAN) 55 | *( uint64_t * )( dst ) = w; 56 | #else 57 | uint8_t *p = ( uint8_t * )dst; 58 | *p++ = ( uint8_t )w; w >>= 8; 59 | *p++ = ( uint8_t )w; w >>= 8; 60 | *p++ = ( uint8_t )w; w >>= 8; 61 | *p++ = ( uint8_t )w; w >>= 8; 62 | *p++ = ( uint8_t )w; w >>= 8; 63 | *p++ = ( uint8_t )w; w >>= 8; 64 | *p++ = ( uint8_t )w; w >>= 8; 65 | *p++ = ( uint8_t )w; 66 | #endif 67 | } 68 | 69 | static inline uint64_t load48( const void *src ) 70 | { 71 | const uint8_t *p = ( const uint8_t * )src; 72 | uint64_t w = *p++; 73 | w |= ( uint64_t )( *p++ ) << 8; 74 | w |= ( uint64_t )( *p++ ) << 16; 75 | w |= ( uint64_t )( *p++ ) << 24; 76 | w |= ( uint64_t )( *p++ ) << 32; 77 | w |= ( uint64_t )( *p++ ) << 40; 78 | return w; 79 | } 80 | 81 | static inline void store48( void *dst, uint64_t w ) 82 | { 83 | uint8_t *p = ( uint8_t * )dst; 84 | *p++ = ( uint8_t )w; w >>= 8; 85 | *p++ = ( uint8_t )w; w >>= 8; 86 | *p++ = ( uint8_t )w; w >>= 8; 87 | *p++ = ( uint8_t )w; w >>= 8; 88 | *p++ = ( uint8_t )w; w >>= 8; 89 | *p++ = ( uint8_t )w; 90 | } 91 | 92 | static inline uint32_t rotl32( const uint32_t w, const unsigned c ) 93 | { 94 | return ( w << c ) | ( w >> ( 32 - c ) ); 95 | } 96 | 97 | static inline uint64_t rotl64( const uint64_t w, const unsigned c ) 98 | { 99 | return ( w << c ) | ( w >> ( 64 - c ) ); 100 | } 101 | 102 | static inline uint32_t rotr32( const uint32_t w, const unsigned c ) 103 | { 104 | return ( w >> c ) | ( w << ( 32 - c ) ); 105 | } 106 | 107 | static inline uint64_t rotr64( const uint64_t w, const unsigned c ) 108 | { 109 | return ( w >> c ) | ( w << ( 64 - c ) ); 110 | } 111 | 112 | /* prevents compiler optimizing out memset() */ 113 | static inline void secure_zero_memory( void *v, size_t n ) 114 | { 115 | volatile uint8_t *p = ( volatile uint8_t * )v; 116 | 117 | while( n-- ) *p++ = 0; 118 | } 119 | 120 | #endif 121 | 122 | -------------------------------------------------------------------------------- /c_src/blake2_nifs.c: -------------------------------------------------------------------------------- 1 | #include "erl_nif.h" 2 | #include "erl_nif_compat.h" 3 | #include "blake2.h" 4 | 5 | static ErlNifResourceType* blake2_hashstate; 6 | 7 | typedef struct 8 | { 9 | uint8_t digest_length; 10 | blake2b_state state; 11 | } blake2_handle; 12 | 13 | // Prototypes 14 | ERL_NIF_TERM blake2_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 15 | ERL_NIF_TERM blake2_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 16 | ERL_NIF_TERM blake2_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 17 | ERL_NIF_TERM blake2_hash(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 18 | 19 | // lifecycle 20 | int load(ErlNifEnv* env, void ** priv_data, ERL_NIF_TERM load_info); 21 | int reload(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info); 22 | int upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info); 23 | void unload(ErlNifEnv* env, void* priv); 24 | 25 | static ErlNifFunc nif_funcs[] = 26 | { 27 | {"init", 1, blake2_init}, 28 | {"update", 2, blake2_update}, 29 | {"final", 1, blake2_final}, 30 | {"hash", 2, blake2_hash} 31 | }; 32 | 33 | ERL_NIF_INIT(blake2, nif_funcs, load, NULL, NULL, NULL) 34 | 35 | int load(ErlNifEnv* env, void ** priv_data, ERL_NIF_TERM load_info) 36 | { 37 | blake2_hashstate = enif_open_resource_type_compat(env, "hashstate", NULL, ERL_NIF_RT_CREATE, NULL); 38 | return 0; 39 | } 40 | 41 | int reload(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info) 42 | { 43 | return 0; 44 | } 45 | 46 | int upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info) 47 | { 48 | return 0; 49 | } 50 | 51 | void unload(ErlNifEnv* env, void* priv) 52 | { 53 | return; 54 | } 55 | 56 | ERL_NIF_TERM blake2_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 57 | { 58 | ERL_NIF_TERM handle_term; 59 | int bits = 0; 60 | if(!enif_get_int(env, argv[0], &bits)) 61 | return enif_make_badarg(env); 62 | 63 | blake2_handle *handle = (blake2_handle *)enif_alloc_resource_compat(env, blake2_hashstate, sizeof(blake2_handle)); 64 | handle->digest_length = bits / 8; 65 | 66 | int r = blake2b_init(&(handle->state), handle->digest_length); 67 | if (r == 0) { 68 | handle_term = enif_make_resource(env, handle); 69 | enif_release_resource_compat(env, handle); 70 | return enif_make_tuple2(env, enif_make_atom(env, "ok"), handle_term); 71 | } else { 72 | enif_release_resource_compat(env, handle); 73 | return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "init_failure")); 74 | } 75 | } 76 | 77 | ERL_NIF_TERM blake2_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 78 | { 79 | blake2_handle *handle = NULL; 80 | enif_get_resource(env, argv[0], blake2_hashstate, (void**)&handle); 81 | 82 | ErlNifBinary bin; 83 | enif_inspect_binary(env, argv[1], &bin); 84 | 85 | int r = blake2b_update(&(handle->state), (const uint8_t *)bin.data, (uint64_t)bin.size); 86 | if (r == 0) 87 | { 88 | return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_resource(env, handle)); 89 | } else { 90 | return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "update_failure")); 91 | } 92 | } 93 | 94 | ERL_NIF_TERM blake2_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 95 | { 96 | blake2_handle *handle = NULL; 97 | enif_get_resource(env, argv[0], blake2_hashstate, (void**)&handle); 98 | 99 | ErlNifBinary out; 100 | enif_alloc_binary_compat(env, (size_t)(handle->digest_length), &out); 101 | 102 | int r = blake2b_final(&(handle->state), (uint8_t *)out.data, handle->digest_length); 103 | if (r == 0) { 104 | return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &out)); 105 | } else { 106 | return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "finalization_failure")); 107 | } 108 | } 109 | 110 | ERL_NIF_TERM blake2_hash(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 111 | { 112 | int bits = 0; 113 | enif_get_int(env, argv[0], &bits); 114 | 115 | ErlNifBinary bin, out; 116 | enif_inspect_binary(env, argv[1], &bin); 117 | enif_alloc_binary_compat(env, (size_t)(bits/8), &out); 118 | 119 | int r = blake2b((uint8_t *)out.data, (const void *)bin.data, NULL, (bits / 8), bin.size, 0); 120 | if (r == 0) { 121 | return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &out)); 122 | } else { 123 | return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_atom(env, "hash_failure")); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /c_src/blake2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __BLAKE2_H__ 3 | #define __BLAKE2_H__ 4 | 5 | #include 6 | #include 7 | 8 | #if defined(_MSC_VER) 9 | #define ALIGN(x) __declspec(align(x)) 10 | #else 11 | #define ALIGN(x) __attribute__((aligned(x))) 12 | #endif 13 | 14 | #if defined(__cplusplus) 15 | extern "C" { 16 | #endif 17 | 18 | enum blake2s_constant 19 | { 20 | BLAKE2S_BLOCKBYTES = 64, 21 | BLAKE2S_OUTBYTES = 32, 22 | BLAKE2S_KEYBYTES = 32, 23 | BLAKE2S_SALTBYTES = 8, 24 | BLAKE2S_PERSONALBYTES = 8 25 | }; 26 | 27 | enum blake2b_constant 28 | { 29 | BLAKE2B_BLOCKBYTES = 128, 30 | BLAKE2B_OUTBYTES = 64, 31 | BLAKE2B_KEYBYTES = 64, 32 | BLAKE2B_SALTBYTES = 16, 33 | BLAKE2B_PERSONALBYTES = 16 34 | }; 35 | 36 | #pragma pack(push, 1) 37 | typedef struct __blake2s_param 38 | { 39 | uint8_t digest_length; // 1 40 | uint8_t key_length; // 2 41 | uint8_t fanout; // 3 42 | uint8_t depth; // 4 43 | uint32_t leaf_length; // 8 44 | uint8_t node_offset[6];// 14 45 | uint8_t node_depth; // 15 46 | uint8_t inner_length; // 16 47 | // uint8_t reserved[0]; 48 | uint8_t salt[BLAKE2B_SALTBYTES]; // 24 49 | uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32 50 | } blake2s_param; 51 | 52 | ALIGN( 64 ) typedef struct __blake2s_state 53 | { 54 | uint32_t h[8]; 55 | uint32_t t[2]; 56 | uint32_t f[2]; 57 | uint8_t buf[2 * BLAKE2S_BLOCKBYTES]; 58 | size_t buflen; 59 | uint8_t last_node; 60 | } blake2s_state ; 61 | 62 | typedef struct __blake2b_param 63 | { 64 | uint8_t digest_length; // 1 65 | uint8_t key_length; // 2 66 | uint8_t fanout; // 3 67 | uint8_t depth; // 4 68 | uint32_t leaf_length; // 8 69 | uint64_t node_offset; // 16 70 | uint8_t node_depth; // 17 71 | uint8_t inner_length; // 18 72 | uint8_t reserved[14]; // 32 73 | uint8_t salt[BLAKE2B_SALTBYTES]; // 48 74 | uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64 75 | } blake2b_param; 76 | 77 | ALIGN( 64 ) typedef struct __blake2b_state 78 | { 79 | uint64_t h[8]; 80 | uint64_t t[2]; 81 | uint64_t f[2]; 82 | uint8_t buf[2 * BLAKE2B_BLOCKBYTES]; 83 | size_t buflen; 84 | uint8_t last_node; 85 | } blake2b_state; 86 | 87 | typedef struct __blake2sp_state 88 | { 89 | blake2s_state S[8][1]; 90 | blake2s_state R[1]; 91 | uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; 92 | size_t buflen; 93 | } blake2sp_state; 94 | 95 | typedef struct __blake2bp_state 96 | { 97 | blake2b_state S[4][1]; 98 | blake2b_state R[1]; 99 | uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; 100 | size_t buflen; 101 | } blake2bp_state; 102 | #pragma pack(pop) 103 | 104 | // Streaming API 105 | int blake2s_init( blake2s_state *S, const uint8_t outlen ); 106 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 107 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); 108 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ); 109 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ); 110 | 111 | int blake2b_init( blake2b_state *S, const uint8_t outlen ); 112 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 113 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); 114 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ); 115 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ); 116 | 117 | int blake2sp_init( blake2sp_state *S, const uint8_t outlen ); 118 | int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 119 | int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen ); 120 | int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen ); 121 | 122 | int blake2bp_init( blake2bp_state *S, const uint8_t outlen ); 123 | int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 124 | int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen ); 125 | int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen ); 126 | 127 | // Simple API 128 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 129 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 130 | 131 | int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 132 | int blake2bp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 133 | 134 | static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 135 | { 136 | return blake2b( out, in, key, outlen, inlen, keylen ); 137 | } 138 | 139 | #if defined(__cplusplus) 140 | } 141 | #endif 142 | 143 | #endif 144 | 145 | -------------------------------------------------------------------------------- /c_src/genkat.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "blake2.h" 8 | 9 | #define STR_(x) #x 10 | #define STR(x) STR_(x) 11 | 12 | #define LENGTH 256 13 | 14 | #define MAKE_KAT(name,size_prefix) \ 15 | do \ 16 | { \ 17 | printf( "static const uint8_t " #name "_kat[KAT_LENGTH][" #size_prefix "_OUTBYTES] = \n{\n" ); \ 18 | \ 19 | for( size_t i = 0; i < LENGTH; ++i ) \ 20 | { \ 21 | name( hash, in, NULL, size_prefix ## _OUTBYTES, i, 0 ); \ 22 | printf( "\t{\n\t\t" ); \ 23 | \ 24 | for( int j = 0; j < size_prefix ## _OUTBYTES; ++j ) \ 25 | printf( "0x%02X%s", hash[j], ( j + 1 ) == size_prefix ## _OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); \ 26 | \ 27 | printf( "\t},\n" ); \ 28 | } \ 29 | \ 30 | printf( "};\n\n\n\n\n" ); \ 31 | \ 32 | } while (0) 33 | 34 | #define MAKE_KEYED_KAT(name,size_prefix) \ 35 | do \ 36 | { \ 37 | printf( "static const uint8_t " #name "_keyed_kat[KAT_LENGTH][" #size_prefix "_OUTBYTES] = \n{\n" ); \ 38 | \ 39 | for( size_t i = 0; i < LENGTH; ++i ) \ 40 | { \ 41 | name( hash, in, key, size_prefix ## _OUTBYTES, i, size_prefix ## _KEYBYTES ); \ 42 | printf( "\t{\n\t\t" ); \ 43 | \ 44 | for( int j = 0; j < size_prefix ## _OUTBYTES; ++j ) \ 45 | printf( "0x%02X%s", hash[j], ( j + 1 ) == size_prefix ## _OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); \ 46 | \ 47 | printf( "\t},\n" ); \ 48 | } \ 49 | \ 50 | printf( "};\n\n\n\n\n" ); \ 51 | \ 52 | } while (0) 53 | 54 | 55 | int main( int argc, char **argv ) 56 | { 57 | uint8_t key[64] = {0}; 58 | uint8_t in[LENGTH] = {0}; 59 | uint8_t hash[64] = {0}; 60 | 61 | for( size_t i = 0; i < sizeof( in ); ++i ) 62 | in[i] = i; 63 | 64 | for( size_t i = 0; i < sizeof( key ); ++i ) 65 | key[i] = i; 66 | 67 | puts( "#pragma once\n" 68 | "#ifndef __BLAKE2_KAT_H__\n" 69 | "#define __BLAKE2_KAT_H__\n\n\n" 70 | "#include \n\n" 71 | "#define KAT_LENGTH " STR( LENGTH ) "\n\n\n" ); 72 | MAKE_KAT( blake2s, BLAKE2S ); 73 | MAKE_KEYED_KAT( blake2s, BLAKE2S ); 74 | MAKE_KAT( blake2b, BLAKE2B ); 75 | MAKE_KEYED_KAT( blake2b, BLAKE2B ); 76 | MAKE_KAT( blake2sp, BLAKE2S ); 77 | MAKE_KEYED_KAT( blake2sp, BLAKE2S ); 78 | MAKE_KAT( blake2bp, BLAKE2B ); 79 | MAKE_KEYED_KAT( blake2bp, BLAKE2B ); 80 | /*printf( "static const uint8_t blake2s_kat[KAT_LENGTH][BLAKE2S_OUTBYTES] = \n{\n" ); 81 | 82 | for( size_t i = 0; i < LENGTH; ++i ) 83 | { 84 | blake2s( hash, in, NULL, BLAKE2S_OUTBYTES, i, 0 ); 85 | printf( "\t{\n\t\t" ); 86 | 87 | for( int j = 0; j < BLAKE2S_OUTBYTES; ++j ) 88 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2S_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 89 | 90 | printf( "\t},\n" ); 91 | } 92 | 93 | printf( "};\n\n\n\n\n" ); 94 | printf( "static const uint8_t blake2s_keyed_kat[KAT_LENGTH][BLAKE2S_OUTBYTES] = \n{\n" ); 95 | 96 | for( size_t i = 0; i < LENGTH; ++i ) 97 | { 98 | blake2s( hash, in, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); 99 | printf( "\t{\n\t\t" ); 100 | 101 | for( int j = 0; j < BLAKE2S_OUTBYTES; ++j ) 102 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2S_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 103 | 104 | printf( "\t},\n" ); 105 | } 106 | 107 | printf( "};\n\n\n\n\n" ); 108 | printf( "static const uint8_t blake2b_kat[KAT_LENGTH][BLAKE2B_OUTBYTES] = \n{\n" ); 109 | 110 | for( size_t i = 0; i < LENGTH; ++i ) 111 | { 112 | blake2b( hash, in, NULL, BLAKE2B_OUTBYTES, i, 0 ); 113 | printf( "\t{\n\t\t" ); 114 | 115 | for( int j = 0; j < BLAKE2B_OUTBYTES; ++j ) 116 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2B_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 117 | 118 | printf( "\t},\n" ); 119 | } 120 | 121 | printf( "};\n\n\n\n\n" ); 122 | printf( "static const uint8_t blake2b_keyed_kat[KAT_LENGTH][BLAKE2B_OUTBYTES] = \n{\n" ); 123 | 124 | for( size_t i = 0; i < LENGTH; ++i ) 125 | { 126 | blake2b( hash, in, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 127 | printf( "\t{\n\t\t" ); 128 | 129 | for( int j = 0; j < BLAKE2B_OUTBYTES; ++j ) 130 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2B_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 131 | 132 | printf( "\t},\n" ); 133 | } 134 | 135 | printf( "};\n\n\n\n\n" ); 136 | 137 | 138 | printf( "static const uint8_t blake2sp_kat[KAT_LENGTH][BLAKE2S_OUTBYTES] = \n{\n" ); 139 | 140 | for( size_t i = 0; i < LENGTH; ++i ) 141 | { 142 | blake2sp( hash, in, NULL, BLAKE2S_OUTBYTES, i, 0 ); 143 | printf( "\t{\n\t\t" ); 144 | 145 | for( int j = 0; j < BLAKE2S_OUTBYTES; ++j ) 146 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2S_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 147 | 148 | printf( "\t},\n" ); 149 | } 150 | 151 | printf( "};\n\n\n\n\n" ); 152 | printf( "static const uint8_t blake2sp_keyed_kat[KAT_LENGTH][BLAKE2S_OUTBYTES] = \n{\n" ); 153 | 154 | for( size_t i = 0; i < LENGTH; ++i ) 155 | { 156 | blake2sp( hash, in, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); 157 | printf( "\t{\n\t\t" ); 158 | 159 | for( int j = 0; j < BLAKE2S_OUTBYTES; ++j ) 160 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2S_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 161 | 162 | printf( "\t},\n" ); 163 | } 164 | 165 | printf( "};\n\n\n\n\n" ); 166 | 167 | 168 | printf( "static const uint8_t blake2bp_kat[KAT_LENGTH][BLAKE2B_OUTBYTES] = \n{\n" ); 169 | 170 | for( size_t i = 0; i < LENGTH; ++i ) 171 | { 172 | blake2bp( hash, in, NULL, BLAKE2B_OUTBYTES, i, 0 ); 173 | printf( "\t{\n\t\t" ); 174 | 175 | for( int j = 0; j < BLAKE2B_OUTBYTES; ++j ) 176 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2B_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 177 | 178 | printf( "\t},\n" ); 179 | } 180 | 181 | printf( "};\n\n\n\n\n" ); 182 | printf( "static const uint8_t blake2bp_keyed_kat[KAT_LENGTH][BLAKE2B_OUTBYTES] = \n{\n" ); 183 | 184 | for( size_t i = 0; i < LENGTH; ++i ) 185 | { 186 | blake2bp( hash, in, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 187 | printf( "\t{\n\t\t" ); 188 | 189 | for( int j = 0; j < BLAKE2B_OUTBYTES; ++j ) 190 | printf( "0x%02X%s", hash[j], ( j + 1 ) == BLAKE2B_OUTBYTES ? "\n" : j && !( ( j + 1 ) % 8 ) ? ",\n\t\t" : ", " ); 191 | 192 | printf( "\t},\n" ); 193 | } 194 | 195 | printf( "};\n\n\n\n\n" );*/ 196 | puts( "#endif\n\n\n" ); 197 | return 0; 198 | } -------------------------------------------------------------------------------- /c_src/blake2sp-ref.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #if defined(_OPENMP) 7 | #include 8 | #endif 9 | 10 | #include "blake2.h" 11 | #include "blake2-impl.h" 12 | 13 | #define PARALLELISM_DEGREE 8 14 | 15 | static inline int blake2sp_init_leaf( blake2s_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset ) 16 | { 17 | blake2s_param P[1]; 18 | P->digest_length = outlen; 19 | P->key_length = keylen; 20 | P->fanout = PARALLELISM_DEGREE; 21 | P->depth = 2; 22 | store32( &P->leaf_length, 0 ); 23 | store48( P->node_offset, offset ); 24 | P->node_depth = 0; 25 | P->inner_length = outlen; 26 | memset( P->salt, 0, sizeof( P->salt ) ); 27 | memset( P->personal, 0, sizeof( P->personal ) ); 28 | return blake2s_init_param( S, P ); 29 | } 30 | 31 | static inline int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t keylen ) 32 | { 33 | blake2s_param P[1]; 34 | P->digest_length = outlen; 35 | P->key_length = keylen; 36 | P->fanout = PARALLELISM_DEGREE; 37 | P->depth = 2; 38 | store32( &P->leaf_length, 0 ); 39 | store48( P->node_offset, 0ULL ); 40 | P->node_depth = 1; 41 | P->inner_length = outlen; 42 | memset( P->salt, 0, sizeof( P->salt ) ); 43 | memset( P->personal, 0, sizeof( P->personal ) ); 44 | return blake2s_init_param( S, P ); 45 | } 46 | 47 | 48 | int blake2sp_init( blake2sp_state *S, const uint8_t outlen ) 49 | { 50 | if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 51 | 52 | memset( S->buf, 0, sizeof( S->buf ) ); 53 | S->buflen = 0; 54 | 55 | if( blake2sp_init_root( S->R, outlen, 0 ) < 0 ) 56 | return -1; 57 | 58 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 59 | if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1; 60 | 61 | S->R->last_node = 1; 62 | S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 63 | return 0; 64 | } 65 | 66 | int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 67 | { 68 | if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 69 | 70 | if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; 71 | 72 | memset( S->buf, 0, sizeof( S->buf ) ); 73 | S->buflen = 0; 74 | 75 | if( blake2sp_init_root( S->R, outlen, keylen ) < 0 ) 76 | return -1; 77 | 78 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 79 | if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1; 80 | 81 | S->R->last_node = 1; 82 | S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 83 | { 84 | uint8_t block[BLAKE2S_BLOCKBYTES]; 85 | memset( block, 0, BLAKE2S_BLOCKBYTES ); 86 | memcpy( block, key, keylen ); 87 | 88 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 89 | blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES ); 90 | 91 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 92 | } 93 | return 0; 94 | } 95 | 96 | 97 | int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen ) 98 | { 99 | size_t left = S->buflen; 100 | size_t fill = sizeof( S->buf ) - left; 101 | 102 | if( left && inlen >= fill ) 103 | { 104 | memcpy( S->buf + left, in, fill ); 105 | 106 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 107 | blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); 108 | 109 | in += fill; 110 | inlen -= fill; 111 | left = 0; 112 | } 113 | 114 | #if defined(_OPENMP) 115 | #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE) 116 | #else 117 | 118 | for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ ) 119 | #endif 120 | { 121 | #if defined(_OPENMP) 122 | size_t id__ = omp_get_thread_num(); 123 | #endif 124 | uint64_t inlen__ = inlen; 125 | const uint8_t *in__ = ( const uint8_t * )in; 126 | in__ += id__ * BLAKE2S_BLOCKBYTES; 127 | 128 | while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) 129 | { 130 | blake2s_update( S->S[id__], in__, BLAKE2S_BLOCKBYTES ); 131 | in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 132 | inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 133 | } 134 | } 135 | 136 | in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ); 137 | inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 138 | 139 | if( inlen > 0 ) 140 | memcpy( S->buf + left, in, inlen ); 141 | 142 | S->buflen = left + inlen; 143 | return 0; 144 | } 145 | 146 | 147 | int blake2sp_final( blake2sp_state *S, uint8_t *out, const uint8_t outlen ) 148 | { 149 | uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; 150 | 151 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 152 | { 153 | if( S->buflen > i * BLAKE2S_BLOCKBYTES ) 154 | { 155 | size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES; 156 | 157 | if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES; 158 | 159 | blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left ); 160 | } 161 | 162 | blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES ); 163 | } 164 | 165 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 166 | blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES ); 167 | 168 | blake2s_final( S->R, out, outlen ); 169 | return 0; 170 | } 171 | 172 | 173 | int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen ) 174 | { 175 | uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; 176 | blake2s_state S[PARALLELISM_DEGREE][1]; 177 | blake2s_state FS[1]; 178 | 179 | /* Verify parameters */ 180 | if ( NULL == in ) return -1; 181 | 182 | if ( NULL == out ) return -1; 183 | 184 | if ( NULL == key ) keylen = 0; 185 | 186 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 187 | if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1; 188 | 189 | S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node 190 | 191 | if( keylen > 0 ) 192 | { 193 | uint8_t block[BLAKE2S_BLOCKBYTES]; 194 | memset( block, 0, BLAKE2S_BLOCKBYTES ); 195 | memcpy( block, key, keylen ); 196 | 197 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 198 | blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES ); 199 | 200 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 201 | } 202 | 203 | #if defined(_OPENMP) 204 | #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE) 205 | #else 206 | 207 | for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ ) 208 | #endif 209 | { 210 | #if defined(_OPENMP) 211 | size_t id__ = omp_get_thread_num(); 212 | #endif 213 | uint64_t inlen__ = inlen; 214 | const uint8_t *in__ = ( const uint8_t * )in; 215 | in__ += id__ * BLAKE2S_BLOCKBYTES; 216 | 217 | while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) 218 | { 219 | blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES ); 220 | in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 221 | inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 222 | } 223 | 224 | if( inlen__ > id__ * BLAKE2S_BLOCKBYTES ) 225 | { 226 | const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES; 227 | const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES; 228 | blake2s_update( S[id__], in__, len ); 229 | } 230 | 231 | blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES ); 232 | } 233 | 234 | if( blake2sp_init_root( FS, outlen, keylen ) < 0 ) 235 | return -1; 236 | 237 | FS->last_node = 1; 238 | 239 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 240 | blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES ); 241 | 242 | blake2s_final( FS, out, outlen ); 243 | return 0; 244 | } 245 | 246 | 247 | 248 | #if defined(BLAKE2SP_SELFTEST) 249 | #include 250 | #include "blake2-kat.h" 251 | int main( int argc, char **argv ) 252 | { 253 | uint8_t key[BLAKE2S_KEYBYTES]; 254 | uint8_t buf[KAT_LENGTH]; 255 | 256 | for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) 257 | key[i] = ( uint8_t )i; 258 | 259 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 260 | buf[i] = ( uint8_t )i; 261 | 262 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 263 | { 264 | uint8_t hash[BLAKE2S_OUTBYTES]; 265 | blake2sp( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); 266 | 267 | if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) ) 268 | { 269 | puts( "error" ); 270 | return -1; 271 | } 272 | } 273 | 274 | puts( "ok" ); 275 | return 0; 276 | } 277 | #endif 278 | 279 | 280 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /c_src/blake2bp-ref.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #if defined(_OPENMP) 8 | #include 9 | #endif 10 | 11 | #include "blake2.h" 12 | #include "blake2-impl.h" 13 | 14 | #define PARALLELISM_DEGREE 4 15 | 16 | static inline int blake2bp_init_leaf( blake2b_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset ) 17 | { 18 | blake2b_param P[1]; 19 | P->digest_length = outlen; 20 | P->key_length = keylen; 21 | P->fanout = PARALLELISM_DEGREE; 22 | P->depth = 2; 23 | store32( &P->leaf_length, 0 ); 24 | store64( &P->node_offset, offset ); 25 | P->node_depth = 0; 26 | P->inner_length = outlen; 27 | memset( P->reserved, 0, sizeof( P->reserved ) ); 28 | memset( P->salt, 0, sizeof( P->salt ) ); 29 | memset( P->personal, 0, sizeof( P->personal ) ); 30 | return blake2b_init_param( S, P ); 31 | } 32 | 33 | static inline int blake2bp_init_root( blake2b_state *S, uint8_t outlen, uint8_t keylen ) 34 | { 35 | blake2b_param P[1]; 36 | P->digest_length = outlen; 37 | P->key_length = keylen; 38 | P->fanout = PARALLELISM_DEGREE; 39 | P->depth = 2; 40 | store32( &P->leaf_length, 0 ); 41 | store64( &P->node_offset, 0 ); 42 | P->node_depth = 1; 43 | P->inner_length = outlen; 44 | memset( P->reserved, 0, sizeof( P->reserved ) ); 45 | memset( P->salt, 0, sizeof( P->salt ) ); 46 | memset( P->personal, 0, sizeof( P->personal ) ); 47 | return blake2b_init_param( S, P ); 48 | } 49 | 50 | 51 | int blake2bp_init( blake2bp_state *S, const uint8_t outlen ) 52 | { 53 | if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; 54 | 55 | memset( S->buf, 0, sizeof( S->buf ) ); 56 | S->buflen = 0; 57 | 58 | if( blake2bp_init_root( S->R, outlen, 0 ) < 0 ) 59 | return -1; 60 | 61 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 62 | if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1; 63 | 64 | S->R->last_node = 1; 65 | S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 66 | return 0; 67 | } 68 | 69 | int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 70 | { 71 | if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; 72 | 73 | if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 74 | 75 | memset( S->buf, 0, sizeof( S->buf ) ); 76 | S->buflen = 0; 77 | 78 | if( blake2bp_init_root( S->R, outlen, keylen ) < 0 ) 79 | return -1; 80 | 81 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 82 | if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1; 83 | 84 | S->R->last_node = 1; 85 | S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 86 | { 87 | uint8_t block[BLAKE2B_BLOCKBYTES]; 88 | memset( block, 0, BLAKE2B_BLOCKBYTES ); 89 | memcpy( block, key, keylen ); 90 | 91 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 92 | blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES ); 93 | 94 | secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 95 | } 96 | return 0; 97 | } 98 | 99 | 100 | int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen ) 101 | { 102 | size_t left = S->buflen; 103 | size_t fill = sizeof( S->buf ) - left; 104 | 105 | if( left && inlen >= fill ) 106 | { 107 | memcpy( S->buf + left, in, fill ); 108 | 109 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 110 | blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); 111 | 112 | in += fill; 113 | inlen -= fill; 114 | left = 0; 115 | } 116 | 117 | #if defined(_OPENMP) 118 | #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE) 119 | #else 120 | 121 | for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ ) 122 | #endif 123 | { 124 | #if defined(_OPENMP) 125 | size_t id__ = omp_get_thread_num(); 126 | #endif 127 | uint64_t inlen__ = inlen; 128 | const uint8_t *in__ = ( const uint8_t * )in; 129 | in__ += id__ * BLAKE2B_BLOCKBYTES; 130 | 131 | while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ) 132 | { 133 | blake2b_update( S->S[id__], in__, BLAKE2B_BLOCKBYTES ); 134 | in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES; 135 | inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES; 136 | } 137 | } 138 | 139 | in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ); 140 | inlen %= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES; 141 | 142 | if( inlen > 0 ) 143 | memcpy( S->buf + left, in, inlen ); 144 | 145 | S->buflen = left + inlen; 146 | return 0; 147 | } 148 | 149 | int blake2bp_final( blake2bp_state *S, uint8_t *out, const uint8_t outlen ) 150 | { 151 | uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES]; 152 | 153 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 154 | { 155 | if( S->buflen > i * BLAKE2B_BLOCKBYTES ) 156 | { 157 | size_t left = S->buflen - i * BLAKE2B_BLOCKBYTES; 158 | 159 | if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES; 160 | 161 | blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left ); 162 | } 163 | 164 | blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES ); 165 | } 166 | 167 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 168 | blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES ); 169 | 170 | blake2b_final( S->R, out, outlen ); 171 | return 0; 172 | } 173 | 174 | int blake2bp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen ) 175 | { 176 | uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES]; 177 | blake2b_state S[PARALLELISM_DEGREE][1]; 178 | blake2b_state FS[1]; 179 | 180 | /* Verify parameters */ 181 | if ( NULL == in ) return -1; 182 | 183 | if ( NULL == out ) return -1; 184 | 185 | if ( NULL == key ) keylen = 0; 186 | 187 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 188 | if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1; 189 | 190 | S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node 191 | 192 | if( keylen > 0 ) 193 | { 194 | uint8_t block[BLAKE2B_BLOCKBYTES]; 195 | memset( block, 0, BLAKE2B_BLOCKBYTES ); 196 | memcpy( block, key, keylen ); 197 | 198 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 199 | blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES ); 200 | 201 | secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 202 | } 203 | 204 | #if defined(_OPENMP) 205 | #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE) 206 | #else 207 | 208 | for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ ) 209 | #endif 210 | { 211 | #if defined(_OPENMP) 212 | size_t id__ = omp_get_thread_num(); 213 | #endif 214 | uint64_t inlen__ = inlen; 215 | const uint8_t *in__ = ( const uint8_t * )in; 216 | in__ += id__ * BLAKE2B_BLOCKBYTES; 217 | 218 | while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ) 219 | { 220 | blake2b_update( S[id__], in__, BLAKE2B_BLOCKBYTES ); 221 | in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES; 222 | inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES; 223 | } 224 | 225 | if( inlen__ > id__ * BLAKE2B_BLOCKBYTES ) 226 | { 227 | const size_t left = inlen__ - id__ * BLAKE2B_BLOCKBYTES; 228 | const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES; 229 | blake2b_update( S[id__], in__, len ); 230 | } 231 | 232 | blake2b_final( S[id__], hash[id__], BLAKE2B_OUTBYTES ); 233 | } 234 | 235 | if( blake2bp_init_root( FS, outlen, keylen ) < 0 ) 236 | return -1; 237 | 238 | FS->last_node = 1; // Mark as last node 239 | 240 | for( size_t i = 0; i < PARALLELISM_DEGREE; ++i ) 241 | blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES ); 242 | 243 | blake2b_final( FS, out, outlen ); 244 | return 0; 245 | } 246 | 247 | #if defined(BLAKE2BP_SELFTEST) 248 | #include 249 | #include "blake2-kat.h" 250 | int main( int argc, char **argv ) 251 | { 252 | uint8_t key[BLAKE2B_KEYBYTES]; 253 | uint8_t buf[KAT_LENGTH]; 254 | 255 | for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i ) 256 | key[i] = ( uint8_t )i; 257 | 258 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 259 | buf[i] = ( uint8_t )i; 260 | 261 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 262 | { 263 | uint8_t hash[BLAKE2B_OUTBYTES]; 264 | blake2bp( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 265 | 266 | if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 267 | { 268 | puts( "error" ); 269 | return -1; 270 | } 271 | } 272 | 273 | puts( "ok" ); 274 | return 0; 275 | } 276 | #endif 277 | -------------------------------------------------------------------------------- /c_src/blake2s-ref.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "blake2.h" 7 | #include "blake2-impl.h" 8 | 9 | static const uint32_t blake2s_IV[8] = 10 | { 11 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 12 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 13 | }; 14 | 15 | static const uint8_t blake2s_sigma[10][16] = 16 | { 17 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 18 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 19 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 20 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 21 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 22 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 23 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 24 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 25 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 26 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 27 | }; 28 | 29 | static inline int blake2s_set_lastnode( blake2s_state *S ) 30 | { 31 | S->f[1] = ~0U; 32 | return 0; 33 | } 34 | 35 | static inline int blake2s_clear_lastnode( blake2s_state *S ) 36 | { 37 | S->f[1] = 0U; 38 | return 0; 39 | } 40 | 41 | /* Some helper functions, not necessarily useful */ 42 | static inline int blake2s_set_lastblock( blake2s_state *S ) 43 | { 44 | if( S->last_node ) blake2s_set_lastnode( S ); 45 | 46 | S->f[0] = ~0U; 47 | return 0; 48 | } 49 | 50 | static inline int blake2s_clear_lastblock( blake2s_state *S ) 51 | { 52 | if( S->last_node ) blake2s_clear_lastnode( S ); 53 | 54 | S->f[0] = 0U; 55 | return 0; 56 | } 57 | 58 | static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) 59 | { 60 | S->t[0] += inc; 61 | S->t[1] += ( S->t[0] < inc ); 62 | return 0; 63 | } 64 | 65 | // Parameter-related functions 66 | static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) 67 | { 68 | P->digest_length = digest_length; 69 | return 0; 70 | } 71 | 72 | static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) 73 | { 74 | P->fanout = fanout; 75 | return 0; 76 | } 77 | 78 | static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) 79 | { 80 | P->depth = depth; 81 | return 0; 82 | } 83 | 84 | static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) 85 | { 86 | store32( &P->leaf_length, leaf_length ); 87 | return 0; 88 | } 89 | 90 | static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) 91 | { 92 | store48( P->node_offset, node_offset ); 93 | return 0; 94 | } 95 | 96 | static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) 97 | { 98 | P->node_depth = node_depth; 99 | return 0; 100 | } 101 | 102 | static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) 103 | { 104 | P->inner_length = inner_length; 105 | return 0; 106 | } 107 | 108 | static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) 109 | { 110 | memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); 111 | return 0; 112 | } 113 | 114 | static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) 115 | { 116 | memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); 117 | return 0; 118 | } 119 | 120 | static inline int blake2s_init0( blake2s_state *S ) 121 | { 122 | memset( S, 0, sizeof( blake2s_state ) ); 123 | 124 | for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; 125 | 126 | return 0; 127 | } 128 | 129 | /* init2 xors IV with input parameter block */ 130 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) 131 | { 132 | blake2s_init0( S ); 133 | uint32_t *p = ( uint32_t * )( P ); 134 | 135 | /* IV XOR ParamBlock */ 136 | for( size_t i = 0; i < 8; ++i ) 137 | S->h[i] ^= load32( &p[i] ); 138 | 139 | return 0; 140 | } 141 | 142 | 143 | // Sequential blake2s initialization 144 | int blake2s_init( blake2s_state *S, const uint8_t outlen ) 145 | { 146 | blake2s_param P[1]; 147 | 148 | /* Move interval verification here? */ 149 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 150 | 151 | P->digest_length = outlen; 152 | P->key_length = 0; 153 | P->fanout = 1; 154 | P->depth = 1; 155 | store32( &P->leaf_length, 0 ); 156 | store48( &P->node_offset, 0 ); 157 | P->node_depth = 0; 158 | P->inner_length = 0; 159 | // memset(P->reserved, 0, sizeof(P->reserved) ); 160 | memset( P->salt, 0, sizeof( P->salt ) ); 161 | memset( P->personal, 0, sizeof( P->personal ) ); 162 | return blake2s_init_param( S, P ); 163 | } 164 | 165 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 166 | { 167 | blake2s_param P[1]; 168 | 169 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 170 | 171 | if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; 172 | 173 | P->digest_length = outlen; 174 | P->key_length = keylen; 175 | P->fanout = 1; 176 | P->depth = 1; 177 | store32( &P->leaf_length, 0 ); 178 | store48( &P->node_offset, 0 ); 179 | P->node_depth = 0; 180 | P->inner_length = 0; 181 | // memset(P->reserved, 0, sizeof(P->reserved) ); 182 | memset( P->salt, 0, sizeof( P->salt ) ); 183 | memset( P->personal, 0, sizeof( P->personal ) ); 184 | 185 | if( blake2s_init_param( S, P ) < 0 ) return -1; 186 | 187 | { 188 | uint8_t block[BLAKE2S_BLOCKBYTES]; 189 | memset( block, 0, BLAKE2S_BLOCKBYTES ); 190 | memcpy( block, key, keylen ); 191 | blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); 192 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 193 | } 194 | return 0; 195 | } 196 | 197 | static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) 198 | { 199 | uint32_t m[16]; 200 | uint32_t v[16]; 201 | 202 | for( size_t i = 0; i < 16; ++i ) 203 | m[i] = load32( block + i * sizeof( m[i] ) ); 204 | 205 | for( size_t i = 0; i < 8; ++i ) 206 | v[i] = S->h[i]; 207 | 208 | v[ 8] = blake2s_IV[0]; 209 | v[ 9] = blake2s_IV[1]; 210 | v[10] = blake2s_IV[2]; 211 | v[11] = blake2s_IV[3]; 212 | v[12] = S->t[0] ^ blake2s_IV[4]; 213 | v[13] = S->t[1] ^ blake2s_IV[5]; 214 | v[14] = S->f[0] ^ blake2s_IV[6]; 215 | v[15] = S->f[1] ^ blake2s_IV[7]; 216 | #define G(r,i,a,b,c,d) \ 217 | do { \ 218 | a = a + b + m[blake2s_sigma[r][2*i+0]]; \ 219 | d = rotr32(d ^ a, 16); \ 220 | c = c + d; \ 221 | b = rotr32(b ^ c, 12); \ 222 | a = a + b + m[blake2s_sigma[r][2*i+1]]; \ 223 | d = rotr32(d ^ a, 8); \ 224 | c = c + d; \ 225 | b = rotr32(b ^ c, 7); \ 226 | } while(0) 227 | #define ROUND(r) \ 228 | do { \ 229 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 230 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 231 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 232 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 233 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 234 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 235 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 236 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 237 | } while(0) 238 | ROUND( 0 ); 239 | ROUND( 1 ); 240 | ROUND( 2 ); 241 | ROUND( 3 ); 242 | ROUND( 4 ); 243 | ROUND( 5 ); 244 | ROUND( 6 ); 245 | ROUND( 7 ); 246 | ROUND( 8 ); 247 | ROUND( 9 ); 248 | 249 | for( size_t i = 0; i < 8; ++i ) 250 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 251 | 252 | #undef G 253 | #undef ROUND 254 | return 0; 255 | } 256 | 257 | 258 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ) 259 | { 260 | while( inlen > 0 ) 261 | { 262 | size_t left = S->buflen; 263 | size_t fill = 2 * BLAKE2S_BLOCKBYTES - left; 264 | 265 | if( inlen > fill ) 266 | { 267 | memcpy( S->buf + left, in, fill ); // Fill buffer 268 | S->buflen += fill; 269 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 270 | blake2s_compress( S, S->buf ); // Compress 271 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left 272 | S->buflen -= BLAKE2S_BLOCKBYTES; 273 | in += fill; 274 | inlen -= fill; 275 | } 276 | else // inlen <= fill 277 | { 278 | memcpy( S->buf + left, in, inlen ); 279 | S->buflen += inlen; // Be lazy, do not compress 280 | in += inlen; 281 | inlen -= inlen; 282 | } 283 | } 284 | 285 | return 0; 286 | } 287 | 288 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ) 289 | { 290 | uint8_t buffer[BLAKE2S_OUTBYTES]; 291 | 292 | if( S->buflen > BLAKE2S_BLOCKBYTES ) 293 | { 294 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 295 | blake2s_compress( S, S->buf ); 296 | S->buflen -= BLAKE2S_BLOCKBYTES; 297 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); 298 | } 299 | 300 | blake2s_increment_counter( S, ( uint32_t )S->buflen ); 301 | blake2s_set_lastblock( S ); 302 | memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ 303 | blake2s_compress( S, S->buf ); 304 | 305 | for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 306 | store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 307 | 308 | memcpy( out, buffer, outlen ); 309 | return 0; 310 | } 311 | 312 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 313 | { 314 | blake2s_state S[1]; 315 | 316 | /* Verify parameters */ 317 | if ( NULL == in ) return -1; 318 | 319 | if ( NULL == out ) return -1; 320 | 321 | if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */ 322 | 323 | if( keylen > 0 ) 324 | { 325 | if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; 326 | } 327 | else 328 | { 329 | if( blake2s_init( S, outlen ) < 0 ) return -1; 330 | } 331 | 332 | blake2s_update( S, ( uint8_t * )in, inlen ); 333 | blake2s_final( S, out, outlen ); 334 | return 0; 335 | } 336 | 337 | #if defined(BLAKE2S_SELFTEST) 338 | #include 339 | #include "blake2-kat.h" 340 | int main( int argc, char **argv ) 341 | { 342 | uint8_t key[BLAKE2S_KEYBYTES]; 343 | uint8_t buf[KAT_LENGTH]; 344 | 345 | for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) 346 | key[i] = ( uint8_t )i; 347 | 348 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 349 | buf[i] = ( uint8_t )i; 350 | 351 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 352 | { 353 | uint8_t hash[BLAKE2S_OUTBYTES]; 354 | blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); 355 | 356 | if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) 357 | { 358 | puts( "error" ); 359 | return -1; 360 | } 361 | } 362 | 363 | puts( "ok" ); 364 | return 0; 365 | } 366 | #endif 367 | 368 | 369 | -------------------------------------------------------------------------------- /c_src/blake2b-ref.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "blake2.h" 7 | #include "blake2-impl.h" 8 | 9 | static const uint64_t blake2b_IV[8] = 10 | { 11 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 12 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 13 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 14 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 15 | }; 16 | 17 | static const uint8_t blake2b_sigma[12][16] = 18 | { 19 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 20 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 21 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 22 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 23 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 24 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 25 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 26 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 27 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 28 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 29 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 30 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 31 | }; 32 | 33 | 34 | static inline int blake2b_set_lastnode( blake2b_state *S ) 35 | { 36 | S->f[1] = ~0ULL; 37 | return 0; 38 | } 39 | 40 | static inline int blake2b_clear_lastnode( blake2b_state *S ) 41 | { 42 | S->f[1] = 0ULL; 43 | return 0; 44 | } 45 | 46 | /* Some helper functions, not necessarily useful */ 47 | static inline int blake2b_set_lastblock( blake2b_state *S ) 48 | { 49 | if( S->last_node ) blake2b_set_lastnode( S ); 50 | 51 | S->f[0] = ~0ULL; 52 | return 0; 53 | } 54 | 55 | static inline int blake2b_clear_lastblock( blake2b_state *S ) 56 | { 57 | if( S->last_node ) blake2b_clear_lastnode( S ); 58 | 59 | S->f[0] = 0ULL; 60 | return 0; 61 | } 62 | 63 | static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) 64 | { 65 | S->t[0] += inc; 66 | S->t[1] += ( S->t[0] < inc ); 67 | return 0; 68 | } 69 | 70 | 71 | 72 | // Parameter-related functions 73 | static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length ) 74 | { 75 | P->digest_length = digest_length; 76 | return 0; 77 | } 78 | 79 | static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout ) 80 | { 81 | P->fanout = fanout; 82 | return 0; 83 | } 84 | 85 | static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth ) 86 | { 87 | P->depth = depth; 88 | return 0; 89 | } 90 | 91 | static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length ) 92 | { 93 | store32( &P->leaf_length, leaf_length ); 94 | return 0; 95 | } 96 | 97 | static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset ) 98 | { 99 | store64( &P->node_offset, node_offset ); 100 | return 0; 101 | } 102 | 103 | static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth ) 104 | { 105 | P->node_depth = node_depth; 106 | return 0; 107 | } 108 | 109 | static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length ) 110 | { 111 | P->inner_length = inner_length; 112 | return 0; 113 | } 114 | 115 | static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] ) 116 | { 117 | memcpy( P->salt, salt, BLAKE2B_SALTBYTES ); 118 | return 0; 119 | } 120 | 121 | static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] ) 122 | { 123 | memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES ); 124 | return 0; 125 | } 126 | 127 | static inline int blake2b_init0( blake2b_state *S ) 128 | { 129 | memset( S, 0, sizeof( blake2b_state ) ); 130 | 131 | for( int i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 132 | 133 | return 0; 134 | } 135 | 136 | /* init xors IV with input parameter block */ 137 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 138 | { 139 | blake2b_init0( S ); 140 | uint8_t *p = ( uint8_t * )( P ); 141 | 142 | /* IV XOR ParamBlock */ 143 | for( size_t i = 0; i < 8; ++i ) 144 | S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 145 | 146 | return 0; 147 | } 148 | 149 | 150 | 151 | int blake2b_init( blake2b_state *S, const uint8_t outlen ) 152 | { 153 | blake2b_param P[1]; 154 | 155 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 156 | 157 | P->digest_length = outlen; 158 | P->key_length = 0; 159 | P->fanout = 1; 160 | P->depth = 1; 161 | store32( &P->leaf_length, 0 ); 162 | store64( &P->node_offset, 0 ); 163 | P->node_depth = 0; 164 | P->inner_length = 0; 165 | memset( P->reserved, 0, sizeof( P->reserved ) ); 166 | memset( P->salt, 0, sizeof( P->salt ) ); 167 | memset( P->personal, 0, sizeof( P->personal ) ); 168 | return blake2b_init_param( S, P ); 169 | } 170 | 171 | 172 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 173 | { 174 | blake2b_param P[1]; 175 | 176 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 177 | 178 | if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 179 | 180 | P->digest_length = outlen; 181 | P->key_length = keylen; 182 | P->fanout = 1; 183 | P->depth = 1; 184 | store32( &P->leaf_length, 0 ); 185 | store64( &P->node_offset, 0 ); 186 | P->node_depth = 0; 187 | P->inner_length = 0; 188 | memset( P->reserved, 0, sizeof( P->reserved ) ); 189 | memset( P->salt, 0, sizeof( P->salt ) ); 190 | memset( P->personal, 0, sizeof( P->personal ) ); 191 | 192 | if( blake2b_init_param( S, P ) < 0 ) return -1; 193 | 194 | { 195 | uint8_t block[BLAKE2B_BLOCKBYTES]; 196 | memset( block, 0, BLAKE2B_BLOCKBYTES ); 197 | memcpy( block, key, keylen ); 198 | blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 199 | secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 200 | } 201 | return 0; 202 | } 203 | 204 | static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) 205 | { 206 | uint64_t m[16]; 207 | uint64_t v[16]; 208 | int i; 209 | 210 | for( i = 0; i < 16; ++i ) 211 | m[i] = load64( block + i * sizeof( m[i] ) ); 212 | 213 | for( i = 0; i < 8; ++i ) 214 | v[i] = S->h[i]; 215 | 216 | v[ 8] = blake2b_IV[0]; 217 | v[ 9] = blake2b_IV[1]; 218 | v[10] = blake2b_IV[2]; 219 | v[11] = blake2b_IV[3]; 220 | v[12] = S->t[0] ^ blake2b_IV[4]; 221 | v[13] = S->t[1] ^ blake2b_IV[5]; 222 | v[14] = S->f[0] ^ blake2b_IV[6]; 223 | v[15] = S->f[1] ^ blake2b_IV[7]; 224 | #define G(r,i,a,b,c,d) \ 225 | do { \ 226 | a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 227 | d = rotr64(d ^ a, 32); \ 228 | c = c + d; \ 229 | b = rotr64(b ^ c, 24); \ 230 | a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 231 | d = rotr64(d ^ a, 16); \ 232 | c = c + d; \ 233 | b = rotr64(b ^ c, 63); \ 234 | } while(0) 235 | #define ROUND(r) \ 236 | do { \ 237 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 238 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 239 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 240 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 241 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 242 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 243 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 244 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 245 | } while(0) 246 | ROUND( 0 ); 247 | ROUND( 1 ); 248 | ROUND( 2 ); 249 | ROUND( 3 ); 250 | ROUND( 4 ); 251 | ROUND( 5 ); 252 | ROUND( 6 ); 253 | ROUND( 7 ); 254 | ROUND( 8 ); 255 | ROUND( 9 ); 256 | ROUND( 10 ); 257 | ROUND( 11 ); 258 | 259 | for( i = 0; i < 8; ++i ) 260 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 261 | 262 | #undef G 263 | #undef ROUND 264 | return 0; 265 | } 266 | 267 | /* inlen now in bytes */ 268 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ) 269 | { 270 | while( inlen > 0 ) 271 | { 272 | size_t left = S->buflen; 273 | size_t fill = 2 * BLAKE2B_BLOCKBYTES - left; 274 | 275 | if( inlen > fill ) 276 | { 277 | memcpy( S->buf + left, in, fill ); // Fill buffer 278 | S->buflen += fill; 279 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 280 | blake2b_compress( S, S->buf ); // Compress 281 | memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); // Shift buffer left 282 | S->buflen -= BLAKE2B_BLOCKBYTES; 283 | in += fill; 284 | inlen -= fill; 285 | } 286 | else // inlen <= fill 287 | { 288 | memcpy( S->buf + left, in, inlen ); 289 | S->buflen += inlen; // Be lazy, do not compress 290 | in += inlen; 291 | inlen -= inlen; 292 | } 293 | } 294 | 295 | return 0; 296 | } 297 | 298 | /* Is this correct? */ 299 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ) 300 | { 301 | uint8_t buffer[BLAKE2B_OUTBYTES]; 302 | 303 | if( S->buflen > BLAKE2B_BLOCKBYTES ) 304 | { 305 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 306 | blake2b_compress( S, S->buf ); 307 | S->buflen -= BLAKE2B_BLOCKBYTES; 308 | memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen ); 309 | } 310 | 311 | blake2b_increment_counter( S, S->buflen ); 312 | blake2b_set_lastblock( S ); 313 | memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ 314 | blake2b_compress( S, S->buf ); 315 | 316 | for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 317 | store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 318 | 319 | memcpy( out, buffer, outlen ); 320 | return 0; 321 | } 322 | 323 | /* inlen, at least, should be uint64_t. Others can be size_t. */ 324 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 325 | { 326 | blake2b_state S[1]; 327 | 328 | /* Verify parameters */ 329 | if ( NULL == in ) return -1; 330 | 331 | if ( NULL == out ) return -1; 332 | 333 | if( NULL == key ) keylen = 0; 334 | 335 | if( keylen > 0 ) 336 | { 337 | if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 338 | } 339 | else 340 | { 341 | if( blake2b_init( S, outlen ) < 0 ) return -1; 342 | } 343 | 344 | blake2b_update( S, ( uint8_t * )in, inlen ); 345 | blake2b_final( S, out, outlen ); 346 | return 0; 347 | } 348 | 349 | #if defined(BLAKE2B_SELFTEST) 350 | #include 351 | #include "blake2-kat.h" 352 | int main( int argc, char **argv ) 353 | { 354 | uint8_t key[BLAKE2B_KEYBYTES]; 355 | uint8_t buf[KAT_LENGTH]; 356 | 357 | for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i ) 358 | key[i] = ( uint8_t )i; 359 | 360 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 361 | buf[i] = ( uint8_t )i; 362 | 363 | for( size_t i = 0; i < KAT_LENGTH; ++i ) 364 | { 365 | uint8_t hash[BLAKE2B_OUTBYTES]; 366 | blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 367 | 368 | if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 369 | { 370 | puts( "error" ); 371 | return -1; 372 | } 373 | } 374 | 375 | puts( "ok" ); 376 | return 0; 377 | } 378 | #endif 379 | 380 | --------------------------------------------------------------------------------