@ -8,32 +8,33 @@
*/
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# include <openssl/hmac.h>
# include <openssl/kdf.h>
# include <openssl/evp.h>
# include <openssl/kdf.h>
# include "internal/cryptlib.h"
# include "internal/evp_int.h"
# include "kdf_local.h"
# define HKDF_MAXBUF 1024
static unsigned char * HKDF ( const EVP_MD * evp_md ,
const unsigned char * salt , size_t salt_len ,
const unsigned char * key , size_t key_len ,
const unsigned char * info , size_t info_len ,
unsigned char * okm , size_t okm_len ) ;
static unsigned char * HKDF_Extract ( const EVP_MD * evp_md ,
const unsigned char * salt , size_t salt_len ,
const unsigned char * key , size_t key_len ,
unsigned char * prk , size_t * prk_len ) ;
static unsigned char * HKDF_Expand ( const EVP_MD * evp_md ,
const unsigned char * prk , size_t prk_len ,
const unsigned char * info , size_t info_len ,
unsigned char * okm , size_t okm_len ) ;
typedef struct {
static void kdf_hkdf_reset ( EVP_KDF_IMPL * impl ) ;
static int HKDF ( const EVP_MD * evp_md ,
const unsigned char * salt , size_t salt_len ,
const unsigned char * key , size_t key_len ,
const unsigned char * info , size_t info_len ,
unsigned char * okm , size_t okm_len ) ;
static int HKDF_Extract ( const EVP_MD * evp_md ,
const unsigned char * salt , size_t salt_len ,
const unsigned char * key , size_t key_len ,
unsigned char * prk , size_t prk_len ) ;
static int HKDF_Expand ( const EVP_MD * evp_md ,
const unsigned char * prk , size_t prk_len ,
const unsigned char * info , size_t info_len ,
unsigned char * okm , size_t okm_len ) ;
struct evp_kdf_impl_st {
int mode ;
const EVP_MD * md ;
unsigned char * salt ;
@ -42,230 +43,208 @@ typedef struct {
size_t key_len ;
unsigned char info [ HKDF_MAXBUF ] ;
size_t info_len ;
} HKDF_PKEY_CTX ;
} ;
static int pkey_hkdf_init ( EVP_PKEY_CTX * ctx )
static EVP_KDF_IMPL * kdf_hkdf_new ( void )
{
HKDF_PKEY_CTX * kctx ;
EVP_KDF_IMPL * impl ;
if ( ( kctx = OPENSSL_zalloc ( sizeof ( * kctx ) ) ) = = NULL ) {
KDFerr ( KDF_F_PKEY_HKDF_INIT , ERR_R_MALLOC_FAILURE ) ;
return 0 ;
}
ctx - > data = kctx ;
if ( ( impl = OPENSSL_zalloc ( sizeof ( * impl ) ) ) = = NULL )
KDFerr ( KDF_F_KDF_HKDF_NEW , ERR_R_MALLOC_FAILURE ) ;
return impl ;
}
return 1 ;
static void kdf_hkdf_free ( EVP_KDF_IMPL * impl )
{
kdf_hkdf_reset ( impl ) ;
OPENSSL_free ( impl ) ;
}
static void pkey_hkdf_cleanup ( EVP_PKEY_CTX * ctx )
static void kdf_hkdf_reset( EVP_KDF_IMPL * impl )
{
HKDF_PKEY_CTX * kctx = ctx - > data ;
OPENSSL_clear_free ( kctx - > salt , kctx - > salt_len ) ;
OPENSSL_clear_free ( kctx - > key , kctx - > key_len ) ;
OPENSSL_cleanse ( kctx - > info , kctx - > info_len ) ;
OPENSSL_free ( kctx ) ;
OPENSSL_free ( impl - > salt ) ;
OPENSSL_clear_free ( impl - > key , impl - > key_len ) ;
OPENSSL_cleanse ( impl - > info , impl - > info_len ) ;
memset ( impl , 0 , sizeof ( * impl ) ) ;
}
static int pkey_hkdf_ctrl( EVP_PKEY_CTX * ctx , int type , int p1 , void * p2 )
static int kdf_hkdf_ctrl( EVP_KDF_IMPL * impl , int cmd , va_list args )
{
HKDF_PKEY_CTX * kctx = ctx - > data ;
const unsigned char * p ;
size_t len ;
const EVP_MD * md ;
switch ( type ) {
case EVP_PKEY_CTRL_HKDF_MD :
if ( p2 = = NULL )
switch ( cmd ) {
case EVP_KDF_CTRL_SET_MD :
md = va_arg ( args , const EVP_MD * ) ;
if ( md = = NULL )
return 0 ;
kctx- > md = p2 ;
impl- > md = md ;
return 1 ;
case EVP_ PKEY_CTRL _HKDF_MODE:
kctx- > mode = p1 ;
case EVP_ KDF_CTRL_SET _HKDF_MODE:
impl- > mode = va_arg ( args , int ) ;
return 1 ;
case EVP_PKEY_CTRL_HKDF_SALT :
if ( p1 = = 0 | | p2 = = NULL )
case EVP_KDF_CTRL_SET_SALT :
p = va_arg ( args , const unsigned char * ) ;
len = va_arg ( args , size_t ) ;
if ( len = = 0 | | p = = NULL )
return 1 ;
if ( p1 < 0 )
OPENSSL_free ( impl - > salt ) ;
impl - > salt = OPENSSL_memdup ( p , len ) ;
if ( impl - > salt = = NULL )
return 0 ;
if ( kctx - > salt ! = NULL )
OPENSSL_clear_free ( kctx - > salt , kctx - > salt_len ) ;
kctx - > salt = OPENSSL_memdup ( p2 , p1 ) ;
if ( kctx - > salt = = NULL )
return 0 ;
kctx - > salt_len = p1 ;
impl - > salt_len = len ;
return 1 ;
case EVP_PKEY_CTRL_HKDF_KEY :
if ( p1 < 0 )
case EVP_KDF_CTRL_SET_KEY :
p = va_arg ( args , const unsigned char * ) ;
len = va_arg ( args , size_t ) ;
OPENSSL_clear_free ( impl - > key , impl - > key_len ) ;
impl - > key = OPENSSL_memdup ( p , len ) ;
if ( impl - > key = = NULL )
return 0 ;
if ( kctx - > key ! = NULL )
OPENSSL_clear_free ( kctx - > key , kctx - > key_len ) ;
kctx - > key = OPENSSL_memdup ( p2 , p1 ) ;
if ( kctx - > key = = NULL )
return 0 ;
impl - > key_len = len ;
return 1 ;
kctx - > key_len = p1 ;
case EVP_KDF_CTRL_RESET_HKDF_INFO :
OPENSSL_cleanse ( impl - > info , impl - > info_len ) ;
impl - > info_len = 0 ;
return 1 ;
case EVP_PKEY_CTRL_HKDF_INFO :
if ( p1 = = 0 | | p2 = = NULL )
case EVP_KDF_CTRL_ADD_HKDF_INFO :
p = va_arg ( args , const unsigned char * ) ;
len = va_arg ( args , size_t ) ;
if ( len = = 0 | | p = = NULL )
return 1 ;
if ( p1 < 0 | | p1 > ( int ) ( HKDF_MAXBUF - kctx - > info_len ) )
if ( len > ( HKDF_MAXBUF - impl - > info_len ) )
return 0 ;
memcpy ( kctx- > info + kctx - > info_len , p2 , p1 ) ;
kctx- > info_len + = p1 ;
memcpy ( impl- > info + impl - > info_len , p , len ) ;
impl- > info_len + = len ;
return 1 ;
default :
return - 2 ;
}
}
static int pkey_hkdf_ctrl_str( EVP_PKEY_CTX * ctx , const char * type ,
const char * value )
static int kdf_hkdf_ctrl_str( EVP_KDF_IMPL * impl , const char * type ,
const char * value )
{
if ( strcmp ( type , " mode " ) = = 0 ) {
int mode ;
if ( strcmp ( value , " EXTRACT_AND_EXPAND " ) = = 0 )
mode = EVP_ PKEY_HKDE F_MODE_EXTRACT_AND_EXPAND;
mode = EVP_ KDF_HKD F_MODE_EXTRACT_AND_EXPAND;
else if ( strcmp ( value , " EXTRACT_ONLY " ) = = 0 )
mode = EVP_ PKEY_HKDE F_MODE_EXTRACT_ONLY;
mode = EVP_ KDF_HKD F_MODE_EXTRACT_ONLY;
else if ( strcmp ( value , " EXPAND_ONLY " ) = = 0 )
mode = EVP_ PKEY_HKDE F_MODE_EXPAND_ONLY;
mode = EVP_ KDF_HKD F_MODE_EXPAND_ONLY;
else
return 0 ;
return EVP_PKEY_CTX_hkdf_mode( ctx , mode ) ;
return call_ctrl( kdf_hkdf_ctrl , impl , EVP_KDF_CTRL_SET_HKDF_MODE , mode ) ;
}
if ( strcmp ( type , " md " ) = = 0 )
return EVP_PKEY_CTX_md ( ctx , EVP_PKEY_OP_DERIVE ,
EVP_PKEY_CTRL_HKDF_MD , value ) ;
if ( strcmp ( type , " digest " ) = = 0 )
return kdf_md2ctrl ( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_SET_MD , value ) ;
if ( strcmp ( type , " salt " ) = = 0 )
return EVP_PKEY_CTX_str2ctrl( ctx , EVP_PKEY_CTRL_HKDF _SALT, value ) ;
return kdf_str2ctrl( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_SET _SALT, value ) ;
if ( strcmp ( type , " hexsalt " ) = = 0 )
return EVP_PKEY_CTX_hex2ctrl( ctx , EVP_PKEY_CTRL_HKDF _SALT, value ) ;
return kdf_hex2ctrl( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_SET _SALT, value ) ;
if ( strcmp ( type , " key " ) = = 0 )
return EVP_PKEY_CTX_str2ctrl( ctx , EVP_PKEY_CTRL_HKDF _KEY, value ) ;
return kdf_str2ctrl( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_SET _KEY, value ) ;
if ( strcmp ( type , " hexkey " ) = = 0 )
return EVP_PKEY_CTX_hex2ctrl( ctx , EVP_PKEY_CTRL_HKDF _KEY, value ) ;
return kdf_hex2ctrl( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_SET _KEY, value ) ;
if ( strcmp ( type , " info " ) = = 0 )
return EVP_PKEY_CTX_str2ctrl ( ctx , EVP_PKEY_CTRL_HKDF_INFO , value ) ;
return kdf_str2ctrl ( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_ADD_HKDF_INFO ,
value ) ;
if ( strcmp ( type , " hexinfo " ) = = 0 )
return EVP_PKEY_CTX_hex2ctrl ( ctx , EVP_PKEY_CTRL_HKDF_INFO , value ) ;
return kdf_hex2ctrl ( impl , kdf_hkdf_ctrl , EVP_KDF_CTRL_ADD_HKDF_INFO ,
value ) ;
KDFerr ( KDF_F_PKEY_HKDF_CTRL_STR , KDF_R_UNKNOWN_PARAMETER_TYPE ) ;
return - 2 ;
}
static int pkey_hkdf_derive_init ( EVP_PKEY_CTX * ctx )
static size_t kdf_hkdf_size ( EVP_KDF_IMPL * impl )
{
HKDF_PKEY_CTX * kctx = ctx - > data ;
OPENSSL_clear_free ( kctx - > key , kctx - > key_len ) ;
OPENSSL_clear_free ( kctx - > salt , kctx - > salt_len ) ;
OPENSSL_cleanse ( kctx - > info , kctx - > info_len ) ;
memset ( kctx , 0 , sizeof ( * kctx ) ) ;
if ( impl - > mode ! = EVP_KDF_HKDF_MODE_EXTRACT_ONLY )
return SIZE_MAX ;
return 1 ;
if ( impl - > md = = NULL ) {
KDFerr ( KDF_F_KDF_HKDF_SIZE , KDF_R_MISSING_MESSAGE_DIGEST ) ;
return 0 ;
}
return EVP_MD_size ( impl - > md ) ;
}
static int pkey_hkdf_derive ( EVP_PKEY_CTX * ctx , unsigned char * key ,
size_t * keylen )
static int kdf_hkdf_derive( EVP_KDF_IMPL * impl , unsigned char * key ,
size_t keylen )
{
HKDF_PKEY_CTX * kctx = ctx - > data ;
if ( kctx - > md = = NULL ) {
KDFerr ( KDF_F_PKEY_HKDF_DERIVE , KDF_R_MISSING_MESSAGE_DIGEST ) ;
if ( impl - > md = = NULL ) {
KDFerr ( KDF_F_KDF_HKDF_DERIVE , KDF_R_MISSING_MESSAGE_DIGEST ) ;
return 0 ;
}
if ( kctx - > key = = NULL ) {
KDFerr ( KDF_F_ PKEY _HKDF_DERIVE, KDF_R_MISSING_KEY ) ;
if ( impl - > key = = NULL ) {
KDFerr ( KDF_F_ KDF _HKDF_DERIVE, KDF_R_MISSING_KEY ) ;
return 0 ;
}
switch ( kctx - > mode ) {
case EVP_ PKEY_HKDE F_MODE_EXTRACT_AND_EXPAND:
return HKDF ( kctx- > md , kctx - > salt , kctx - > salt_len , kctx - > key ,
kctx- > key_len , kctx - > info , kctx - > info_len , key ,
* keylen ) ! = NULL ;
switch ( impl - > mode ) {
case EVP_ KDF_HKD F_MODE_EXTRACT_AND_EXPAND:
return HKDF ( impl- > md , impl - > salt , impl - > salt_len , impl - > key ,
impl- > key_len , impl - > info , impl - > info_len , key ,
keylen ) ;
case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY :
if ( key = = NULL ) {
* keylen = EVP_MD_size ( kctx - > md ) ;
return 1 ;
}
return HKDF_Extract ( kctx - > md , kctx - > salt , kctx - > salt_len , kctx - > key ,
kctx - > key_len , key , keylen ) ! = NULL ;
case EVP_KDF_HKDF_MODE_EXTRACT_ONLY :
return HKDF_Extract ( impl - > md , impl - > salt , impl - > salt_len , impl - > key ,
impl - > key_len , key , keylen ) ;
case EVP_ PKEY_HKDE F_MODE_EXPAND_ONLY:
return HKDF_Expand ( kctx- > md , kctx - > key , kctx - > key_len , kctx - > info ,
kctx - > info_len , key , * keylen ) ! = NULL ;
case EVP_KDF_HKDF_MODE_EXPAND_ONLY :