Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/crypto/ansi_cprng.c
26131 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* PRNG: Pseudo Random Number Generator
4
* Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using
5
* AES 128 cipher
6
*
7
* (C) Neil Horman <[email protected]>
8
*/
9
10
#include <crypto/internal/cipher.h>
11
#include <crypto/internal/rng.h>
12
#include <linux/err.h>
13
#include <linux/init.h>
14
#include <linux/module.h>
15
#include <linux/moduleparam.h>
16
#include <linux/string.h>
17
18
#define DEFAULT_PRNG_KEY "0123456789abcdef"
19
#define DEFAULT_PRNG_KSZ 16
20
#define DEFAULT_BLK_SZ 16
21
#define DEFAULT_V_SEED "zaybxcwdveuftgsh"
22
23
/*
24
* Flags for the prng_context flags field
25
*/
26
27
#define PRNG_FIXED_SIZE 0x1
28
#define PRNG_NEED_RESET 0x2
29
30
/*
31
* Note: DT is our counter value
32
* I is our intermediate value
33
* V is our seed vector
34
* See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
35
* for implementation details
36
*/
37
38
39
struct prng_context {
40
spinlock_t prng_lock;
41
unsigned char rand_data[DEFAULT_BLK_SZ];
42
unsigned char last_rand_data[DEFAULT_BLK_SZ];
43
unsigned char DT[DEFAULT_BLK_SZ];
44
unsigned char I[DEFAULT_BLK_SZ];
45
unsigned char V[DEFAULT_BLK_SZ];
46
u32 rand_data_valid;
47
struct crypto_cipher *tfm;
48
u32 flags;
49
};
50
51
static int dbg;
52
53
static void hexdump(char *note, unsigned char *buf, unsigned int len)
54
{
55
if (dbg) {
56
printk(KERN_CRIT "%s", note);
57
print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
58
16, 1,
59
buf, len, false);
60
}
61
}
62
63
#define dbgprint(format, args...) do {\
64
if (dbg)\
65
printk(format, ##args);\
66
} while (0)
67
68
static void xor_vectors(unsigned char *in1, unsigned char *in2,
69
unsigned char *out, unsigned int size)
70
{
71
int i;
72
73
for (i = 0; i < size; i++)
74
out[i] = in1[i] ^ in2[i];
75
76
}
77
/*
78
* Returns DEFAULT_BLK_SZ bytes of random data per call
79
* returns 0 if generation succeeded, <0 if something went wrong
80
*/
81
static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test)
82
{
83
int i;
84
unsigned char tmp[DEFAULT_BLK_SZ];
85
unsigned char *output = NULL;
86
87
88
dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n",
89
ctx);
90
91
hexdump("Input DT: ", ctx->DT, DEFAULT_BLK_SZ);
92
hexdump("Input I: ", ctx->I, DEFAULT_BLK_SZ);
93
hexdump("Input V: ", ctx->V, DEFAULT_BLK_SZ);
94
95
/*
96
* This algorithm is a 3 stage state machine
97
*/
98
for (i = 0; i < 3; i++) {
99
100
switch (i) {
101
case 0:
102
/*
103
* Start by encrypting the counter value
104
* This gives us an intermediate value I
105
*/
106
memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ);
107
output = ctx->I;
108
hexdump("tmp stage 0: ", tmp, DEFAULT_BLK_SZ);
109
break;
110
case 1:
111
112
/*
113
* Next xor I with our secret vector V
114
* encrypt that result to obtain our
115
* pseudo random data which we output
116
*/
117
xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ);
118
hexdump("tmp stage 1: ", tmp, DEFAULT_BLK_SZ);
119
output = ctx->rand_data;
120
break;
121
case 2:
122
/*
123
* First check that we didn't produce the same
124
* random data that we did last time around through this
125
*/
126
if (!memcmp(ctx->rand_data, ctx->last_rand_data,
127
DEFAULT_BLK_SZ)) {
128
if (cont_test) {
129
panic("cprng %p Failed repetition check!\n",
130
ctx);
131
}
132
133
printk(KERN_ERR
134
"ctx %p Failed repetition check!\n",
135
ctx);
136
137
ctx->flags |= PRNG_NEED_RESET;
138
return -EINVAL;
139
}
140
memcpy(ctx->last_rand_data, ctx->rand_data,
141
DEFAULT_BLK_SZ);
142
143
/*
144
* Lastly xor the random data with I
145
* and encrypt that to obtain a new secret vector V
146
*/
147
xor_vectors(ctx->rand_data, ctx->I, tmp,
148
DEFAULT_BLK_SZ);
149
output = ctx->V;
150
hexdump("tmp stage 2: ", tmp, DEFAULT_BLK_SZ);
151
break;
152
}
153
154
155
/* do the encryption */
156
crypto_cipher_encrypt_one(ctx->tfm, output, tmp);
157
158
}
159
160
/*
161
* Now update our DT value
162
*/
163
for (i = DEFAULT_BLK_SZ - 1; i >= 0; i--) {
164
ctx->DT[i] += 1;
165
if (ctx->DT[i] != 0)
166
break;
167
}
168
169
dbgprint("Returning new block for context %p\n", ctx);
170
ctx->rand_data_valid = 0;
171
172
hexdump("Output DT: ", ctx->DT, DEFAULT_BLK_SZ);
173
hexdump("Output I: ", ctx->I, DEFAULT_BLK_SZ);
174
hexdump("Output V: ", ctx->V, DEFAULT_BLK_SZ);
175
hexdump("New Random Data: ", ctx->rand_data, DEFAULT_BLK_SZ);
176
177
return 0;
178
}
179
180
/* Our exported functions */
181
static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx,
182
int do_cont_test)
183
{
184
unsigned char *ptr = buf;
185
unsigned int byte_count = (unsigned int)nbytes;
186
int err;
187
188
189
spin_lock_bh(&ctx->prng_lock);
190
191
err = -EINVAL;
192
if (ctx->flags & PRNG_NEED_RESET)
193
goto done;
194
195
/*
196
* If the FIXED_SIZE flag is on, only return whole blocks of
197
* pseudo random data
198
*/
199
err = -EINVAL;
200
if (ctx->flags & PRNG_FIXED_SIZE) {
201
if (nbytes < DEFAULT_BLK_SZ)
202
goto done;
203
byte_count = DEFAULT_BLK_SZ;
204
}
205
206
/*
207
* Return 0 in case of success as mandated by the kernel
208
* crypto API interface definition.
209
*/
210
err = 0;
211
212
dbgprint(KERN_CRIT "getting %d random bytes for context %p\n",
213
byte_count, ctx);
214
215
216
remainder:
217
if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
218
if (_get_more_prng_bytes(ctx, do_cont_test) < 0) {
219
memset(buf, 0, nbytes);
220
err = -EINVAL;
221
goto done;
222
}
223
}
224
225
/*
226
* Copy any data less than an entire block
227
*/
228
if (byte_count < DEFAULT_BLK_SZ) {
229
empty_rbuf:
230
while (ctx->rand_data_valid < DEFAULT_BLK_SZ) {
231
*ptr = ctx->rand_data[ctx->rand_data_valid];
232
ptr++;
233
byte_count--;
234
ctx->rand_data_valid++;
235
if (byte_count == 0)
236
goto done;
237
}
238
}
239
240
/*
241
* Now copy whole blocks
242
*/
243
for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) {
244
if (ctx->rand_data_valid == DEFAULT_BLK_SZ) {
245
if (_get_more_prng_bytes(ctx, do_cont_test) < 0) {
246
memset(buf, 0, nbytes);
247
err = -EINVAL;
248
goto done;
249
}
250
}
251
if (ctx->rand_data_valid > 0)
252
goto empty_rbuf;
253
memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ);
254
ctx->rand_data_valid += DEFAULT_BLK_SZ;
255
ptr += DEFAULT_BLK_SZ;
256
}
257
258
/*
259
* Now go back and get any remaining partial block
260
*/
261
if (byte_count)
262
goto remainder;
263
264
done:
265
spin_unlock_bh(&ctx->prng_lock);
266
dbgprint(KERN_CRIT "returning %d from get_prng_bytes in context %p\n",
267
err, ctx);
268
return err;
269
}
270
271
static void free_prng_context(struct prng_context *ctx)
272
{
273
crypto_free_cipher(ctx->tfm);
274
}
275
276
static int reset_prng_context(struct prng_context *ctx,
277
const unsigned char *key, size_t klen,
278
const unsigned char *V, const unsigned char *DT)
279
{
280
int ret;
281
const unsigned char *prng_key;
282
283
spin_lock_bh(&ctx->prng_lock);
284
ctx->flags |= PRNG_NEED_RESET;
285
286
prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY;
287
288
if (!key)
289
klen = DEFAULT_PRNG_KSZ;
290
291
if (V)
292
memcpy(ctx->V, V, DEFAULT_BLK_SZ);
293
else
294
memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ);
295
296
if (DT)
297
memcpy(ctx->DT, DT, DEFAULT_BLK_SZ);
298
else
299
memset(ctx->DT, 0, DEFAULT_BLK_SZ);
300
301
memset(ctx->rand_data, 0, DEFAULT_BLK_SZ);
302
memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ);
303
304
ctx->rand_data_valid = DEFAULT_BLK_SZ;
305
306
ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen);
307
if (ret) {
308
dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n",
309
crypto_cipher_get_flags(ctx->tfm));
310
goto out;
311
}
312
313
ret = 0;
314
ctx->flags &= ~PRNG_NEED_RESET;
315
out:
316
spin_unlock_bh(&ctx->prng_lock);
317
return ret;
318
}
319
320
static int cprng_init(struct crypto_tfm *tfm)
321
{
322
struct prng_context *ctx = crypto_tfm_ctx(tfm);
323
324
spin_lock_init(&ctx->prng_lock);
325
ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
326
if (IS_ERR(ctx->tfm)) {
327
dbgprint(KERN_CRIT "Failed to alloc tfm for context %p\n",
328
ctx);
329
return PTR_ERR(ctx->tfm);
330
}
331
332
if (reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL) < 0)
333
return -EINVAL;
334
335
/*
336
* after allocation, we should always force the user to reset
337
* so they don't inadvertently use the insecure default values
338
* without specifying them intentially
339
*/
340
ctx->flags |= PRNG_NEED_RESET;
341
return 0;
342
}
343
344
static void cprng_exit(struct crypto_tfm *tfm)
345
{
346
free_prng_context(crypto_tfm_ctx(tfm));
347
}
348
349
static int cprng_get_random(struct crypto_rng *tfm,
350
const u8 *src, unsigned int slen,
351
u8 *rdata, unsigned int dlen)
352
{
353
struct prng_context *prng = crypto_rng_ctx(tfm);
354
355
return get_prng_bytes(rdata, dlen, prng, 0);
356
}
357
358
/*
359
* This is the cprng_registered reset method the seed value is
360
* interpreted as the tuple { V KEY DT}
361
* V and KEY are required during reset, and DT is optional, detected
362
* as being present by testing the length of the seed
363
*/
364
static int cprng_reset(struct crypto_rng *tfm,
365
const u8 *seed, unsigned int slen)
366
{
367
struct prng_context *prng = crypto_rng_ctx(tfm);
368
const u8 *key = seed + DEFAULT_BLK_SZ;
369
const u8 *dt = NULL;
370
371
if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
372
return -EINVAL;
373
374
if (slen >= (2 * DEFAULT_BLK_SZ + DEFAULT_PRNG_KSZ))
375
dt = key + DEFAULT_PRNG_KSZ;
376
377
reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, dt);
378
379
if (prng->flags & PRNG_NEED_RESET)
380
return -EINVAL;
381
return 0;
382
}
383
384
#ifdef CONFIG_CRYPTO_FIPS
385
static int fips_cprng_get_random(struct crypto_rng *tfm,
386
const u8 *src, unsigned int slen,
387
u8 *rdata, unsigned int dlen)
388
{
389
struct prng_context *prng = crypto_rng_ctx(tfm);
390
391
return get_prng_bytes(rdata, dlen, prng, 1);
392
}
393
394
static int fips_cprng_reset(struct crypto_rng *tfm,
395
const u8 *seed, unsigned int slen)
396
{
397
u8 rdata[DEFAULT_BLK_SZ];
398
const u8 *key = seed + DEFAULT_BLK_SZ;
399
int rc;
400
401
struct prng_context *prng = crypto_rng_ctx(tfm);
402
403
if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ)
404
return -EINVAL;
405
406
/* fips strictly requires seed != key */
407
if (!memcmp(seed, key, DEFAULT_PRNG_KSZ))
408
return -EINVAL;
409
410
rc = cprng_reset(tfm, seed, slen);
411
412
if (!rc)
413
goto out;
414
415
/* this primes our continuity test */
416
rc = get_prng_bytes(rdata, DEFAULT_BLK_SZ, prng, 0);
417
prng->rand_data_valid = DEFAULT_BLK_SZ;
418
419
out:
420
return rc;
421
}
422
#endif
423
424
static struct rng_alg rng_algs[] = { {
425
.generate = cprng_get_random,
426
.seed = cprng_reset,
427
.seedsize = DEFAULT_PRNG_KSZ + 2 * DEFAULT_BLK_SZ,
428
.base = {
429
.cra_name = "stdrng",
430
.cra_driver_name = "ansi_cprng",
431
.cra_priority = 100,
432
.cra_ctxsize = sizeof(struct prng_context),
433
.cra_module = THIS_MODULE,
434
.cra_init = cprng_init,
435
.cra_exit = cprng_exit,
436
}
437
#ifdef CONFIG_CRYPTO_FIPS
438
}, {
439
.generate = fips_cprng_get_random,
440
.seed = fips_cprng_reset,
441
.seedsize = DEFAULT_PRNG_KSZ + 2 * DEFAULT_BLK_SZ,
442
.base = {
443
.cra_name = "fips(ansi_cprng)",
444
.cra_driver_name = "fips_ansi_cprng",
445
.cra_priority = 300,
446
.cra_ctxsize = sizeof(struct prng_context),
447
.cra_module = THIS_MODULE,
448
.cra_init = cprng_init,
449
.cra_exit = cprng_exit,
450
}
451
#endif
452
} };
453
454
/* Module initalization */
455
static int __init prng_mod_init(void)
456
{
457
return crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
458
}
459
460
static void __exit prng_mod_fini(void)
461
{
462
crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
463
}
464
465
MODULE_LICENSE("GPL");
466
MODULE_DESCRIPTION("Software Pseudo Random Number Generator");
467
MODULE_AUTHOR("Neil Horman <[email protected]>");
468
module_param(dbg, int, 0);
469
MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
470
module_init(prng_mod_init);
471
module_exit(prng_mod_fini);
472
MODULE_ALIAS_CRYPTO("stdrng");
473
MODULE_ALIAS_CRYPTO("ansi_cprng");
474
MODULE_IMPORT_NS("CRYPTO_INTERNAL");
475
476