Re: [PATCH v2 05/25] crypto: ansi_cprng - Eliminate ctx->I and ctx->last_rand_data

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

 



Am Sonntag, 7. Dezember 2014, 07:26:13 schrieb George Spelvin:

Hi George,

> Careful use of the other available buffers avoids the need for
> these, shrinking the context by 32 bytes.
> 
> Neither the debug output nor the FIPS-required anti-repetition check
> are changed in the slightest.
> 
> Signed-off-by: George Spelvin <linux@xxxxxxxxxxx>
> ---
>  crypto/ansi_cprng.c | 50 ++++++++++++++++++++++++--------------------------
> 1 file changed, 24 insertions(+), 26 deletions(-)
> 
> diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
> index 325aa727d..2edac42e 100644
> --- a/crypto/ansi_cprng.c
> +++ b/crypto/ansi_cprng.c
> @@ -37,19 +37,14 @@
> 
>  /*
>   * Note: DT is our counter value
> - *	 I is our intermediate value
>   *	 V is our seed vector
>   * See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
>   * for implementation details
>   */
> -
> -
>  struct prng_context {
>  	spinlock_t prng_lock;
>  	unsigned char rand_data[DEFAULT_BLK_SZ];
> -	unsigned char last_rand_data[DEFAULT_BLK_SZ];
>  	unsigned char DT[DEFAULT_BLK_SZ];
> -	unsigned char I[DEFAULT_BLK_SZ];
>  	unsigned char V[DEFAULT_BLK_SZ];
>  	u32 rand_data_valid;
>  	struct crypto_cipher *tfm;
> @@ -97,27 +92,27 @@ static int _get_more_prng_bytes(struct prng_context
> *ctx, int cont_test)
> 
>  	/*
>  	 * Start by encrypting the counter value
> -	 * This gives us an intermediate value I
> +	 * This gives us an intermediate value I (stored in tmp)
>  	 */
> -	memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ);
> -	crypto_cipher_encrypt_one(ctx->tfm, ctx->I, tmp);
> -	hexdump("I", ctx->I);
> +	crypto_cipher_encrypt_one(ctx->tfm, tmp, ctx->DT);
> +	hexdump("I", tmp);
> 
>  	/*
> -	 * Next xor I with our secret vector V
> -	 * encrypt that result to obtain our
> -	 * pseudo random data which we output
> +	 * Next xor I with our secret vector V.  Encrypt that result
> +	 * to obtain our pseudo random data which we output.  But
> +	 * keep that output in ctx->V for the moment; we need the
> +	 * previous rand_data for ons more thing.
>  	 */
> -	xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ);
> -	hexdump("V^I", tmp);
> -	crypto_cipher_encrypt_one(ctx->tfm, ctx->rand_data, tmp);
> -	hexdump("R", ctx->rand_data);
> +	xor_vectors(tmp, ctx->V, ctx->V, DEFAULT_BLK_SZ);
> +	hexdump("V^I", ctx->V);
> +	crypto_cipher_encrypt_one(ctx->tfm, ctx->V, ctx->V);
> +	hexdump("R", ctx->V);
> 
>  	/*
> -	 * First check that we didn't produce the same
> -	 * random data that we did last time around through this
> +	 * Check that we didn't produce the same random data that we
> +	 * did last time around.
>  	 */
> -	if (!memcmp(ctx->rand_data, ctx->last_rand_data, DEFAULT_BLK_SZ)) {
> +	if (!memcmp(ctx->V, ctx->rand_data, DEFAULT_BLK_SZ)) {

Due to the huge number of diffs, I may have missed the following point. 
Therefore, please help me:

NIST requires that ctx->rand_data must be "primed" before the first random 
number is returned to the aller (see FIPS 140-2 section 4.9.2). That means, 
the very first random number that was generated must go into what is now ctx-
>rand_data, but shall not be returned to the caller.

Only starting with the 2nd random number these values shall be returned to the 
caller.

Where do I see that priming?

Note, this priming should have an ability to be disabled for performing the 
CAVS tests as they (as stupid as it may sound) want the very first random 
number after the seeding.

>  		if (cont_test) {
>  			panic("cprng %p Failed repetition check!\n", ctx);
>  		}
> @@ -127,15 +122,19 @@ static int _get_more_prng_bytes(struct prng_context
> *ctx, int cont_test) ctx->flags |= PRNG_NEED_RESET;
>  		return -EINVAL;
>  	}
> -	memcpy(ctx->last_rand_data, ctx->rand_data, DEFAULT_BLK_SZ);
> +	/*
> +	 * Okay, the new data is okay, copy it to the buffer.
> +	 */
> +	memcpy(ctx->rand_data, ctx->V, DEFAULT_BLK_SZ);
> 
>  	/*
> -	 * Lastly xor the random data with I
> -	 * and encrypt that to obtain a new secret vector V
> +	 * Lastly xor the random data with I and encrypt that to obtain
> +	 * a new secret vector V.
>  	 */
> -	xor_vectors(ctx->rand_data, ctx->I, tmp, DEFAULT_BLK_SZ);
> -	hexdump("R^I", tmp);
> -	crypto_cipher_encrypt_one(ctx->tfm, ctx->V, tmp);
> +	xor_vectors(tmp, ctx->V, ctx->V, DEFAULT_BLK_SZ);
> +	hexdump("R^I", ctx->V);
> +	memzero_explicit(tmp, DEFAULT_BLK_SZ);
> +	crypto_cipher_encrypt_one(ctx->tfm, ctx->V, ctx->V);
>  	hexdump("V'", ctx->V);
> 
>  	/*
> @@ -272,7 +271,6 @@ static int reset_prng_context(struct prng_context *ctx,
>  		memset(ctx->DT, 0, DEFAULT_BLK_SZ);
> 
>  	memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
> -	memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ);
> 
>  	ctx->rand_data_valid = DEFAULT_BLK_SZ;


-- 
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