diff options
Diffstat (limited to 'crypto/ansi_cprng.c')
-rw-r--r-- | crypto/ansi_cprng.c | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index 3aa6e3834bf..027176a0e88 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c | |||
@@ -85,7 +85,7 @@ static void xor_vectors(unsigned char *in1, unsigned char *in2, | |||
85 | * Returns DEFAULT_BLK_SZ bytes of random data per call | 85 | * Returns DEFAULT_BLK_SZ bytes of random data per call |
86 | * returns 0 if generation succeded, <0 if something went wrong | 86 | * returns 0 if generation succeded, <0 if something went wrong |
87 | */ | 87 | */ |
88 | static int _get_more_prng_bytes(struct prng_context *ctx) | 88 | static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test) |
89 | { | 89 | { |
90 | int i; | 90 | int i; |
91 | unsigned char tmp[DEFAULT_BLK_SZ]; | 91 | unsigned char tmp[DEFAULT_BLK_SZ]; |
@@ -132,7 +132,7 @@ static int _get_more_prng_bytes(struct prng_context *ctx) | |||
132 | */ | 132 | */ |
133 | if (!memcmp(ctx->rand_data, ctx->last_rand_data, | 133 | if (!memcmp(ctx->rand_data, ctx->last_rand_data, |
134 | DEFAULT_BLK_SZ)) { | 134 | DEFAULT_BLK_SZ)) { |
135 | if (fips_enabled) { | 135 | if (cont_test) { |
136 | panic("cprng %p Failed repetition check!\n", | 136 | panic("cprng %p Failed repetition check!\n", |
137 | ctx); | 137 | ctx); |
138 | } | 138 | } |
@@ -185,7 +185,8 @@ static int _get_more_prng_bytes(struct prng_context *ctx) | |||
185 | } | 185 | } |
186 | 186 | ||
187 | /* Our exported functions */ | 187 | /* Our exported functions */ |
188 | static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) | 188 | static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx, |
189 | int do_cont_test) | ||
189 | { | 190 | { |
190 | unsigned char *ptr = buf; | 191 | unsigned char *ptr = buf; |
191 | unsigned int byte_count = (unsigned int)nbytes; | 192 | unsigned int byte_count = (unsigned int)nbytes; |
@@ -220,7 +221,7 @@ static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) | |||
220 | 221 | ||
221 | remainder: | 222 | remainder: |
222 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { | 223 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { |
223 | if (_get_more_prng_bytes(ctx) < 0) { | 224 | if (_get_more_prng_bytes(ctx, do_cont_test) < 0) { |
224 | memset(buf, 0, nbytes); | 225 | memset(buf, 0, nbytes); |
225 | err = -EINVAL; | 226 | err = -EINVAL; |
226 | goto done; | 227 | goto done; |
@@ -247,7 +248,7 @@ empty_rbuf: | |||
247 | */ | 248 | */ |
248 | for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { | 249 | for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { |
249 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { | 250 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { |
250 | if (_get_more_prng_bytes(ctx) < 0) { | 251 | if (_get_more_prng_bytes(ctx, do_cont_test) < 0) { |
251 | memset(buf, 0, nbytes); | 252 | memset(buf, 0, nbytes); |
252 | err = -EINVAL; | 253 | err = -EINVAL; |
253 | goto done; | 254 | goto done; |
@@ -356,7 +357,15 @@ static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata, | |||
356 | { | 357 | { |
357 | struct prng_context *prng = crypto_rng_ctx(tfm); | 358 | struct prng_context *prng = crypto_rng_ctx(tfm); |
358 | 359 | ||
359 | return get_prng_bytes(rdata, dlen, prng); | 360 | return get_prng_bytes(rdata, dlen, prng, 0); |
361 | } | ||
362 | |||
363 | static int fips_cprng_get_random(struct crypto_rng *tfm, u8 *rdata, | ||
364 | unsigned int dlen) | ||
365 | { | ||
366 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
367 | |||
368 | return get_prng_bytes(rdata, dlen, prng, 1); | ||
360 | } | 369 | } |
361 | 370 | ||
362 | /* | 371 | /* |
@@ -384,6 +393,26 @@ static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | |||
384 | return 0; | 393 | return 0; |
385 | } | 394 | } |
386 | 395 | ||
396 | static int fips_cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | ||
397 | { | ||
398 | u8 rdata[DEFAULT_BLK_SZ]; | ||
399 | int rc; | ||
400 | |||
401 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
402 | |||
403 | rc = cprng_reset(tfm, seed, slen); | ||
404 | |||
405 | if (!rc) | ||
406 | goto out; | ||
407 | |||
408 | /* this primes our continuity test */ | ||
409 | rc = get_prng_bytes(rdata, DEFAULT_BLK_SZ, prng, 0); | ||
410 | prng->rand_data_valid = DEFAULT_BLK_SZ; | ||
411 | |||
412 | out: | ||
413 | return rc; | ||
414 | } | ||
415 | |||
387 | static struct crypto_alg rng_alg = { | 416 | static struct crypto_alg rng_alg = { |
388 | .cra_name = "stdrng", | 417 | .cra_name = "stdrng", |
389 | .cra_driver_name = "ansi_cprng", | 418 | .cra_driver_name = "ansi_cprng", |
@@ -404,19 +433,51 @@ static struct crypto_alg rng_alg = { | |||
404 | } | 433 | } |
405 | }; | 434 | }; |
406 | 435 | ||
436 | #ifdef CONFIG_CRYPTO_FIPS | ||
437 | static struct crypto_alg fips_rng_alg = { | ||
438 | .cra_name = "fips(ansi_cprng)", | ||
439 | .cra_driver_name = "fips_ansi_cprng", | ||
440 | .cra_priority = 300, | ||
441 | .cra_flags = CRYPTO_ALG_TYPE_RNG, | ||
442 | .cra_ctxsize = sizeof(struct prng_context), | ||
443 | .cra_type = &crypto_rng_type, | ||
444 | .cra_module = THIS_MODULE, | ||
445 | .cra_list = LIST_HEAD_INIT(rng_alg.cra_list), | ||
446 | .cra_init = cprng_init, | ||
447 | .cra_exit = cprng_exit, | ||
448 | .cra_u = { | ||
449 | .rng = { | ||
450 | .rng_make_random = fips_cprng_get_random, | ||
451 | .rng_reset = fips_cprng_reset, | ||
452 | .seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ, | ||
453 | } | ||
454 | } | ||
455 | }; | ||
456 | #endif | ||
407 | 457 | ||
408 | /* Module initalization */ | 458 | /* Module initalization */ |
409 | static int __init prng_mod_init(void) | 459 | static int __init prng_mod_init(void) |
410 | { | 460 | { |
411 | if (fips_enabled) | 461 | int rc = 0; |
412 | rng_alg.cra_priority += 200; | ||
413 | 462 | ||
414 | return crypto_register_alg(&rng_alg); | 463 | rc = crypto_register_alg(&rng_alg); |
464 | #ifdef CONFIG_CRYPTO_FIPS | ||
465 | if (rc) | ||
466 | goto out; | ||
467 | |||
468 | rc = crypto_register_alg(&fips_rng_alg); | ||
469 | |||
470 | out: | ||
471 | #endif | ||
472 | return rc; | ||
415 | } | 473 | } |
416 | 474 | ||
417 | static void __exit prng_mod_fini(void) | 475 | static void __exit prng_mod_fini(void) |
418 | { | 476 | { |
419 | crypto_unregister_alg(&rng_alg); | 477 | crypto_unregister_alg(&rng_alg); |
478 | #ifdef CONFIG_CRYPTO_FIPS | ||
479 | crypto_unregister_alg(&fips_rng_alg); | ||
480 | #endif | ||
420 | return; | 481 | return; |
421 | } | 482 | } |
422 | 483 | ||