*/
if (!memcmp(ctx->rand_data, ctx->last_rand_data,
DEFAULT_BLK_SZ)) {
+ if (fips_enabled) {
+ panic("cprng %p Failed repetition check!\n",
+ ctx);
+ }
+
printk(KERN_ERR
"ctx %p Failed repetition check!\n",
ctx);
+
ctx->flags |= PRNG_NEED_RESET;
return -EINVAL;
}
/*
* Now update our DT value
*/
- for (i = 0; i < DEFAULT_BLK_SZ; i++) {
+ for (i = DEFAULT_BLK_SZ - 1; i >= 0; i--) {
ctx->DT[i] += 1;
if (ctx->DT[i] != 0)
break;
}
/*
- * Copy up to the next whole block size
+ * Copy any data less than an entire block
*/
if (byte_count < DEFAULT_BLK_SZ) {
+empty_rbuf:
for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
ctx->rand_data_valid++) {
*ptr = ctx->rand_data[ctx->rand_data_valid];
* Now copy whole blocks
*/
for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) {
- if (_get_more_prng_bytes(ctx) < 0) {
- memset(buf, 0, nbytes);
- err = -EINVAL;
- goto done;
+ if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
+ if (_get_more_prng_bytes(ctx) < 0) {
+ memset(buf, 0, nbytes);
+ err = -EINVAL;
+ goto done;
+ }
}
+ if (ctx->rand_data_valid > 0)
+ goto empty_rbuf;
memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
ctx->rand_data_valid += DEFAULT_BLK_SZ;
ptr += DEFAULT_BLK_SZ;
}
/*
- * Now copy any extra partial data
+ * Now go back and get any remaining partial block
*/
if (byte_count)
goto remainder;
spin_lock_init(&ctx->prng_lock);
- return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL);
+ if (reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL) < 0)
+ return -EINVAL;
+
+ /*
+ * after allocation, we should always force the user to reset
+ * so they don't inadvertently use the insecure default values
+ * without specifying them intentially
+ */
+ ctx->flags |= PRNG_NEED_RESET;
+ return 0;
}
static void cprng_exit(struct crypto_tfm *tfm)