LCOV - code coverage report
Current view: top level - crypto - rng.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 12 95 12.6 %
Date: 2021-04-22 12:43:58 Functions: 2 12 16.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Cryptographic API.
       4             :  *
       5             :  * RNG operations.
       6             :  *
       7             :  * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
       8             :  * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
       9             :  */
      10             : 
      11             : #include <linux/atomic.h>
      12             : #include <crypto/internal/rng.h>
      13             : #include <linux/err.h>
      14             : #include <linux/module.h>
      15             : #include <linux/mutex.h>
      16             : #include <linux/random.h>
      17             : #include <linux/seq_file.h>
      18             : #include <linux/slab.h>
      19             : #include <linux/string.h>
      20             : #include <linux/cryptouser.h>
      21             : #include <linux/compiler.h>
      22             : #include <net/netlink.h>
      23             : 
      24             : #include "internal.h"
      25             : 
      26             : static DEFINE_MUTEX(crypto_default_rng_lock);
      27             : struct crypto_rng *crypto_default_rng;
      28             : EXPORT_SYMBOL_GPL(crypto_default_rng);
      29             : static int crypto_default_rng_refcnt;
      30             : 
      31           0 : int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
      32             : {
      33           0 :         struct crypto_alg *alg = tfm->base.__crt_alg;
      34           0 :         u8 *buf = NULL;
      35           0 :         int err;
      36             : 
      37           0 :         crypto_stats_get(alg);
      38           0 :         if (!seed && slen) {
      39           0 :                 buf = kmalloc(slen, GFP_KERNEL);
      40           0 :                 if (!buf) {
      41           0 :                         crypto_alg_put(alg);
      42           0 :                         return -ENOMEM;
      43             :                 }
      44             : 
      45           0 :                 err = get_random_bytes_wait(buf, slen);
      46           0 :                 if (err) {
      47           0 :                         crypto_alg_put(alg);
      48           0 :                         goto out;
      49             :                 }
      50             :                 seed = buf;
      51             :         }
      52             : 
      53           0 :         err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
      54           0 :         crypto_stats_rng_seed(alg, err);
      55           0 : out:
      56           0 :         kfree_sensitive(buf);
      57           0 :         return err;
      58             : }
      59             : EXPORT_SYMBOL_GPL(crypto_rng_reset);
      60             : 
      61           0 : static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
      62             : {
      63           0 :         return 0;
      64             : }
      65             : 
      66           0 : static unsigned int seedsize(struct crypto_alg *alg)
      67             : {
      68           0 :         struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
      69             : 
      70           0 :         return ralg->seedsize;
      71             : }
      72             : 
      73             : #ifdef CONFIG_NET
      74           0 : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
      75             : {
      76           0 :         struct crypto_report_rng rrng;
      77             : 
      78           0 :         memset(&rrng, 0, sizeof(rrng));
      79             : 
      80           0 :         strscpy(rrng.type, "rng", sizeof(rrng.type));
      81             : 
      82           0 :         rrng.seedsize = seedsize(alg);
      83             : 
      84           0 :         return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);
      85             : }
      86             : #else
      87             : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
      88             : {
      89             :         return -ENOSYS;
      90             : }
      91             : #endif
      92             : 
      93             : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
      94             :         __maybe_unused;
      95           0 : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
      96             : {
      97           0 :         seq_printf(m, "type         : rng\n");
      98           0 :         seq_printf(m, "seedsize     : %u\n", seedsize(alg));
      99           0 : }
     100             : 
     101             : static const struct crypto_type crypto_rng_type = {
     102             :         .extsize = crypto_alg_extsize,
     103             :         .init_tfm = crypto_rng_init_tfm,
     104             : #ifdef CONFIG_PROC_FS
     105             :         .show = crypto_rng_show,
     106             : #endif
     107             :         .report = crypto_rng_report,
     108             :         .maskclear = ~CRYPTO_ALG_TYPE_MASK,
     109             :         .maskset = CRYPTO_ALG_TYPE_MASK,
     110             :         .type = CRYPTO_ALG_TYPE_RNG,
     111             :         .tfmsize = offsetof(struct crypto_rng, base),
     112             : };
     113             : 
     114           0 : struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
     115             : {
     116           0 :         return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
     117             : }
     118             : EXPORT_SYMBOL_GPL(crypto_alloc_rng);
     119             : 
     120           0 : int crypto_get_default_rng(void)
     121             : {
     122           0 :         struct crypto_rng *rng;
     123           0 :         int err;
     124             : 
     125           0 :         mutex_lock(&crypto_default_rng_lock);
     126           0 :         if (!crypto_default_rng) {
     127           0 :                 rng = crypto_alloc_rng("stdrng", 0, 0);
     128           0 :                 err = PTR_ERR(rng);
     129           0 :                 if (IS_ERR(rng))
     130           0 :                         goto unlock;
     131             : 
     132           0 :                 err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
     133           0 :                 if (err) {
     134           0 :                         crypto_free_rng(rng);
     135           0 :                         goto unlock;
     136             :                 }
     137             : 
     138           0 :                 crypto_default_rng = rng;
     139             :         }
     140             : 
     141           0 :         crypto_default_rng_refcnt++;
     142           0 :         err = 0;
     143             : 
     144           0 : unlock:
     145           0 :         mutex_unlock(&crypto_default_rng_lock);
     146             : 
     147           0 :         return err;
     148             : }
     149             : EXPORT_SYMBOL_GPL(crypto_get_default_rng);
     150             : 
     151           0 : void crypto_put_default_rng(void)
     152             : {
     153           0 :         mutex_lock(&crypto_default_rng_lock);
     154           0 :         crypto_default_rng_refcnt--;
     155           0 :         mutex_unlock(&crypto_default_rng_lock);
     156           0 : }
     157             : EXPORT_SYMBOL_GPL(crypto_put_default_rng);
     158             : 
     159             : #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
     160           0 : int crypto_del_default_rng(void)
     161             : {
     162           0 :         int err = -EBUSY;
     163             : 
     164           0 :         mutex_lock(&crypto_default_rng_lock);
     165           0 :         if (crypto_default_rng_refcnt)
     166           0 :                 goto out;
     167             : 
     168           0 :         crypto_free_rng(crypto_default_rng);
     169           0 :         crypto_default_rng = NULL;
     170             : 
     171           0 :         err = 0;
     172             : 
     173           0 : out:
     174           0 :         mutex_unlock(&crypto_default_rng_lock);
     175             : 
     176           0 :         return err;
     177             : }
     178             : EXPORT_SYMBOL_GPL(crypto_del_default_rng);
     179             : #endif
     180             : 
     181           1 : int crypto_register_rng(struct rng_alg *alg)
     182             : {
     183           1 :         struct crypto_alg *base = &alg->base;
     184             : 
     185           1 :         if (alg->seedsize > PAGE_SIZE / 8)
     186             :                 return -EINVAL;
     187             : 
     188           1 :         base->cra_type = &crypto_rng_type;
     189           1 :         base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
     190           1 :         base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
     191             : 
     192           1 :         return crypto_register_alg(base);
     193             : }
     194             : EXPORT_SYMBOL_GPL(crypto_register_rng);
     195             : 
     196           0 : void crypto_unregister_rng(struct rng_alg *alg)
     197             : {
     198           0 :         crypto_unregister_alg(&alg->base);
     199           0 : }
     200             : EXPORT_SYMBOL_GPL(crypto_unregister_rng);
     201             : 
     202           1 : int crypto_register_rngs(struct rng_alg *algs, int count)
     203             : {
     204           1 :         int i, ret;
     205             : 
     206           2 :         for (i = 0; i < count; i++) {
     207           1 :                 ret = crypto_register_rng(algs + i);
     208           1 :                 if (ret)
     209           0 :                         goto err;
     210             :         }
     211             : 
     212             :         return 0;
     213             : 
     214           0 : err:
     215           0 :         for (--i; i >= 0; --i)
     216           0 :                 crypto_unregister_rng(algs + i);
     217             : 
     218             :         return ret;
     219             : }
     220             : EXPORT_SYMBOL_GPL(crypto_register_rngs);
     221             : 
     222           0 : void crypto_unregister_rngs(struct rng_alg *algs, int count)
     223             : {
     224           0 :         int i;
     225             : 
     226           0 :         for (i = count - 1; i >= 0; --i)
     227           0 :                 crypto_unregister_rng(algs + i);
     228           0 : }
     229             : EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
     230             : 
     231             : MODULE_LICENSE("GPL");
     232             : MODULE_DESCRIPTION("Random Number Generator");

Generated by: LCOV version 1.14