diff options
Diffstat (limited to 'crypto/ansi_cprng.c')
| -rw-r--r-- | crypto/ansi_cprng.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index 3aa6e3834bfe..2bc332142849 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,16 +185,14 @@ 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; |
| 192 | int err; | 193 | int err; |
| 193 | 194 | ||
| 194 | 195 | ||
| 195 | if (nbytes < 0) | ||
| 196 | return -EINVAL; | ||
| 197 | |||
| 198 | spin_lock_bh(&ctx->prng_lock); | 196 | spin_lock_bh(&ctx->prng_lock); |
| 199 | 197 | ||
| 200 | err = -EINVAL; | 198 | err = -EINVAL; |
| @@ -220,7 +218,7 @@ static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) | |||
| 220 | 218 | ||
| 221 | remainder: | 219 | remainder: |
| 222 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { | 220 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { |
| 223 | if (_get_more_prng_bytes(ctx) < 0) { | 221 | if (_get_more_prng_bytes(ctx, do_cont_test) < 0) { |
| 224 | memset(buf, 0, nbytes); | 222 | memset(buf, 0, nbytes); |
| 225 | err = -EINVAL; | 223 | err = -EINVAL; |
| 226 | goto done; | 224 | goto done; |
| @@ -247,7 +245,7 @@ empty_rbuf: | |||
| 247 | */ | 245 | */ |
| 248 | for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { | 246 | for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { |
| 249 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { | 247 | if (ctx->rand_data_valid == DEFAULT_BLK_SZ) { |
| 250 | if (_get_more_prng_bytes(ctx) < 0) { | 248 | if (_get_more_prng_bytes(ctx, do_cont_test) < 0) { |
| 251 | memset(buf, 0, nbytes); | 249 | memset(buf, 0, nbytes); |
| 252 | err = -EINVAL; | 250 | err = -EINVAL; |
| 253 | goto done; | 251 | goto done; |
| @@ -356,7 +354,7 @@ static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata, | |||
| 356 | { | 354 | { |
| 357 | struct prng_context *prng = crypto_rng_ctx(tfm); | 355 | struct prng_context *prng = crypto_rng_ctx(tfm); |
| 358 | 356 | ||
| 359 | return get_prng_bytes(rdata, dlen, prng); | 357 | return get_prng_bytes(rdata, dlen, prng, 0); |
| 360 | } | 358 | } |
| 361 | 359 | ||
| 362 | /* | 360 | /* |
| @@ -404,19 +402,79 @@ static struct crypto_alg rng_alg = { | |||
| 404 | } | 402 | } |
| 405 | }; | 403 | }; |
| 406 | 404 | ||
| 405 | #ifdef CONFIG_CRYPTO_FIPS | ||
| 406 | static int fips_cprng_get_random(struct crypto_rng *tfm, u8 *rdata, | ||
| 407 | unsigned int dlen) | ||
| 408 | { | ||
| 409 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
| 410 | |||
| 411 | return get_prng_bytes(rdata, dlen, prng, 1); | ||
| 412 | } | ||
| 413 | |||
| 414 | static int fips_cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | ||
| 415 | { | ||
| 416 | u8 rdata[DEFAULT_BLK_SZ]; | ||
| 417 | int rc; | ||
| 418 | |||
| 419 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
| 420 | |||
| 421 | rc = cprng_reset(tfm, seed, slen); | ||
| 422 | |||
| 423 | if (!rc) | ||
| 424 | goto out; | ||
| 425 | |||
| 426 | /* this primes our continuity test */ | ||
| 427 | rc = get_prng_bytes(rdata, DEFAULT_BLK_SZ, prng, 0); | ||
| 428 | prng->rand_data_valid = DEFAULT_BLK_SZ; | ||
| 429 | |||
| 430 | out: | ||
| 431 | return rc; | ||
| 432 | } | ||
| 433 | |||
| 434 | static struct crypto_alg fips_rng_alg = { | ||
| 435 | .cra_name = "fips(ansi_cprng)", | ||
| 436 | .cra_driver_name = "fips_ansi_cprng", | ||
| 437 | .cra_priority = 300, | ||
| 438 | .cra_flags = CRYPTO_ALG_TYPE_RNG, | ||
| 439 | .cra_ctxsize = sizeof(struct prng_context), | ||
| 440 | .cra_type = &crypto_rng_type, | ||
| 441 | .cra_module = THIS_MODULE, | ||
| 442 | .cra_list = LIST_HEAD_INIT(rng_alg.cra_list), | ||
| 443 | .cra_init = cprng_init, | ||
| 444 | .cra_exit = cprng_exit, | ||
| 445 | .cra_u = { | ||
| 446 | .rng = { | ||
| 447 | .rng_make_random = fips_cprng_get_random, | ||
| 448 | .rng_reset = fips_cprng_reset, | ||
| 449 | .seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ, | ||
| 450 | } | ||
| 451 | } | ||
| 452 | }; | ||
| 453 | #endif | ||
| 407 | 454 | ||
| 408 | /* Module initalization */ | 455 | /* Module initalization */ |
| 409 | static int __init prng_mod_init(void) | 456 | static int __init prng_mod_init(void) |
| 410 | { | 457 | { |
| 411 | if (fips_enabled) | 458 | int rc = 0; |
| 412 | rng_alg.cra_priority += 200; | ||
| 413 | 459 | ||
| 414 | return crypto_register_alg(&rng_alg); | 460 | rc = crypto_register_alg(&rng_alg); |
| 461 | #ifdef CONFIG_CRYPTO_FIPS | ||
| 462 | if (rc) | ||
| 463 | goto out; | ||
| 464 | |||
| 465 | rc = crypto_register_alg(&fips_rng_alg); | ||
| 466 | |||
| 467 | out: | ||
| 468 | #endif | ||
| 469 | return rc; | ||
| 415 | } | 470 | } |
| 416 | 471 | ||
| 417 | static void __exit prng_mod_fini(void) | 472 | static void __exit prng_mod_fini(void) |
| 418 | { | 473 | { |
| 419 | crypto_unregister_alg(&rng_alg); | 474 | crypto_unregister_alg(&rng_alg); |
| 475 | #ifdef CONFIG_CRYPTO_FIPS | ||
| 476 | crypto_unregister_alg(&fips_rng_alg); | ||
| 477 | #endif | ||
| 420 | return; | 478 | return; |
| 421 | } | 479 | } |
| 422 | 480 | ||
