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