root/crypto/ansi_cprng.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hexdump
  2. xor_vectors
  3. _get_more_prng_bytes
  4. get_prng_bytes
  5. free_prng_context
  6. reset_prng_context
  7. cprng_init
  8. cprng_exit
  9. cprng_get_random
  10. cprng_reset
  11. fips_cprng_get_random
  12. fips_cprng_reset
  13. prng_mod_init
  14. prng_mod_fini

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

/* [<][>][^][v][top][bottom][index][help] */