Re: crypto: drbg - Do not seed RNG in drbg_kcapi_init

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Am Montag, 20. April 2015, 11:29:15 schrieb Herbert Xu:

Hi Herbert,

> Initialising the RNG in drbg_kcapi_init is a waste of precious
> entropy because all users will immediately seed the RNG after
> the allocation.
> 
> In fact, all users should seed the RNG before using it.  So there
> is no point in doing the seeding in drbg_kcapi_init.
> 
> This patch removes the initial seeding and the user must seed
> the RNG explicitly (as they all currently do).
> 
> This patch also changes drbg_kcapi_reset to allow reseeding.
> That is, if you call it after a successful initial seeding, then
> it will not reset the internal state of the DRBG before mixing
> the new input and entropy.
> 
> If you still wish to reset the internal state, you can always
> free the DRBG and allocate a new one.
> 
> Finally this patch removes locking from drbg_uninstantiate because
> it's now only called from the destruction path which must not be
> executed in parallel with normal operations.
> 
> Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>

Acked-by: Stephan Mueller <smueller@xxxxxxxxxx>

> 
> diff --git a/crypto/drbg.c b/crypto/drbg.c
> index 57fd479..5bce159 100644
> --- a/crypto/drbg.c
> +++ b/crypto/drbg.c
> @@ -1136,6 +1136,8 @@ static inline void drbg_dealloc_state(struct
> drbg_state *drbg) kzfree(drbg->scratchpad);
>  	drbg->scratchpad = NULL;
>  	drbg->reseed_ctr = 0;
> +	drbg->d_ops = NULL;
> +	drbg->core = NULL;
>  #ifdef CONFIG_CRYPTO_FIPS
>  	kzfree(drbg->prev);
>  	drbg->prev = NULL;
> @@ -1152,6 +1154,27 @@ static inline int drbg_alloc_state(struct drbg_state
> *drbg) int ret = -ENOMEM;
>  	unsigned int sb_size = 0;
> 
> +	switch (drbg->core->flags & DRBG_TYPE_MASK) {
> +#ifdef CONFIG_CRYPTO_DRBG_HMAC
> +	case DRBG_HMAC:
> +		drbg->d_ops = &drbg_hmac_ops;
> +		break;
> +#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> +#ifdef CONFIG_CRYPTO_DRBG_HASH
> +	case DRBG_HASH:
> +		drbg->d_ops = &drbg_hash_ops;
> +		break;
> +#endif /* CONFIG_CRYPTO_DRBG_HASH */
> +#ifdef CONFIG_CRYPTO_DRBG_CTR
> +	case DRBG_CTR:
> +		drbg->d_ops = &drbg_ctr_ops;
> +		break;
> +#endif /* CONFIG_CRYPTO_DRBG_CTR */
> +	default:
> +		ret = -EOPNOTSUPP;
> +		goto err;
> +	}
> +
>  	drbg->V = kmalloc(drbg_statelen(drbg), GFP_KERNEL);
>  	if (!drbg->V)
>  		goto err;
> @@ -1215,6 +1238,10 @@ static int drbg_generate(struct drbg_state *drbg,
>  	int len = 0;
>  	LIST_HEAD(addtllist);
> 
> +	if (!drbg->core) {
> +		pr_devel("DRBG: not yet seeded\n");
> +		return -EINVAL;
> +	}
>  	if (0 == buflen || !buf) {
>  		pr_devel("DRBG: no output buffer provided\n");
>  		return -EINVAL;
> @@ -1372,33 +1399,12 @@ static int drbg_generate_long(struct drbg_state
> *drbg, static int drbg_instantiate(struct drbg_state *drbg, struct
> drbg_string *pers, int coreref, bool pr)
>  {
> -	int ret = -EOPNOTSUPP;
> +	int ret;
> +	bool reseed = true;
> 
>  	pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
>  		 "%s\n", coreref, pr ? "enabled" : "disabled");
>  	mutex_lock(&drbg->drbg_mutex);
> -	drbg->core = &drbg_cores[coreref];
> -	drbg->pr = pr;
> -	drbg->seeded = false;
> -	switch (drbg->core->flags & DRBG_TYPE_MASK) {
> -#ifdef CONFIG_CRYPTO_DRBG_HMAC
> -	case DRBG_HMAC:
> -		drbg->d_ops = &drbg_hmac_ops;
> -		break;
> -#endif /* CONFIG_CRYPTO_DRBG_HMAC */
> -#ifdef CONFIG_CRYPTO_DRBG_HASH
> -	case DRBG_HASH:
> -		drbg->d_ops = &drbg_hash_ops;
> -		break;
> -#endif /* CONFIG_CRYPTO_DRBG_HASH */
> -#ifdef CONFIG_CRYPTO_DRBG_CTR
> -	case DRBG_CTR:
> -		drbg->d_ops = &drbg_ctr_ops;
> -		break;
> -#endif /* CONFIG_CRYPTO_DRBG_CTR */
> -	default:
> -		goto unlock;
> -	}
> 
>  	/* 9.1 step 1 is implicit with the selected DRBG type */
> 
> @@ -1410,21 +1416,31 @@ static int drbg_instantiate(struct drbg_state *drbg,
> struct drbg_string *pers,
> 
>  	/* 9.1 step 4 is implicit in  drbg_sec_strength */
> 
> -	ret = drbg_alloc_state(drbg);
> -	if (ret)
> -		goto unlock;
> +	if (!drbg->core) {
> +		drbg->core = &drbg_cores[coreref];
> +		drbg->pr = pr;
> +		drbg->seeded = false;
> 
> -	ret = -EFAULT;
> -	if (drbg->d_ops->crypto_init(drbg))
> -		goto err;
> -	ret = drbg_seed(drbg, pers, false);
> -	if (ret) {
> +		ret = drbg_alloc_state(drbg);
> +		if (ret)
> +			goto unlock;
> +
> +		ret = -EFAULT;
> +		if (drbg->d_ops->crypto_init(drbg))
> +			goto err;
> +
> +		reseed = false;
> +	}
> +
> +	ret = drbg_seed(drbg, pers, reseed);
> +
> +	if (ret && !reseed) {
>  		drbg->d_ops->crypto_fini(drbg);
>  		goto err;
>  	}
> 
>  	mutex_unlock(&drbg->drbg_mutex);
> -	return 0;
> +	return ret;
> 
>  err:
>  	drbg_dealloc_state(drbg);
> @@ -1444,11 +1460,10 @@ unlock:
>   */
>  static int drbg_uninstantiate(struct drbg_state *drbg)
>  {
> -	mutex_lock(&drbg->drbg_mutex);
> -	drbg->d_ops->crypto_fini(drbg);
> +	if (drbg->d_ops)
> +		drbg->d_ops->crypto_fini(drbg);
>  	drbg_dealloc_state(drbg);
>  	/* no scrubbing of test_data -- this shall survive an uninstantiate */
> -	mutex_unlock(&drbg->drbg_mutex);
>  	return 0;
>  }
> 
> @@ -1615,16 +1630,10 @@ static inline void drbg_convert_tfm_core(const char
> *cra_driver_name, static int drbg_kcapi_init(struct crypto_tfm *tfm)
>  {
>  	struct drbg_state *drbg = crypto_tfm_ctx(tfm);
> -	bool pr = false;
> -	int coreref = 0;
> 
>  	mutex_init(&drbg->drbg_mutex);
> -	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm), &coreref, &pr);
> -	/*
> -	 * when personalization string is needed, the caller must call reset
> -	 * and provide the personalization string as seed information
> -	 */
> -	return drbg_instantiate(drbg, NULL, coreref, pr);
> +
> +	return 0;
>  }
> 
>  static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
> @@ -1665,10 +1674,9 @@ static int drbg_kcapi_random(struct crypto_rng *tfm,
> u8 *rdata, }
> 
>  /*
> - * Reset the DRBG invoked by the kernel crypto API
> - * The reset implies a full re-initialization of the DRBG. Similar to the
> - * generate function of drbg_kcapi_random, this function extends the
> - * kernel crypto API interface with struct drbg_gen
> + * Seed the DRBG invoked by the kernel crypto API
> + * Similar to the generate function of drbg_kcapi_random, this
> + * function extends the kernel crypto API interface with struct drbg_gen
>   */
>  static int drbg_kcapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int
> slen) {
> @@ -1678,7 +1686,6 @@ static int drbg_kcapi_reset(struct crypto_rng *tfm, u8
> *seed, unsigned int slen) struct drbg_string seed_string;
>  	int coreref = 0;
> 
> -	drbg_uninstantiate(drbg);
>  	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
>  			      &pr);
>  	if (0 < slen) {


-- 
Ciao
Stephan
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux