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.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 72db0fd763cc..0fac8ffc2fb7 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -161,7 +161,7 @@ static int _get_more_prng_bytes(struct prng_context *ctx)
161 /* 161 /*
162 * Now update our DT value 162 * Now update our DT value
163 */ 163 */
164 for (i = 0; i < DEFAULT_BLK_SZ; i++) { 164 for (i = DEFAULT_BLK_SZ - 1; i >= 0; i--) {
165 ctx->DT[i] += 1; 165 ctx->DT[i] += 1;
166 if (ctx->DT[i] != 0) 166 if (ctx->DT[i] != 0)
167 break; 167 break;
@@ -223,9 +223,10 @@ remainder:
223 } 223 }
224 224
225 /* 225 /*
226 * Copy up to the next whole block size 226 * Copy any data less than an entire block
227 */ 227 */
228 if (byte_count < DEFAULT_BLK_SZ) { 228 if (byte_count < DEFAULT_BLK_SZ) {
229empty_rbuf:
229 for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; 230 for (; ctx->rand_data_valid < DEFAULT_BLK_SZ;
230 ctx->rand_data_valid++) { 231 ctx->rand_data_valid++) {
231 *ptr = ctx->rand_data[ctx->rand_data_valid]; 232 *ptr = ctx->rand_data[ctx->rand_data_valid];
@@ -240,18 +241,22 @@ remainder:
240 * Now copy whole blocks 241 * Now copy whole blocks
241 */ 242 */
242 for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { 243 for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) {
243 if (_get_more_prng_bytes(ctx) < 0) { 244 if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
244 memset(buf, 0, nbytes); 245 if (_get_more_prng_bytes(ctx) < 0) {
245 err = -EINVAL; 246 memset(buf, 0, nbytes);
246 goto done; 247 err = -EINVAL;
248 goto done;
249 }
247 } 250 }
251 if (ctx->rand_data_valid > 0)
252 goto empty_rbuf;
248 memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ); 253 memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
249 ctx->rand_data_valid += DEFAULT_BLK_SZ; 254 ctx->rand_data_valid += DEFAULT_BLK_SZ;
250 ptr += DEFAULT_BLK_SZ; 255 ptr += DEFAULT_BLK_SZ;
251 } 256 }
252 257
253 /* 258 /*
254 * Now copy any extra partial data 259 * Now go back and get any remaining partial block
255 */ 260 */
256 if (byte_count) 261 if (byte_count)
257 goto remainder; 262 goto remainder;
@@ -349,15 +354,25 @@ static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata,
349 return get_prng_bytes(rdata, dlen, prng); 354 return get_prng_bytes(rdata, dlen, prng);
350} 355}
351 356
357/*
358 * This is the cprng_registered reset method the seed value is
359 * interpreted as the tuple { V KEY DT}
360 * V and KEY are required during reset, and DT is optional, detected
361 * as being present by testing the length of the seed
362 */
352static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) 363static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
353{ 364{
354 struct prng_context *prng = crypto_rng_ctx(tfm); 365 struct prng_context *prng = crypto_rng_ctx(tfm);
355 u8 *key = seed + DEFAULT_PRNG_KSZ; 366 u8 *key = seed + DEFAULT_BLK_SZ;
367 u8 *dt = NULL;
356 368
357 if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ) 369 if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
358 return -EINVAL; 370 return -EINVAL;
359 371
360 reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, NULL); 372 if (slen >= (2 * DEFAULT_BLK_SZ + DEFAULT_PRNG_KSZ))
373 dt = key + DEFAULT_PRNG_KSZ;
374
375 reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, dt);
361 376
362 if (prng->flags & PRNG_NEED_RESET) 377 if (prng->flags & PRNG_NEED_RESET)
363 return -EINVAL; 378 return -EINVAL;
@@ -379,7 +394,7 @@ static struct crypto_alg rng_alg = {
379 .rng = { 394 .rng = {
380 .rng_make_random = cprng_get_random, 395 .rng_make_random = cprng_get_random,
381 .rng_reset = cprng_reset, 396 .rng_reset = cprng_reset,
382 .seedsize = DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ, 397 .seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ,
383 } 398 }
384 } 399 }
385}; 400};