diff options
Diffstat (limited to 'ref/blake2xs-ref.c')
-rw-r--r-- | ref/blake2xs-ref.c | 219 |
1 files changed, 120 insertions, 99 deletions
diff --git a/ref/blake2xs-ref.c b/ref/blake2xs-ref.c index 5c6145e..bd6ad2b 100644 --- a/ref/blake2xs-ref.c +++ b/ref/blake2xs-ref.c @@ -5,141 +5,162 @@ #include "blake2.h" #include "blake2-impl.h" +typedef struct blake2xs_state__ { + blake2s_state S[1]; + blake2s_param P[1]; +} blake2xs_state; + -int blake2xs_init( blake2s_state *S, const uint16_t outlen, const void *key, const uint8_t keylen) +int blake2xs_init( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ) { - blake2s_param P[1]; + if ( outlen == 0 || outlen > 0xFFFFUL ) { + return -1; + } - if ( !outlen ) return -1; - - P->digest_length = BLAKE2S_OUTBYTES; - P->key_length = keylen; - P->fanout = 1; - P->depth = 1; - store32( &P->leaf_length, 0 ); - store32( &P->node_offset, 0 ); - store16( &P->xof_length, outlen ); - P->node_depth = 0; - P->inner_length = 0; - memset( P->salt, 0, sizeof( P->salt ) ); - memset( P->personal, 0, sizeof( P->personal ) ); - - if( blake2s_init_param( S, P ) < 0 ) return -1; - - if (keylen) - { - if ( !key || keylen > BLAKE2S_KEYBYTES ) return -1; - uint8_t block[BLAKE2S_BLOCKBYTES]; - memset( block, 0, BLAKE2S_BLOCKBYTES ); - memcpy( block, key, keylen ); - blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); - secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); - } + if (key == NULL || keylen > BLAKE2S_KEYBYTES) { + return -1; + } + + /* Initialize parameter block */ + S->P->digest_length = BLAKE2S_OUTBYTES; + S->P->key_length = keylen; + S->P->fanout = 1; + S->P->depth = 1; + store32( &S->P->leaf_length, 0 ); + store32( &S->P->node_offset, 0 ); + store16( &S->P->xof_length, outlen ); + S->P->node_depth = 0; + S->P->inner_length = 0; + memset( S->P->salt, 0, sizeof( S->P->salt ) ); + memset( S->P->personal, 0, sizeof( S->P->personal ) ); + + if( blake2s_init_param( S->S, S->P ) < 0 ) { + return -1; + } + + if (keylen > 0) { + uint8_t block[BLAKE2S_BLOCKBYTES]; + memset(block, 0, BLAKE2S_BLOCKBYTES); + memcpy(block, key, keylen); + blake2s_update(S->S, block, BLAKE2S_BLOCKBYTES); + secure_zero_memory(block, BLAKE2S_BLOCKBYTES); + } return 0; } +int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ) { + return blake2s_update( S->S, in, inlen ); +} -int blake2xs_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ) +int blake2xs_final(blake2xs_state *S, void *out, size_t outlen) { - if ( !in ) return -1; - - return blake2s_update( S, in, inlen ); + blake2s_state C[1]; + blake2s_param P[1]; + uint16_t xof_length = load16(&S->P->xof_length); + uint8_t root[BLAKE2S_BLOCKBYTES]; + size_t i; -} + if (out == NULL) { + return -1; + } -int blake2xs_final( blake2s_state *S, uint8_t *out, const uint16_t outlen ) { - - blake2s_state C[1]; - blake2s_param P[1]; - int i; - uint16_t last_index = outlen/BLAKE2S_OUTBYTES; - uint8_t root[BLAKE2S_BLOCKBYTES]; - - if ( !out ) return 1; - - /* Finalize the root hash */ - if (blake2s_final( S, root, BLAKE2S_OUTBYTES ) < 0 ) - return -1; - - /* Set common block structure values */ - P->digest_length = BLAKE2S_OUTBYTES; - P->key_length = 0; - P->fanout = 0; - P->depth = 0; - store32( &P->leaf_length, BLAKE2S_OUTBYTES ); - store16( &P->xof_length, outlen ); - P->inner_length = 0; - P->node_depth = 0; - memset( P->salt, 0, sizeof( P->salt ) ); - memset( P->personal, 0, sizeof( P->personal ) ); - - for( i = 0; i < last_index; ++ i ) { - /* Initialize state */ - store32( &P->node_offset, i ); - if( blake2s_init_param( C, P ) < 0 ) return -1; - /* Process key if needed */ - blake2s_update( C, root, BLAKE2S_OUTBYTES); - blake2s_final( C, out + i*BLAKE2S_OUTBYTES, BLAKE2S_OUTBYTES ); + /* outlen must match the output size defined in xof_length, */ + /* unless it was -1, in which case anything goes except 0. */ + if(xof_length == 0xFFFFUL) { + if(outlen == 0) { + return -1; + } + } else { + if(outlen != xof_length) { + return -1; } - /* Last instance */ - store32( &P->node_offset, last_index); - P->digest_length = outlen % BLAKE2S_OUTBYTES; - if( blake2s_init_param( C, P ) < 0 ) return -1; - blake2s_update( C, root, BLAKE2S_OUTBYTES); - blake2s_final( C, out + last_index*BLAKE2S_OUTBYTES, outlen % BLAKE2S_OUTBYTES ); - - return 0; + } + + /* Finalize the root hash */ + if (blake2s_final(S->S, root, BLAKE2S_OUTBYTES) < 0) { + return -1; + } + + /* Set common block structure values */ + /* Copy values from parent instance, and only change the ones below */ + memcpy(P, S->P, sizeof(blake2s_param)); + P->fanout = 0; + P->depth = 0; + store32(&P->leaf_length, BLAKE2S_OUTBYTES); + P->inner_length = BLAKE2S_OUTBYTES; + P->node_depth = 0; + + for (i = 0; outlen > 0; ++i) { + const size_t block_size = (outlen < BLAKE2S_OUTBYTES) ? outlen : BLAKE2S_OUTBYTES; + /* Initialize state */ + store32(&P->node_offset, i); + blake2s_init_param(C, P); + /* Process key if needed */ + blake2s_update(C, root, BLAKE2S_OUTBYTES); + blake2s_final(C, (uint8_t *)out + i * BLAKE2S_OUTBYTES, BLAKE2S_OUTBYTES); + outlen -= block_size; + } + secure_zero_memory(root, sizeof(root)); + secure_zero_memory(P, sizeof(P)); + secure_zero_memory(C, sizeof(C)); + /* Put blake2xs in an invalid state? cf. blake2s_is_lastblock */ + return 0; } -int blake2xs( uint8_t *out, const void *in, const void *key, const -uint16_t outlen, const uint64_t inlen, const uint8_t keylen ) +int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen) { - blake2s_state S[1]; - - /* Verify parameters */ - if ( NULL == in && inlen > 0 ) return -1; + blake2xs_state S[1]; - if ( NULL == out ) return -1; + /* Verify parameters */ + if (NULL == in && inlen > 0) + return -1; - if ( NULL == key && keylen > 0) return -1; + if (NULL == out) + return -1; - if( keylen > BLAKE2S_KEYBYTES ) return -1; + if (NULL == key && keylen > 0) + return -1; - if( !outlen ) return -1; + if (keylen > BLAKE2S_KEYBYTES) + return -1; - /* Initialize the root block structure */ - if ( blake2xs_init( S, outlen, key, keylen ) < 0 ) { - return -1; - } + if (outlen == 0) + return -1; - /* Compute the root of the tree */ - if ( blake2xs_update( S, ( const uint8_t * )in, inlen ) < 0 ) - return -1; + /* Initialize the root block structure */ + if (blake2xs_init(S, outlen, key, keylen) < 0) { + return -1; + } - /* Compute the final hash using the counter construction */ - blake2xs_final( S, out, outlen ); + /* Compute the root of the tree */ + if (blake2xs_update(S, in, inlen) < 0) { + return -1; + } - return 0; + /* Compute the final hash using the counter construction */ + return blake2xs_final(S, out, outlen); } #if defined(BLAKE2XS_SELFTEST) #include <string.h> #include "blake2-kat.h" -int main( int argc, char **argv ) +int main( void ) { uint8_t key[BLAKE2S_KEYBYTES]; uint8_t buf[BLAKE2_KAT_LENGTH]; - for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) + for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) { key[i] = ( uint8_t )i; + } - for( size_t i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + for( size_t i = 0; i < BLAKE2_KAT_LENGTH; ++i ) { buf[i] = ( uint8_t )i; + } - for( size_t i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + for( size_t i = 1; i < BLAKE2_KAT_LENGTH; ++i ) { - uint8_t hash[BLAKE2_KAT_LENGTH]; - blake2xs( hash, buf, key, i, BLAKE2_KAT_LENGTH, BLAKE2S_KEYBYTES ); + uint8_t hash[BLAKE2_KAT_LENGTH] = {0}; + blake2xs( hash, i, buf, BLAKE2_KAT_LENGTH, key, BLAKE2S_KEYBYTES ); for( size_t j = 0; j < i; ++j ) { printf("%02x", hash[j]); |