diff options
| -rw-r--r-- | crypto/Kconfig | 16 | ||||
| -rw-r--r-- | crypto/Makefile | 4 | ||||
| -rw-r--r-- | crypto/ansi_cprng.c | 417 | ||||
| -rw-r--r-- | crypto/krng.c | 66 | ||||
| -rw-r--r-- | crypto/rng.c | 126 | ||||
| -rw-r--r-- | include/crypto/internal/rng.h | 26 | ||||
| -rw-r--r-- | include/crypto/rng.h | 75 | ||||
| -rw-r--r-- | include/linux/crypto.h | 25 |
8 files changed, 754 insertions, 1 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index a784c2dce57e..2274293e71e1 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
| @@ -46,6 +46,10 @@ config CRYPTO_HASH | |||
| 46 | tristate | 46 | tristate |
| 47 | select CRYPTO_ALGAPI | 47 | select CRYPTO_ALGAPI |
| 48 | 48 | ||
| 49 | config CRYPTO_RNG | ||
| 50 | tristate | ||
| 51 | select CRYPTO_ALGAPI | ||
| 52 | |||
| 49 | config CRYPTO_MANAGER | 53 | config CRYPTO_MANAGER |
| 50 | tristate "Cryptographic algorithm manager" | 54 | tristate "Cryptographic algorithm manager" |
| 51 | select CRYPTO_AEAD | 55 | select CRYPTO_AEAD |
| @@ -689,6 +693,18 @@ config CRYPTO_LZO | |||
| 689 | help | 693 | help |
| 690 | This is the LZO algorithm. | 694 | This is the LZO algorithm. |
| 691 | 695 | ||
| 696 | comment "Random Number Generation" | ||
| 697 | |||
| 698 | config CRYPTO_ANSI_CPRNG | ||
| 699 | tristate "Pseudo Random Number Generation for Cryptographic modules" | ||
| 700 | select CRYPTO_AES | ||
| 701 | select CRYPTO_RNG | ||
| 702 | select CRYPTO_FIPS | ||
| 703 | help | ||
| 704 | This option enables the generic pseudo random number generator | ||
| 705 | for cryptographic modules. Uses the Algorithm specified in | ||
| 706 | ANSI X9.31 A.2.4 | ||
| 707 | |||
| 692 | source "drivers/crypto/Kconfig" | 708 | source "drivers/crypto/Kconfig" |
| 693 | 709 | ||
| 694 | endif # if CRYPTO | 710 | endif # if CRYPTO |
diff --git a/crypto/Makefile b/crypto/Makefile index 8a27b834ea76..5862b807334e 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
| @@ -73,7 +73,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o | |||
| 73 | obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o | 73 | obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o |
| 74 | obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o | 74 | obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o |
| 75 | obj-$(CONFIG_CRYPTO_LZO) += lzo.o | 75 | obj-$(CONFIG_CRYPTO_LZO) += lzo.o |
| 76 | 76 | obj-$(CONFIG_CRYPTO_RNG) += rng.o | |
| 77 | obj-$(CONFIG_CRYPTO_RNG) += krng.o | ||
| 78 | obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o | ||
| 77 | obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o | 79 | obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o |
| 78 | 80 | ||
| 79 | # | 81 | # |
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c new file mode 100644 index 000000000000..72db0fd763cc --- /dev/null +++ b/crypto/ansi_cprng.c | |||
| @@ -0,0 +1,417 @@ | |||
| 1 | /* | ||
| 2 | * PRNG: Pseudo Random Number Generator | ||
| 3 | * Based on NIST Recommended PRNG From ANSI X9.31 Appendix A.2.4 using | ||
| 4 | * AES 128 cipher | ||
| 5 | * | ||
| 6 | * (C) Neil Horman <nhorman@tuxdriver.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * any later version. | ||
| 12 | * | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <crypto/internal/rng.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/moduleparam.h> | ||
| 21 | #include <linux/string.h> | ||
| 22 | |||
| 23 | #include "internal.h" | ||
| 24 | |||
| 25 | #define DEFAULT_PRNG_KEY "0123456789abcdef" | ||
| 26 | #define DEFAULT_PRNG_KSZ 16 | ||
| 27 | #define DEFAULT_BLK_SZ 16 | ||
| 28 | #define DEFAULT_V_SEED "zaybxcwdveuftgsh" | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Flags for the prng_context flags field | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define PRNG_FIXED_SIZE 0x1 | ||
| 35 | #define PRNG_NEED_RESET 0x2 | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Note: DT is our counter value | ||
| 39 | * I is our intermediate value | ||
| 40 | * V is our seed vector | ||
| 41 | * See http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf | ||
| 42 | * for implementation details | ||
| 43 | */ | ||
| 44 | |||
| 45 | |||
| 46 | struct prng_context { | ||
| 47 | spinlock_t prng_lock; | ||
| 48 | unsigned char rand_data[DEFAULT_BLK_SZ]; | ||
| 49 | unsigned char last_rand_data[DEFAULT_BLK_SZ]; | ||
| 50 | unsigned char DT[DEFAULT_BLK_SZ]; | ||
| 51 | unsigned char I[DEFAULT_BLK_SZ]; | ||
| 52 | unsigned char V[DEFAULT_BLK_SZ]; | ||
| 53 | u32 rand_data_valid; | ||
| 54 | struct crypto_cipher *tfm; | ||
| 55 | u32 flags; | ||
| 56 | }; | ||
| 57 | |||
| 58 | static int dbg; | ||
| 59 | |||
| 60 | static void hexdump(char *note, unsigned char *buf, unsigned int len) | ||
| 61 | { | ||
| 62 | if (dbg) { | ||
| 63 | printk(KERN_CRIT "%s", note); | ||
| 64 | print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, | ||
| 65 | 16, 1, | ||
| 66 | buf, len, false); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | #define dbgprint(format, args...) do {\ | ||
| 71 | if (dbg)\ | ||
| 72 | printk(format, ##args);\ | ||
| 73 | } while (0) | ||
| 74 | |||
| 75 | static void xor_vectors(unsigned char *in1, unsigned char *in2, | ||
| 76 | unsigned char *out, unsigned int size) | ||
| 77 | { | ||
| 78 | int i; | ||
| 79 | |||
| 80 | for (i = 0; i < size; i++) | ||
| 81 | out[i] = in1[i] ^ in2[i]; | ||
| 82 | |||
| 83 | } | ||
| 84 | /* | ||
| 85 | * Returns DEFAULT_BLK_SZ bytes of random data per call | ||
| 86 | * returns 0 if generation succeded, <0 if something went wrong | ||
| 87 | */ | ||
| 88 | static int _get_more_prng_bytes(struct prng_context *ctx) | ||
| 89 | { | ||
| 90 | int i; | ||
| 91 | unsigned char tmp[DEFAULT_BLK_SZ]; | ||
| 92 | unsigned char *output = NULL; | ||
| 93 | |||
| 94 | |||
| 95 | dbgprint(KERN_CRIT "Calling _get_more_prng_bytes for context %p\n", | ||
| 96 | ctx); | ||
| 97 | |||
| 98 | hexdump("Input DT: ", ctx->DT, DEFAULT_BLK_SZ); | ||
| 99 | hexdump("Input I: ", ctx->I, DEFAULT_BLK_SZ); | ||
| 100 | hexdump("Input V: ", ctx->V, DEFAULT_BLK_SZ); | ||
| 101 | |||
| 102 | /* | ||
| 103 | * This algorithm is a 3 stage state machine | ||
| 104 | */ | ||
| 105 | for (i = 0; i < 3; i++) { | ||
| 106 | |||
| 107 | switch (i) { | ||
| 108 | case 0: | ||
| 109 | /* | ||
| 110 | * Start by encrypting the counter value | ||
| 111 | * This gives us an intermediate value I | ||
| 112 | */ | ||
| 113 | memcpy(tmp, ctx->DT, DEFAULT_BLK_SZ); | ||
| 114 | output = ctx->I; | ||
| 115 | hexdump("tmp stage 0: ", tmp, DEFAULT_BLK_SZ); | ||
| 116 | break; | ||
| 117 | case 1: | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Next xor I with our secret vector V | ||
| 121 | * encrypt that result to obtain our | ||
| 122 | * pseudo random data which we output | ||
| 123 | */ | ||
| 124 | xor_vectors(ctx->I, ctx->V, tmp, DEFAULT_BLK_SZ); | ||
| 125 | hexdump("tmp stage 1: ", tmp, DEFAULT_BLK_SZ); | ||
| 126 | output = ctx->rand_data; | ||
| 127 | break; | ||
| 128 | case 2: | ||
| 129 | /* | ||
| 130 | * First check that we didn't produce the same | ||
| 131 | * random data that we did last time around through this | ||
| 132 | */ | ||
| 133 | if (!memcmp(ctx->rand_data, ctx->last_rand_data, | ||
| 134 | DEFAULT_BLK_SZ)) { | ||
| 135 | printk(KERN_ERR | ||
| 136 | "ctx %p Failed repetition check!\n", | ||
| 137 | ctx); | ||
| 138 | ctx->flags |= PRNG_NEED_RESET; | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | memcpy(ctx->last_rand_data, ctx->rand_data, | ||
| 142 | DEFAULT_BLK_SZ); | ||
| 143 | |||
| 144 | /* | ||
| 145 | * Lastly xor the random data with I | ||
| 146 | * and encrypt that to obtain a new secret vector V | ||
| 147 | */ | ||
| 148 | xor_vectors(ctx->rand_data, ctx->I, tmp, | ||
| 149 | DEFAULT_BLK_SZ); | ||
| 150 | output = ctx->V; | ||
| 151 | hexdump("tmp stage 2: ", tmp, DEFAULT_BLK_SZ); | ||
| 152 | break; | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | /* do the encryption */ | ||
| 157 | crypto_cipher_encrypt_one(ctx->tfm, output, tmp); | ||
| 158 | |||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * Now update our DT value | ||
| 163 | */ | ||
| 164 | for (i = 0; i < DEFAULT_BLK_SZ; i++) { | ||
| 165 | ctx->DT[i] += 1; | ||
| 166 | if (ctx->DT[i] != 0) | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | |||
| 170 | dbgprint("Returning new block for context %p\n", ctx); | ||
| 171 | ctx->rand_data_valid = 0; | ||
| 172 | |||
| 173 | hexdump("Output DT: ", ctx->DT, DEFAULT_BLK_SZ); | ||
| 174 | hexdump("Output I: ", ctx->I, DEFAULT_BLK_SZ); | ||
| 175 | hexdump("Output V: ", ctx->V, DEFAULT_BLK_SZ); | ||
| 176 | hexdump("New Random Data: ", ctx->rand_data, DEFAULT_BLK_SZ); | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* Our exported functions */ | ||
| 182 | static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx) | ||
| 183 | { | ||
| 184 | unsigned long flags; | ||
| 185 | unsigned char *ptr = buf; | ||
| 186 | unsigned int byte_count = (unsigned int)nbytes; | ||
| 187 | int err; | ||
| 188 | |||
| 189 | |||
| 190 | if (nbytes < 0) | ||
| 191 | return -EINVAL; | ||
| 192 | |||
| 193 | spin_lock_irqsave(&ctx->prng_lock, flags); | ||
| 194 | |||
| 195 | err = -EINVAL; | ||
| 196 | if (ctx->flags & PRNG_NEED_RESET) | ||
| 197 | goto done; | ||
| 198 | |||
| 199 | /* | ||
| 200 | * If the FIXED_SIZE flag is on, only return whole blocks of | ||
| 201 | * pseudo random data | ||
| 202 | */ | ||
| 203 | err = -EINVAL; | ||
| 204 | if (ctx->flags & PRNG_FIXED_SIZE) { | ||
| 205 | if (nbytes < DEFAULT_BLK_SZ) | ||
| 206 | goto done; | ||
| 207 | byte_count = DEFAULT_BLK_SZ; | ||
| 208 | } | ||
| 209 | |||
| 210 | err = byte_count; | ||
| 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) < 0) { | ||
| 219 | memset(buf, 0, nbytes); | ||
| 220 | err = -EINVAL; | ||
| 221 | goto done; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Copy up to the next whole block size | ||
| 227 | */ | ||
| 228 | if (byte_count < DEFAULT_BLK_SZ) { | ||
| 229 | for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; | ||
| 230 | ctx->rand_data_valid++) { | ||
| 231 | *ptr = ctx->rand_data[ctx->rand_data_valid]; | ||
| 232 | ptr++; | ||
| 233 | byte_count--; | ||
| 234 | if (byte_count == 0) | ||
| 235 | goto done; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Now copy whole blocks | ||
| 241 | */ | ||
| 242 | for (; byte_count >= DEFAULT_BLK_SZ; byte_count -= DEFAULT_BLK_SZ) { | ||
| 243 | if (_get_more_prng_bytes(ctx) < 0) { | ||
| 244 | memset(buf, 0, nbytes); | ||
| 245 | err = -EINVAL; | ||
| 246 | goto done; | ||
| 247 | } | ||
| 248 | memcpy(ptr, ctx->rand_data, DEFAULT_BLK_SZ); | ||
| 249 | ctx->rand_data_valid += DEFAULT_BLK_SZ; | ||
| 250 | ptr += DEFAULT_BLK_SZ; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * Now copy any extra partial data | ||
| 255 | */ | ||
| 256 | if (byte_count) | ||
| 257 | goto remainder; | ||
| 258 | |||
| 259 | done: | ||
| 260 | spin_unlock_irqrestore(&ctx->prng_lock, flags); | ||
| 261 | dbgprint(KERN_CRIT "returning %d from get_prng_bytes in context %p\n", | ||
| 262 | err, ctx); | ||
| 263 | return err; | ||
| 264 | } | ||
| 265 | |||
| 266 | static void free_prng_context(struct prng_context *ctx) | ||
| 267 | { | ||
| 268 | crypto_free_cipher(ctx->tfm); | ||
| 269 | } | ||
| 270 | |||
| 271 | static int reset_prng_context(struct prng_context *ctx, | ||
| 272 | unsigned char *key, size_t klen, | ||
| 273 | unsigned char *V, unsigned char *DT) | ||
| 274 | { | ||
| 275 | int ret; | ||
| 276 | int rc = -EINVAL; | ||
| 277 | unsigned char *prng_key; | ||
| 278 | |||
| 279 | spin_lock(&ctx->prng_lock); | ||
| 280 | ctx->flags |= PRNG_NEED_RESET; | ||
| 281 | |||
| 282 | prng_key = (key != NULL) ? key : (unsigned char *)DEFAULT_PRNG_KEY; | ||
| 283 | |||
| 284 | if (!key) | ||
| 285 | klen = DEFAULT_PRNG_KSZ; | ||
| 286 | |||
| 287 | if (V) | ||
| 288 | memcpy(ctx->V, V, DEFAULT_BLK_SZ); | ||
| 289 | else | ||
| 290 | memcpy(ctx->V, DEFAULT_V_SEED, DEFAULT_BLK_SZ); | ||
| 291 | |||
| 292 | if (DT) | ||
| 293 | memcpy(ctx->DT, DT, DEFAULT_BLK_SZ); | ||
| 294 | else | ||
| 295 | memset(ctx->DT, 0, DEFAULT_BLK_SZ); | ||
| 296 | |||
| 297 | memset(ctx->rand_data, 0, DEFAULT_BLK_SZ); | ||
| 298 | memset(ctx->last_rand_data, 0, DEFAULT_BLK_SZ); | ||
| 299 | |||
| 300 | if (ctx->tfm) | ||
| 301 | crypto_free_cipher(ctx->tfm); | ||
| 302 | |||
| 303 | ctx->tfm = crypto_alloc_cipher("aes", 0, 0); | ||
| 304 | if (IS_ERR(ctx->tfm)) { | ||
| 305 | dbgprint(KERN_CRIT "Failed to alloc tfm for context %p\n", | ||
| 306 | ctx); | ||
| 307 | ctx->tfm = NULL; | ||
| 308 | goto out; | ||
| 309 | } | ||
| 310 | |||
| 311 | ctx->rand_data_valid = DEFAULT_BLK_SZ; | ||
| 312 | |||
| 313 | ret = crypto_cipher_setkey(ctx->tfm, prng_key, klen); | ||
| 314 | if (ret) { | ||
| 315 | dbgprint(KERN_CRIT "PRNG: setkey() failed flags=%x\n", | ||
| 316 | crypto_cipher_get_flags(ctx->tfm)); | ||
| 317 | crypto_free_cipher(ctx->tfm); | ||
| 318 | goto out; | ||
| 319 | } | ||
| 320 | |||
| 321 | rc = 0; | ||
| 322 | ctx->flags &= ~PRNG_NEED_RESET; | ||
| 323 | out: | ||
| 324 | spin_unlock(&ctx->prng_lock); | ||
| 325 | |||
| 326 | return rc; | ||
| 327 | |||
| 328 | } | ||
| 329 | |||
| 330 | static int cprng_init(struct crypto_tfm *tfm) | ||
| 331 | { | ||
| 332 | struct prng_context *ctx = crypto_tfm_ctx(tfm); | ||
| 333 | |||
| 334 | spin_lock_init(&ctx->prng_lock); | ||
| 335 | |||
| 336 | return reset_prng_context(ctx, NULL, DEFAULT_PRNG_KSZ, NULL, NULL); | ||
| 337 | } | ||
| 338 | |||
| 339 | static void cprng_exit(struct crypto_tfm *tfm) | ||
| 340 | { | ||
| 341 | free_prng_context(crypto_tfm_ctx(tfm)); | ||
| 342 | } | ||
| 343 | |||
| 344 | static int cprng_get_random(struct crypto_rng *tfm, u8 *rdata, | ||
| 345 | unsigned int dlen) | ||
| 346 | { | ||
| 347 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
| 348 | |||
| 349 | return get_prng_bytes(rdata, dlen, prng); | ||
| 350 | } | ||
| 351 | |||
| 352 | static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | ||
| 353 | { | ||
| 354 | struct prng_context *prng = crypto_rng_ctx(tfm); | ||
| 355 | u8 *key = seed + DEFAULT_PRNG_KSZ; | ||
| 356 | |||
| 357 | if (slen < DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ) | ||
| 358 | return -EINVAL; | ||
| 359 | |||
| 360 | reset_prng_context(prng, key, DEFAULT_PRNG_KSZ, seed, NULL); | ||
| 361 | |||
| 362 | if (prng->flags & PRNG_NEED_RESET) | ||
| 363 | return -EINVAL; | ||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | |||
| 367 | static struct crypto_alg rng_alg = { | ||
| 368 | .cra_name = "stdrng", | ||
| 369 | .cra_driver_name = "ansi_cprng", | ||
| 370 | .cra_priority = 100, | ||
| 371 | .cra_flags = CRYPTO_ALG_TYPE_RNG, | ||
| 372 | .cra_ctxsize = sizeof(struct prng_context), | ||
| 373 | .cra_type = &crypto_rng_type, | ||
| 374 | .cra_module = THIS_MODULE, | ||
| 375 | .cra_list = LIST_HEAD_INIT(rng_alg.cra_list), | ||
| 376 | .cra_init = cprng_init, | ||
| 377 | .cra_exit = cprng_exit, | ||
| 378 | .cra_u = { | ||
| 379 | .rng = { | ||
| 380 | .rng_make_random = cprng_get_random, | ||
| 381 | .rng_reset = cprng_reset, | ||
| 382 | .seedsize = DEFAULT_PRNG_KSZ + DEFAULT_BLK_SZ, | ||
| 383 | } | ||
| 384 | } | ||
| 385 | }; | ||
| 386 | |||
| 387 | |||
| 388 | /* Module initalization */ | ||
| 389 | static int __init prng_mod_init(void) | ||
| 390 | { | ||
| 391 | int ret = 0; | ||
| 392 | |||
| 393 | if (fips_enabled) | ||
| 394 | rng_alg.cra_priority += 200; | ||
| 395 | |||
| 396 | ret = crypto_register_alg(&rng_alg); | ||
| 397 | |||
| 398 | if (ret) | ||
| 399 | goto out; | ||
| 400 | out: | ||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static void __exit prng_mod_fini(void) | ||
| 405 | { | ||
| 406 | crypto_unregister_alg(&rng_alg); | ||
| 407 | return; | ||
| 408 | } | ||
| 409 | |||
| 410 | MODULE_LICENSE("GPL"); | ||
| 411 | MODULE_DESCRIPTION("Software Pseudo Random Number Generator"); | ||
| 412 | MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>"); | ||
| 413 | module_param(dbg, int, 0); | ||
| 414 | MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)"); | ||
| 415 | module_init(prng_mod_init); | ||
| 416 | module_exit(prng_mod_fini); | ||
| 417 | MODULE_ALIAS("stdrng"); | ||
diff --git a/crypto/krng.c b/crypto/krng.c new file mode 100644 index 000000000000..4328bb3430ed --- /dev/null +++ b/crypto/krng.c | |||
| @@ -0,0 +1,66 @@ | |||
| 1 | /* | ||
| 2 | * RNG implementation using standard kernel RNG. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <crypto/internal/rng.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/random.h> | ||
| 18 | |||
| 19 | static int krng_get_random(struct crypto_rng *tfm, u8 *rdata, unsigned int dlen) | ||
| 20 | { | ||
| 21 | get_random_bytes(rdata, dlen); | ||
| 22 | return 0; | ||
| 23 | } | ||
| 24 | |||
| 25 | static int krng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | ||
| 26 | { | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | static struct crypto_alg krng_alg = { | ||
| 31 | .cra_name = "stdrng", | ||
| 32 | .cra_driver_name = "krng", | ||
| 33 | .cra_priority = 200, | ||
| 34 | .cra_flags = CRYPTO_ALG_TYPE_RNG, | ||
| 35 | .cra_ctxsize = 0, | ||
| 36 | .cra_type = &crypto_rng_type, | ||
| 37 | .cra_module = THIS_MODULE, | ||
| 38 | .cra_list = LIST_HEAD_INIT(krng_alg.cra_list), | ||
| 39 | .cra_u = { | ||
| 40 | .rng = { | ||
| 41 | .rng_make_random = krng_get_random, | ||
| 42 | .rng_reset = krng_reset, | ||
| 43 | .seedsize = 0, | ||
| 44 | } | ||
| 45 | } | ||
| 46 | }; | ||
| 47 | |||
| 48 | |||
| 49 | /* Module initalization */ | ||
| 50 | static int __init krng_mod_init(void) | ||
| 51 | { | ||
| 52 | return crypto_register_alg(&krng_alg); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void __exit krng_mod_fini(void) | ||
| 56 | { | ||
| 57 | crypto_unregister_alg(&krng_alg); | ||
| 58 | return; | ||
| 59 | } | ||
| 60 | |||
| 61 | module_init(krng_mod_init); | ||
| 62 | module_exit(krng_mod_fini); | ||
| 63 | |||
| 64 | MODULE_LICENSE("GPL"); | ||
| 65 | MODULE_DESCRIPTION("Kernel Random Number Generator"); | ||
| 66 | MODULE_ALIAS("stdrng"); | ||
diff --git a/crypto/rng.c b/crypto/rng.c new file mode 100644 index 000000000000..6e94bc735578 --- /dev/null +++ b/crypto/rng.c | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | /* | ||
| 2 | * Cryptographic API. | ||
| 3 | * | ||
| 4 | * RNG operations. | ||
| 5 | * | ||
| 6 | * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <asm/atomic.h> | ||
| 16 | #include <crypto/internal/rng.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/random.h> | ||
| 21 | #include <linux/seq_file.h> | ||
| 22 | #include <linux/string.h> | ||
| 23 | |||
| 24 | static DEFINE_MUTEX(crypto_default_rng_lock); | ||
| 25 | struct crypto_rng *crypto_default_rng; | ||
| 26 | EXPORT_SYMBOL_GPL(crypto_default_rng); | ||
| 27 | static int crypto_default_rng_refcnt; | ||
| 28 | |||
| 29 | static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen) | ||
| 30 | { | ||
| 31 | u8 *buf = NULL; | ||
| 32 | int err; | ||
| 33 | |||
| 34 | if (!seed && slen) { | ||
| 35 | buf = kmalloc(slen, GFP_KERNEL); | ||
| 36 | if (!buf) | ||
| 37 | return -ENOMEM; | ||
| 38 | |||
| 39 | get_random_bytes(buf, slen); | ||
| 40 | seed = buf; | ||
| 41 | } | ||
| 42 | |||
| 43 | err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen); | ||
| 44 | |||
| 45 | kfree(buf); | ||
| 46 | return err; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | ||
| 50 | { | ||
| 51 | struct rng_alg *alg = &tfm->__crt_alg->cra_rng; | ||
| 52 | struct rng_tfm *ops = &tfm->crt_rng; | ||
| 53 | |||
| 54 | ops->rng_gen_random = alg->rng_make_random; | ||
| 55 | ops->rng_reset = rngapi_reset; | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) | ||
| 61 | __attribute__ ((unused)); | ||
| 62 | static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg) | ||
| 63 | { | ||
| 64 | seq_printf(m, "type : rng\n"); | ||
| 65 | seq_printf(m, "seedsize : %u\n", alg->cra_rng.seedsize); | ||
| 66 | } | ||
| 67 | |||
| 68 | static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type, | ||
| 69 | u32 mask) | ||
| 70 | { | ||
| 71 | return alg->cra_ctxsize; | ||
| 72 | } | ||
| 73 | |||
| 74 | const struct crypto_type crypto_rng_type = { | ||
| 75 | .ctxsize = crypto_rng_ctxsize, | ||
| 76 | .init = crypto_init_rng_ops, | ||
| 77 | #ifdef CONFIG_PROC_FS | ||
| 78 | .show = crypto_rng_show, | ||
| 79 | #endif | ||
| 80 | }; | ||
| 81 | EXPORT_SYMBOL_GPL(crypto_rng_type); | ||
| 82 | |||
| 83 | int crypto_get_default_rng(void) | ||
| 84 | { | ||
| 85 | struct crypto_rng *rng; | ||
| 86 | int err; | ||
| 87 | |||
| 88 | mutex_lock(&crypto_default_rng_lock); | ||
| 89 | if (!crypto_default_rng) { | ||
| 90 | rng = crypto_alloc_rng("stdrng", 0, 0); | ||
| 91 | err = PTR_ERR(rng); | ||
| 92 | if (IS_ERR(rng)) | ||
| 93 | goto unlock; | ||
| 94 | |||
| 95 | err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng)); | ||
| 96 | if (err) { | ||
| 97 | crypto_free_rng(rng); | ||
| 98 | goto unlock; | ||
| 99 | } | ||
| 100 | |||
| 101 | crypto_default_rng = rng; | ||
| 102 | } | ||
| 103 | |||
| 104 | crypto_default_rng_refcnt++; | ||
| 105 | err = 0; | ||
| 106 | |||
| 107 | unlock: | ||
| 108 | mutex_unlock(&crypto_default_rng_lock); | ||
| 109 | |||
| 110 | return err; | ||
| 111 | } | ||
| 112 | EXPORT_SYMBOL_GPL(crypto_get_default_rng); | ||
| 113 | |||
| 114 | void crypto_put_default_rng(void) | ||
| 115 | { | ||
| 116 | mutex_lock(&crypto_default_rng_lock); | ||
| 117 | if (!--crypto_default_rng_refcnt) { | ||
| 118 | crypto_free_rng(crypto_default_rng); | ||
| 119 | crypto_default_rng = NULL; | ||
| 120 | } | ||
| 121 | mutex_unlock(&crypto_default_rng_lock); | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(crypto_put_default_rng); | ||
| 124 | |||
| 125 | MODULE_LICENSE("GPL"); | ||
| 126 | MODULE_DESCRIPTION("Random Number Genertor"); | ||
diff --git a/include/crypto/internal/rng.h b/include/crypto/internal/rng.h new file mode 100644 index 000000000000..896973369573 --- /dev/null +++ b/include/crypto/internal/rng.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | * RNG: Random Number Generator algorithms under the crypto API | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _CRYPTO_INTERNAL_RNG_H | ||
| 14 | #define _CRYPTO_INTERNAL_RNG_H | ||
| 15 | |||
| 16 | #include <crypto/algapi.h> | ||
| 17 | #include <crypto/rng.h> | ||
| 18 | |||
| 19 | extern const struct crypto_type crypto_rng_type; | ||
| 20 | |||
| 21 | static inline void *crypto_rng_ctx(struct crypto_rng *tfm) | ||
| 22 | { | ||
| 23 | return crypto_tfm_ctx(&tfm->base); | ||
| 24 | } | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/include/crypto/rng.h b/include/crypto/rng.h new file mode 100644 index 000000000000..c93f9b917925 --- /dev/null +++ b/include/crypto/rng.h | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | /* | ||
| 2 | * RNG: Random Number Generator algorithms under the crypto API | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the Free | ||
| 8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 9 | * any later version. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _CRYPTO_RNG_H | ||
| 14 | #define _CRYPTO_RNG_H | ||
| 15 | |||
| 16 | #include <linux/crypto.h> | ||
| 17 | |||
| 18 | extern struct crypto_rng *crypto_default_rng; | ||
| 19 | |||
| 20 | int crypto_get_default_rng(void); | ||
| 21 | void crypto_put_default_rng(void); | ||
| 22 | |||
| 23 | static inline struct crypto_rng *__crypto_rng_cast(struct crypto_tfm *tfm) | ||
| 24 | { | ||
| 25 | return (struct crypto_rng *)tfm; | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline struct crypto_rng *crypto_alloc_rng(const char *alg_name, | ||
| 29 | u32 type, u32 mask) | ||
| 30 | { | ||
| 31 | type &= ~CRYPTO_ALG_TYPE_MASK; | ||
| 32 | type |= CRYPTO_ALG_TYPE_RNG; | ||
| 33 | mask |= CRYPTO_ALG_TYPE_MASK; | ||
| 34 | |||
| 35 | return __crypto_rng_cast(crypto_alloc_base(alg_name, type, mask)); | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm) | ||
| 39 | { | ||
| 40 | return &tfm->base; | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm) | ||
| 44 | { | ||
| 45 | return &crypto_rng_tfm(tfm)->__crt_alg->cra_rng; | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline struct rng_tfm *crypto_rng_crt(struct crypto_rng *tfm) | ||
| 49 | { | ||
| 50 | return &crypto_rng_tfm(tfm)->crt_rng; | ||
| 51 | } | ||
| 52 | |||
| 53 | static inline void crypto_free_rng(struct crypto_rng *tfm) | ||
| 54 | { | ||
| 55 | crypto_free_tfm(crypto_rng_tfm(tfm)); | ||
| 56 | } | ||
| 57 | |||
| 58 | static inline int crypto_rng_get_bytes(struct crypto_rng *tfm, | ||
| 59 | u8 *rdata, unsigned int dlen) | ||
| 60 | { | ||
| 61 | return crypto_rng_crt(tfm)->rng_gen_random(tfm, rdata, dlen); | ||
| 62 | } | ||
| 63 | |||
| 64 | static inline int crypto_rng_reset(struct crypto_rng *tfm, | ||
| 65 | u8 *seed, unsigned int slen) | ||
| 66 | { | ||
| 67 | return crypto_rng_crt(tfm)->rng_reset(tfm, seed, slen); | ||
| 68 | } | ||
| 69 | |||
| 70 | static inline int crypto_rng_seedsize(struct crypto_rng *tfm) | ||
| 71 | { | ||
| 72 | return crypto_rng_alg(tfm)->seedsize; | ||
| 73 | } | ||
| 74 | |||
| 75 | #endif | ||
diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 81d994a3bdaf..3d2317e4af2e 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #define CRYPTO_ALG_TYPE_DIGEST 0x00000008 | 38 | #define CRYPTO_ALG_TYPE_DIGEST 0x00000008 |
| 39 | #define CRYPTO_ALG_TYPE_HASH 0x00000009 | 39 | #define CRYPTO_ALG_TYPE_HASH 0x00000009 |
| 40 | #define CRYPTO_ALG_TYPE_AHASH 0x0000000a | 40 | #define CRYPTO_ALG_TYPE_AHASH 0x0000000a |
| 41 | #define CRYPTO_ALG_TYPE_RNG 0x0000000c | ||
| 41 | 42 | ||
| 42 | #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e | 43 | #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e |
| 43 | #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c | 44 | #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c |
| @@ -113,6 +114,7 @@ struct crypto_aead; | |||
| 113 | struct crypto_blkcipher; | 114 | struct crypto_blkcipher; |
| 114 | struct crypto_hash; | 115 | struct crypto_hash; |
| 115 | struct crypto_ahash; | 116 | struct crypto_ahash; |
| 117 | struct crypto_rng; | ||
| 116 | struct crypto_tfm; | 118 | struct crypto_tfm; |
| 117 | struct crypto_type; | 119 | struct crypto_type; |
| 118 | struct aead_givcrypt_request; | 120 | struct aead_givcrypt_request; |
| @@ -298,6 +300,15 @@ struct compress_alg { | |||
| 298 | unsigned int slen, u8 *dst, unsigned int *dlen); | 300 | unsigned int slen, u8 *dst, unsigned int *dlen); |
| 299 | }; | 301 | }; |
| 300 | 302 | ||
| 303 | struct rng_alg { | ||
| 304 | int (*rng_make_random)(struct crypto_rng *tfm, u8 *rdata, | ||
| 305 | unsigned int dlen); | ||
| 306 | int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen); | ||
| 307 | |||
| 308 | unsigned int seedsize; | ||
| 309 | }; | ||
| 310 | |||
| 311 | |||
| 301 | #define cra_ablkcipher cra_u.ablkcipher | 312 | #define cra_ablkcipher cra_u.ablkcipher |
| 302 | #define cra_aead cra_u.aead | 313 | #define cra_aead cra_u.aead |
| 303 | #define cra_blkcipher cra_u.blkcipher | 314 | #define cra_blkcipher cra_u.blkcipher |
| @@ -306,6 +317,7 @@ struct compress_alg { | |||
| 306 | #define cra_hash cra_u.hash | 317 | #define cra_hash cra_u.hash |
| 307 | #define cra_ahash cra_u.ahash | 318 | #define cra_ahash cra_u.ahash |
| 308 | #define cra_compress cra_u.compress | 319 | #define cra_compress cra_u.compress |
| 320 | #define cra_rng cra_u.rng | ||
| 309 | 321 | ||
| 310 | struct crypto_alg { | 322 | struct crypto_alg { |
| 311 | struct list_head cra_list; | 323 | struct list_head cra_list; |
| @@ -333,6 +345,7 @@ struct crypto_alg { | |||
| 333 | struct hash_alg hash; | 345 | struct hash_alg hash; |
| 334 | struct ahash_alg ahash; | 346 | struct ahash_alg ahash; |
| 335 | struct compress_alg compress; | 347 | struct compress_alg compress; |
| 348 | struct rng_alg rng; | ||
| 336 | } cra_u; | 349 | } cra_u; |
| 337 | 350 | ||
| 338 | int (*cra_init)(struct crypto_tfm *tfm); | 351 | int (*cra_init)(struct crypto_tfm *tfm); |
| @@ -438,6 +451,12 @@ struct compress_tfm { | |||
| 438 | u8 *dst, unsigned int *dlen); | 451 | u8 *dst, unsigned int *dlen); |
| 439 | }; | 452 | }; |
| 440 | 453 | ||
| 454 | struct rng_tfm { | ||
| 455 | int (*rng_gen_random)(struct crypto_rng *tfm, u8 *rdata, | ||
| 456 | unsigned int dlen); | ||
| 457 | int (*rng_reset)(struct crypto_rng *tfm, u8 *seed, unsigned int slen); | ||
| 458 | }; | ||
| 459 | |||
| 441 | #define crt_ablkcipher crt_u.ablkcipher | 460 | #define crt_ablkcipher crt_u.ablkcipher |
| 442 | #define crt_aead crt_u.aead | 461 | #define crt_aead crt_u.aead |
| 443 | #define crt_blkcipher crt_u.blkcipher | 462 | #define crt_blkcipher crt_u.blkcipher |
| @@ -445,6 +464,7 @@ struct compress_tfm { | |||
| 445 | #define crt_hash crt_u.hash | 464 | #define crt_hash crt_u.hash |
| 446 | #define crt_ahash crt_u.ahash | 465 | #define crt_ahash crt_u.ahash |
| 447 | #define crt_compress crt_u.compress | 466 | #define crt_compress crt_u.compress |
| 467 | #define crt_rng crt_u.rng | ||
| 448 | 468 | ||
| 449 | struct crypto_tfm { | 469 | struct crypto_tfm { |
| 450 | 470 | ||
| @@ -458,6 +478,7 @@ struct crypto_tfm { | |||
| 458 | struct hash_tfm hash; | 478 | struct hash_tfm hash; |
| 459 | struct ahash_tfm ahash; | 479 | struct ahash_tfm ahash; |
| 460 | struct compress_tfm compress; | 480 | struct compress_tfm compress; |
| 481 | struct rng_tfm rng; | ||
| 461 | } crt_u; | 482 | } crt_u; |
| 462 | 483 | ||
| 463 | struct crypto_alg *__crt_alg; | 484 | struct crypto_alg *__crt_alg; |
| @@ -489,6 +510,10 @@ struct crypto_hash { | |||
| 489 | struct crypto_tfm base; | 510 | struct crypto_tfm base; |
| 490 | }; | 511 | }; |
| 491 | 512 | ||
| 513 | struct crypto_rng { | ||
| 514 | struct crypto_tfm base; | ||
| 515 | }; | ||
| 516 | |||
| 492 | enum { | 517 | enum { |
| 493 | CRYPTOA_UNSPEC, | 518 | CRYPTOA_UNSPEC, |
| 494 | CRYPTOA_ALG, | 519 | CRYPTOA_ALG, |
