linux/crypto/ansi_cprng.c
<<
>>
Prefs
   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
  38struct 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
  50static int dbg;
  51
  52static 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 {\
  63if (dbg)\
  64        printk(format, ##args);\
  65} while (0)
  66
  67static 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 */
  80static 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 */
 180static 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
 215remainder:
 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) {
 228empty_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
 263done:
 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
 270static void free_prng_context(struct prng_context *ctx)
 271{
 272        crypto_free_cipher(ctx->tfm);
 273}
 274
 275static 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;
 314out:
 315        spin_unlock_bh(&ctx->prng_lock);
 316        return ret;
 317}
 318
 319static 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
 343static void cprng_exit(struct crypto_tfm *tfm)
 344{
 345        free_prng_context(crypto_tfm_ctx(tfm));
 346}
 347
 348static 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 */
 363static 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
 384static 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
 393static 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
 418out:
 419        return rc;
 420}
 421#endif
 422
 423static 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 */
 454static int __init prng_mod_init(void)
 455{
 456        return crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
 457}
 458
 459static void __exit prng_mod_fini(void)
 460{
 461        crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
 462}
 463
 464MODULE_LICENSE("GPL");
 465MODULE_DESCRIPTION("Software Pseudo Random Number Generator");
 466MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");
 467module_param(dbg, int, 0);
 468MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
 469subsys_initcall(prng_mod_init);
 470module_exit(prng_mod_fini);
 471MODULE_ALIAS_CRYPTO("stdrng");
 472MODULE_ALIAS_CRYPTO("ansi_cprng");
 473