1
1
mirror of https://github.com/BLAKE2/BLAKE2 synced 2024-11-08 14:59:19 +01:00

Implemented keyed-mode for BLAKE2b

Note, that OpenSSL doesn't seem to be using standard HMAC *or* keyed mode.
As such, my attempt to bring my implementation to agree with theirs dies
with their inibility to follow standards. If I'm incorrect in my assessment
I'd appreciate someone sending a pull-request with the fixed version. Perhaps
OpenSSL combines HMAC with keyed mode?
This commit is contained in:
Alex 2020-09-07 22:18:22 +00:00
parent 750880af71
commit 8bc9e85048

@ -274,6 +274,57 @@ int blake2b_stream_hmac( unsigned char *key, FILE *stream, void *resstream, size
blake2b_update( S, buffer, buffer_length );
}
final_process:;
if( sum > 0 ) blake2b_update( S, buffer, sum );
blake2b_final( S, resstream, outbytes );
ret = 0;
cleanup_buffer:
free( buffer );
return ret;
}
int blake2b_stream_keym( unsigned char *key, size_t key_length, FILE *stream, void *resstream, size_t outbytes )
{
int ret = -1;
size_t sum, n;
blake2b_state S[1];
static const size_t buffer_length = 32768;
uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
size_t i;
size_t j;
if( !buffer ) return -1;
blake2b_init_key( S, outbytes, key, key_length );
while( 1 )
{
sum = 0;
while( 1 )
{
n = fread( buffer + sum, 1, buffer_length - sum, stream );
sum += n;
if( buffer_length == sum )
break;
if( 0 == n )
{
if( ferror( stream ) )
goto cleanup_buffer;
goto final_process;
}
if( feof( stream ) )
goto final_process;
}
blake2b_update( S, buffer, buffer_length );
}
final_process:;
if( sum > 0 ) blake2b_update( S, buffer, sum );
@ -349,12 +400,20 @@ static void usage( char **argv, int errcode )
fprintf( out, "\n" );
fprintf( out, "With no FILE, or when FILE is -, read standard input.\n" );
fprintf( out, "\n" );
fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n"
" [blake2b|blake2s|blake2bp|blake2sp]\n" );
fprintf( out, " -h <key> hash in HMAC mode\n"
" if <key> is '-' stdin will be used (only applies to blake2b)\n" );
fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n"
" the selected algorithm and must be a multiple of 8\n" );
fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n" );
fprintf( out, " [blake2b|blake2s|blake2bp|blake2sp]\n" );
fprintf( out, " -h <key> hash in HMAC mode\n" );
fprintf( out, " if <key> is '-' stdin will be used (only applies to blake2b)\n" );
fprintf( out, " -k <key> uses keyed mode (as opposed to HMAC)\n" );
fprintf( out, " I include separated this because I don't like HMAC not being real HMAC\n" );
fprintf( out, " in OpenSSL's implementation of BLAKE2b-HMAC : they should change the\n" );
fprintf( out, " name of the option if they're not gonna use real HMAC!\n" );
fprintf( out, " >> note that keyed mode and HMAC mode are different, since BLAKE\n" );
fprintf( out, " >> is made of a construction that is secure with prefixed-key MACs\n" );
fprintf( out, " >> I included HMAC mode because I like conforming to specs and I\n" );
fprintf( out, " >> refuse to use a non-HMAC keyed mode and call it HMAC\n" );
fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n" );
fprintf( out, " the selected algorithm and must be a multiple of 8\n" );
fprintf( out, " --tag create a BSD-style checksum\n" );
fprintf( out, " --help display this help and exit\n" );
exit( errcode );
@ -371,6 +430,7 @@ int main( int argc, char **argv )
unsigned char hash2[BLAKE2B_OUTBYTES] = {0};
unsigned char hmac_key[HMAC_MAX_KEY_LEN + 1]; /* add an extra byte to make room for a null-terminator */
unsigned char use_hmac = 0;
unsigned char use_keym = 0;
size_t hmac_key_len = 0;
bool bsdstyle = false;
int c, i;
@ -387,7 +447,7 @@ int main( int argc, char **argv )
{ NULL, 0, NULL, 0 }
};
c = getopt_long( argc, argv, "a:l:h:", long_options, &option_index );
c = getopt_long( argc, argv, "a:l:h:k:", long_options, &option_index );
if( c == -1 ) break;
switch( c )
{
@ -461,6 +521,34 @@ int main( int argc, char **argv )
}
} /* Now you have a zero-padded key, per spec */
break;
case 'k':
use_keym = 0xFF;
hmac_key_len = 0;
if ( 0 == strcmp( optarg, "-" ) ){
hmac_key_len = 0;
while(hmac_key_len < HMAC_MAX_KEY_LEN){
hmac_key[hmac_key_len++] = 0;
}
hmac_key[HMAC_MAX_KEY_LEN] = 0;
hmac_key_len = 0;
while(hmac_key_len < HMAC_MAX_KEY_LEN){
unsigned char c = getc(stdin);
if(c == '\n' || c == '\r') break;
hmac_key[hmac_key_len++] = c;
}
} else {
hmac_key_len = 0;
while(hmac_key_len < HMAC_MAX_KEY_LEN + 1){
hmac_key[hmac_key_len++] = 0;
}
hmac_key_len = 0;
while(hmac_key_len < HMAC_MAX_KEY_LEN){
unsigned char c = optarg[hmac_key_len];
if(c == 0) break;
hmac_key[hmac_key_len++] = c;
}
} /* Now you have a zero-padded key, per spec */
break;
case 0:
if( 0 == strcmp( "help", long_options[option_index].name ) )
usage( argv, 0 );
@ -502,7 +590,6 @@ int main( int argc, char **argv )
if(use_hmac){
if(hmac_key_len > outbytes){
size_t j;
printf("Building key...");
blake2b_stream_build_key( hmac_key, hmac_key_len, hash, outbytes );
for(j=0; j<outbytes; ++j){
hmac_key[j] = hash[j];
@ -568,6 +655,61 @@ int main( int argc, char **argv )
printf(hmac_key);
}
}
} else if(use_keym){
/*
Apparently OpenSSL doesn't use standard HMAC, *or* keyed mode with BLAKE2...
I'm using the keyed-mode provided by BLAKE's own library, so I'm just gonna
call it a day.
https://blake2.net/blake2.pdf
*/
if(hmac_key_len > outbytes){
size_t j;
blake2b_stream_build_key( hmac_key, hmac_key_len, hash, outbytes );
for(j=0; j<outbytes; ++j){
hmac_key[j] = hash[j];
hash[j] = 0;
}
hmac_key_len = outbytes;
}
/* The indentation is weird because I got lazy and used tab */
/* printf("%s\n", hmac_key); /* Used for debugging or seeing what the key looks like */
size_t j;
/* printf("%s\n", hmac_key); /* Used for debugging or seeing what the key looks like */
if( blake2b_stream_keym( hmac_key, hmac_key_len, f, hash, outbytes ) < 0 )
{
fprintf( stderr, "Failed to hash `%s'\n", argv[i] );
}
else
{
size_t j;
if( bsdstyle )
{
if( outbytes < maxbytes )
printf( "%s-%lu (%s) = ", algorithm, outbytes * 8, argv[i] );
else
printf( "%s (%s) = ", algorithm, argv[i] );
}
for( j = 0; j < outbytes; ++j )
printf( "%02x", hash[j] );
if( bsdstyle )
printf( "\n" );
else
printf( " %s\n", argv[i] );
/* clean up */
memset(hmac_key, 0, HMAC_MAX_KEY_LEN);
memset(hash2, 0, outbytes);
memset(hash, 0, outbytes);
/*
Make sure the compiler doesn't optimize away our memory reset; it's a security measure
*/
printf(hash);
printf(hash2);
printf(hmac_key);
}
} else{
if( blake2_stream( f, hash, outbytes ) < 0 )
{