@ -1041,6 +1041,21 @@ static struct drbg_state_ops drbg_hash_ops = {
* Functions common for DRBG implementations
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static inline int __drbg_seed ( struct drbg_state * drbg , struct list_head * seed ,
int reseed )
{
int ret = drbg - > d_ops - > update ( drbg , seed , reseed ) ;
if ( ret )
return ret ;
drbg - > seeded = true ;
/* 10.1.1.2 / 10.1.1.3 step 5 */
drbg - > reseed_ctr = 1 ;
return ret ;
}
/*
* Seeding or reseeding of the DRBG
*
@ -1056,8 +1071,6 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
bool reseed )
{
int ret = 0 ;
unsigned char * entropy = NULL ;
size_t entropylen = 0 ;
struct drbg_string data1 ;
LIST_HEAD ( seedlist ) ;
@ -1073,26 +1086,10 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
drbg - > test_data . len ) ;
pr_devel ( " DRBG: using test entropy \n " ) ;
} else {
/*
* Gather entropy equal to the security strength of the DRBG .
* With a derivation function , a nonce is required in addition
* to the entropy . A nonce must be at least 1 / 2 of the security
* strength of the DRBG in size . Thus , entropy * nonce is 3 / 2
* of the strength . The consideration of a nonce is only
* applicable during initial seeding .
*/
entropylen = drbg_sec_strength ( drbg - > core - > flags ) ;
if ( ! entropylen )
return - EFAULT ;
if ( ! reseed )
entropylen = ( ( entropylen + 1 ) / 2 ) * 3 ;
pr_devel ( " DRBG: (re)seeding with %zu bytes of entropy \n " ,
entropylen ) ;
entropy = kzalloc ( entropylen , GFP_KERNEL ) ;
if ( ! entropy )
return - ENOMEM ;
get_random_bytes ( entropy , entropylen ) ;
drbg_string_fill ( & data1 , entropy , entropylen ) ;
drbg - > seed_buf_len ) ;
get_random_bytes ( drbg - > seed_buf , drbg - > seed_buf_len ) ;
drbg_string_fill ( & data1 , drbg - > seed_buf , drbg - > seed_buf_len ) ;
}
list_add_tail ( & data1 . list , & seedlist ) ;
@ -1111,16 +1108,24 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
memset ( drbg - > C , 0 , drbg_statelen ( drbg ) ) ;
}
ret = drbg - > d_ops - > update ( drbg , & seedlist , reseed ) ;
ret = __drbg_seed ( drbg , & seedlist , reseed ) ;
/*
* Clear the initial entropy buffer as the async call may not overwrite
* that buffer for quite some time .
*/
memzero_explicit ( drbg - > seed_buf , drbg - > seed_buf_len ) ;
if ( ret )
goto out ;
drbg - > seeded = true ;
/* 10.1.1.2 / 10.1.1.3 step 5 */
drbg - > reseed_ctr = 1 ;
/*
* For all subsequent seeding calls , we only need the seed buffer
* equal to the security strength of the DRBG . We undo the calculation
* in drbg_alloc_state .
*/
if ( ! reseed )
drbg - > seed_buf_len = drbg - > seed_buf_len / 3 * 2 ;
out :
kzfree ( entropy ) ;
return ret ;
}
@ -1143,6 +1148,8 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
drbg - > prev = NULL ;
drbg - > fips_primed = false ;
# endif
kzfree ( drbg - > seed_buf ) ;
drbg - > seed_buf = NULL ;
}
/*
@ -1204,6 +1211,26 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
if ( ! drbg - > scratchpad )
goto err ;
}
/*
* Gather entropy equal to the security strength of the DRBG .
* With a derivation function , a nonce is required in addition
* to the entropy . A nonce must be at least 1 / 2 of the security
* strength of the DRBG in size . Thus , entropy * nonce is 3 / 2
* of the strength . The consideration of a nonce is only
* applicable during initial seeding .
*/
drbg - > seed_buf_len = drbg_sec_strength ( drbg - > core - > flags ) ;
if ( ! drbg - > seed_buf_len ) {
ret = - EFAULT ;
goto err ;
}
/* ensure we have sufficient buffer space for initial seed */
drbg - > seed_buf_len = ( ( drbg - > seed_buf_len + 1 ) / 2 ) * 3 ;
drbg - > seed_buf = kzalloc ( drbg - > seed_buf_len , GFP_KERNEL ) ;
if ( ! drbg - > seed_buf )
goto err ;
return 0 ;
err :