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/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
  39struct 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
  51static int dbg;
  52
  53static 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 {\
  64if (dbg)\
  65        printk(format, ##args);\
  66} while (0)
  67
  68static 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 */
  81static 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 */
 181static 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
 216remainder:
 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) {
 229empty_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
 264done:
 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
 271static void free_prng_context(struct prng_context *ctx)
 272{
 273        crypto_free_cipher(ctx->tfm);
 274}
 275
 276static 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;
 315out:
 316        spin_unlock_bh(&ctx->prng_lock);
 317        return ret;
 318}
 319
 320static 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
 344static void cprng_exit(struct crypto_tfm *tfm)
 345{
 346        free_prng_context(crypto_tfm_ctx(tfm));
 347}
 348
 349static 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 */
 364static 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
 385static 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
 394static 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
 419out:
 420        return rc;
 421}
 422#endif
 423
 424static 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 */
 455static int __init prng_mod_init(void)
 456{
 457        return crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
 458}
 459
 460static void __exit prng_mod_fini(void)
 461{
 462        crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
 463}
 464
 465MODULE_LICENSE("GPL");
 466MODULE_DESCRIPTION("Software Pseudo Random Number Generator");
 467MODULE_AUTHOR("Neil Horman <nhorman@tuxdriver.com>");
 468module_param(dbg, int, 0);
 469MODULE_PARM_DESC(dbg, "Boolean to enable debugging (0/1 == off/on)");
 470subsys_initcall(prng_mod_init);
 471module_exit(prng_mod_fini);
 472MODULE_ALIAS_CRYPTO("stdrng");
 473MODULE_ALIAS_CRYPTO("ansi_cprng");
 474MODULE_IMPORT_NS(CRYPTO_INTERNAL);
 475
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.