diff options
Diffstat (limited to 'crypto/ansi_cprng.c')
| -rw-r--r-- | crypto/ansi_cprng.c | 35 |
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) { |
| 229 | empty_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 | */ | ||
| 352 | static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | 363 | static 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 | }; |
