aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/ansi_cprng.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/ansi_cprng.c')
-rw-r--r--crypto/ansi_cprng.c82
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 */
88static int _get_more_prng_bytes(struct prng_context *ctx) 88static 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 */
188static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) 188static 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
221remainder: 219remainder:
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
406static 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
414static 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
430out:
431 return rc;
432}
433
434static 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 */
409static int __init prng_mod_init(void) 456static 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
467out:
468#endif
469 return rc;
415} 470}
416 471
417static void __exit prng_mod_fini(void) 472static 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