@ -199,14 +199,19 @@ static OSSL_PARAM *construct_hkdf_params(char *digest, char *key,
if ( params = = NULL )
return NULL ;
* p + + = OSSL_PARAM_construct_utf8_string ( OSSL_KDF_PARAM_DIGEST ,
digest , 0 ) ;
if ( digest ! = NULL )
* p + + = OSSL_PARAM_construct_utf8_string ( OSSL_KDF_PARAM_DIGEST ,
digest , 0 ) ;
* p + + = OSSL_PARAM_construct_octet_string ( OSSL_KDF_PARAM_SALT ,
salt , strlen ( salt ) ) ;
* p + + = OSSL_PARAM_construct_octet_string ( OSSL_KDF_PARAM_KEY ,
( unsigned char * ) key , keylen ) ;
* p + + = OSSL_PARAM_construct_octet_string ( OSSL_KDF_PARAM_INFO ,
info , strlen ( info ) ) ;
if ( info ! = NULL )
* p + + = OSSL_PARAM_construct_octet_string ( OSSL_KDF_PARAM_INFO ,
info , strlen ( info ) ) ;
else
* p + + = OSSL_PARAM_construct_utf8_string ( OSSL_KDF_PARAM_MODE ,
" EXTRACT_ONLY " , 0 ) ;
* p = OSSL_PARAM_construct_end ( ) ;
return params ;
@ -234,6 +239,66 @@ static int test_kdf_hkdf(void)
return ret ;
}
static int do_kdf_hkdf_gettables ( int expand_only , int has_digest )
{
int ret = 0 ;
size_t sz = 0 ;
OSSL_PARAM * params ;
OSSL_PARAM params_get [ 2 ] ;
const OSSL_PARAM * gettables , * p ;
EVP_KDF_CTX * kctx = NULL ;
if ( ! TEST_ptr ( params = construct_hkdf_params (
has_digest ? " sha256 " : NULL ,
" secret " , 6 , " salt " ,
expand_only ? NULL : " label " ) )
| | ! TEST_ptr ( kctx = get_kdfbyname ( OSSL_KDF_NAME_HKDF ) )
| | ! TEST_true ( EVP_KDF_CTX_set_params ( kctx , params ) ) )
goto err ;
/* Check OSSL_KDF_PARAM_SIZE is gettable */
if ( ! TEST_ptr ( gettables = EVP_KDF_CTX_gettable_params ( kctx ) )
| | ! TEST_ptr ( p = OSSL_PARAM_locate_const ( gettables , OSSL_KDF_PARAM_SIZE ) ) )
goto err ;
/* Get OSSL_KDF_PARAM_SIZE as a size_t */
params_get [ 0 ] = OSSL_PARAM_construct_size_t ( OSSL_KDF_PARAM_SIZE , & sz ) ;
params_get [ 1 ] = OSSL_PARAM_construct_end ( ) ;
if ( has_digest ) {
if ( ! TEST_int_eq ( EVP_KDF_CTX_get_params ( kctx , params_get ) , 1 )
| | ! TEST_size_t_eq ( sz , expand_only ? SHA256_DIGEST_LENGTH : SIZE_MAX ) )
goto err ;
} else {
if ( ! TEST_int_eq ( EVP_KDF_CTX_get_params ( kctx , params_get ) , 0 ) )
goto err ;
}
/* Get params returns -2 if an unsupported parameter is requested */
params_get [ 0 ] = OSSL_PARAM_construct_end ( ) ;
if ( ! TEST_int_eq ( EVP_KDF_CTX_get_params ( kctx , params_get ) , - 2 ) )
goto err ;
ret = 1 ;
err :
EVP_KDF_CTX_free ( kctx ) ;
OPENSSL_free ( params ) ;
return ret ;
}
static int test_kdf_hkdf_gettables ( void )
{
return do_kdf_hkdf_gettables ( 0 , 1 ) ;
}
static int test_kdf_hkdf_gettables_expandonly ( void )
{
return do_kdf_hkdf_gettables ( 1 , 1 ) ;
}
static int test_kdf_hkdf_gettables_no_digest ( void )
{
return do_kdf_hkdf_gettables ( 1 , 0 ) ;
}
static int test_kdf_hkdf_invalid_digest ( void )
{
int ret ;
@ -251,6 +316,89 @@ static int test_kdf_hkdf_invalid_digest(void)
return ret ;
}
static int test_kdf_hkdf_derive_set_params_fail ( void )
{
int ret = 0 , i = 0 ;
EVP_KDF_CTX * kctx = NULL ;
OSSL_PARAM params [ 2 ] ;
unsigned char out [ 10 ] ;
if ( ! TEST_ptr ( kctx = get_kdfbyname ( OSSL_KDF_NAME_HKDF ) ) )
goto end ;
/*
* Set the wrong type for the digest so that it causes a failure
* inside kdf_hkdf_derive ( ) when kdf_hkdf_set_ctx_params ( ) is called
*/
params [ 0 ] = OSSL_PARAM_construct_int ( OSSL_KDF_PARAM_DIGEST , & i ) ;
params [ 1 ] = OSSL_PARAM_construct_end ( ) ;
if ( ! TEST_int_eq ( EVP_KDF_derive ( kctx , out , sizeof ( out ) , params ) , 0 ) )
goto end ;
ret = 1 ;
end :
EVP_KDF_CTX_free ( kctx ) ;
return ret ;
}
static int test_kdf_hkdf_set_invalid_mode ( void )
{
int ret = 0 , bad_mode = 100 ;
EVP_KDF_CTX * kctx = NULL ;
OSSL_PARAM params [ 2 ] ;
if ( ! TEST_ptr ( kctx = get_kdfbyname ( OSSL_KDF_NAME_HKDF ) ) )
goto end ;
params [ 0 ] = OSSL_PARAM_construct_utf8_string ( OSSL_KDF_PARAM_MODE ,
" BADMODE " , 0 ) ;
params [ 1 ] = OSSL_PARAM_construct_end ( ) ;
if ( ! TEST_int_eq ( EVP_KDF_CTX_set_params ( kctx , params ) , 0 ) )
goto end ;
params [ 0 ] = OSSL_PARAM_construct_int ( OSSL_KDF_PARAM_MODE , & bad_mode ) ;
if ( ! TEST_int_eq ( EVP_KDF_CTX_set_params ( kctx , params ) , 0 ) )
goto end ;
ret = 1 ;
end :
EVP_KDF_CTX_free ( kctx ) ;
return ret ;
}
static int do_kdf_hkdf_set_invalid_param ( const char * key , int type )
{
int ret = 0 ;
EVP_KDF_CTX * kctx = NULL ;
OSSL_PARAM params [ 2 ] ;
unsigned char buf [ 2 ] ;
if ( ! TEST_ptr ( kctx = get_kdfbyname ( OSSL_KDF_NAME_HKDF ) ) )
goto end ;
/* Set the wrong type for the key so that it causes a failure */
if ( type = = OSSL_PARAM_UTF8_STRING )
params [ 0 ] = OSSL_PARAM_construct_utf8_string ( key , " BAD " , 0 ) ;
else
params [ 0 ] = OSSL_PARAM_construct_octet_string ( key , buf , sizeof ( buf ) ) ;
params [ 1 ] = OSSL_PARAM_construct_end ( ) ;
if ( ! TEST_int_eq ( EVP_KDF_CTX_set_params ( kctx , params ) , 0 ) )
goto end ;
ret = 1 ;
end :
EVP_KDF_CTX_free ( kctx ) ;
return ret ;
}
static int test_kdf_hkdf_set_ctx_param_fail ( void )
{
return do_kdf_hkdf_set_invalid_param ( OSSL_KDF_PARAM_MODE ,
OSSL_PARAM_OCTET_STRING )
& & do_kdf_hkdf_set_invalid_param ( OSSL_KDF_PARAM_KEY ,
OSSL_PARAM_UTF8_STRING )
& & do_kdf_hkdf_set_invalid_param ( OSSL_KDF_PARAM_SALT ,
OSSL_PARAM_UTF8_STRING )
& & do_kdf_hkdf_set_invalid_param ( OSSL_KDF_PARAM_INFO ,
OSSL_PARAM_UTF8_STRING ) ;
}
static int test_kdf_hkdf_zero_output_size ( void )
{
int ret ;
@ -366,8 +514,10 @@ static int test_kdf_pbkdf1(void)
/* PBKDF1 only available in the legacy provider */
prov = OSSL_PROVIDER_load ( libctx , " legacy " ) ;
if ( prov = = NULL )
if ( prov = = NULL ) {
OSSL_LIB_CTX_free ( libctx ) ;
return TEST_skip ( " PBKDF1 only available in legacy provider " ) ;
}
params = construct_pbkdf1_params ( " passwordPASSWORDpassword " , " sha256 " ,
" saltSALTsaltSALTsaltSALTsaltSALTsalt " ,
@ -1495,6 +1645,12 @@ int setup_tests(void)
ADD_TEST ( test_kdf_hkdf_empty_key ) ;
ADD_TEST ( test_kdf_hkdf_1byte_key ) ;
ADD_TEST ( test_kdf_hkdf_empty_salt ) ;
ADD_TEST ( test_kdf_hkdf_gettables ) ;
ADD_TEST ( test_kdf_hkdf_gettables_expandonly ) ;
ADD_TEST ( test_kdf_hkdf_gettables_no_digest ) ;
ADD_TEST ( test_kdf_hkdf_derive_set_params_fail ) ;
ADD_TEST ( test_kdf_hkdf_set_invalid_mode ) ;
ADD_TEST ( test_kdf_hkdf_set_ctx_param_fail ) ;
ADD_TEST ( test_kdf_pbkdf2 ) ;
ADD_TEST ( test_kdf_pbkdf2_small_output ) ;
ADD_TEST ( test_kdf_pbkdf2_large_output ) ;