LCOV - code coverage report
Current view: top level - crypto - rng.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 12 91 13.2 %
Date: 2022-03-28 13:20:08 Functions: 2 12 16.7 %
Branches: 5 32 15.6 %

           Branch data     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                 :            :                         return -ENOMEM;
      42                 :            : 
      43                 :          0 :                 err = get_random_bytes_wait(buf, slen);
      44         [ #  # ]:          0 :                 if (err)
      45                 :          0 :                         goto out;
      46                 :            :                 seed = buf;
      47                 :            :         }
      48                 :            : 
      49                 :          0 :         err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
      50                 :          0 :         crypto_stats_rng_seed(alg, err);
      51                 :          0 : out:
      52                 :          0 :         kzfree(buf);
      53                 :          0 :         return err;
      54                 :            : }
      55                 :            : EXPORT_SYMBOL_GPL(crypto_rng_reset);
      56                 :            : 
      57                 :          0 : static int crypto_rng_init_tfm(struct crypto_tfm *tfm)
      58                 :            : {
      59                 :          0 :         return 0;
      60                 :            : }
      61                 :            : 
      62                 :          0 : static unsigned int seedsize(struct crypto_alg *alg)
      63                 :            : {
      64                 :          0 :         struct rng_alg *ralg = container_of(alg, struct rng_alg, base);
      65                 :            : 
      66                 :          0 :         return ralg->seedsize;
      67                 :            : }
      68                 :            : 
      69                 :            : #ifdef CONFIG_NET
      70                 :          0 : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
      71                 :            : {
      72                 :          0 :         struct crypto_report_rng rrng;
      73                 :            : 
      74                 :          0 :         memset(&rrng, 0, sizeof(rrng));
      75                 :            : 
      76                 :          0 :         strscpy(rrng.type, "rng", sizeof(rrng.type));
      77                 :            : 
      78                 :          0 :         rrng.seedsize = seedsize(alg);
      79                 :            : 
      80                 :          0 :         return nla_put(skb, CRYPTOCFGA_REPORT_RNG, sizeof(rrng), &rrng);
      81                 :            : }
      82                 :            : #else
      83                 :            : static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
      84                 :            : {
      85                 :            :         return -ENOSYS;
      86                 :            : }
      87                 :            : #endif
      88                 :            : 
      89                 :            : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
      90                 :            :         __maybe_unused;
      91                 :          0 : static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
      92                 :            : {
      93                 :          0 :         seq_printf(m, "type         : rng\n");
      94                 :          0 :         seq_printf(m, "seedsize     : %u\n", seedsize(alg));
      95                 :          0 : }
      96                 :            : 
      97                 :            : static const struct crypto_type crypto_rng_type = {
      98                 :            :         .extsize = crypto_alg_extsize,
      99                 :            :         .init_tfm = crypto_rng_init_tfm,
     100                 :            : #ifdef CONFIG_PROC_FS
     101                 :            :         .show = crypto_rng_show,
     102                 :            : #endif
     103                 :            :         .report = crypto_rng_report,
     104                 :            :         .maskclear = ~CRYPTO_ALG_TYPE_MASK,
     105                 :            :         .maskset = CRYPTO_ALG_TYPE_MASK,
     106                 :            :         .type = CRYPTO_ALG_TYPE_RNG,
     107                 :            :         .tfmsize = offsetof(struct crypto_rng, base),
     108                 :            : };
     109                 :            : 
     110                 :          0 : struct crypto_rng *crypto_alloc_rng(const char *alg_name, u32 type, u32 mask)
     111                 :            : {
     112                 :          0 :         return crypto_alloc_tfm(alg_name, &crypto_rng_type, type, mask);
     113                 :            : }
     114                 :            : EXPORT_SYMBOL_GPL(crypto_alloc_rng);
     115                 :            : 
     116                 :          0 : int crypto_get_default_rng(void)
     117                 :            : {
     118                 :          0 :         struct crypto_rng *rng;
     119                 :          0 :         int err;
     120                 :            : 
     121                 :          0 :         mutex_lock(&crypto_default_rng_lock);
     122         [ #  # ]:          0 :         if (!crypto_default_rng) {
     123                 :          0 :                 rng = crypto_alloc_rng("stdrng", 0, 0);
     124         [ #  # ]:          0 :                 err = PTR_ERR(rng);
     125         [ #  # ]:          0 :                 if (IS_ERR(rng))
     126                 :          0 :                         goto unlock;
     127                 :            : 
     128                 :          0 :                 err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
     129         [ #  # ]:          0 :                 if (err) {
     130                 :          0 :                         crypto_free_rng(rng);
     131                 :          0 :                         goto unlock;
     132                 :            :                 }
     133                 :            : 
     134                 :          0 :                 crypto_default_rng = rng;
     135                 :            :         }
     136                 :            : 
     137                 :          0 :         crypto_default_rng_refcnt++;
     138                 :          0 :         err = 0;
     139                 :            : 
     140                 :          0 : unlock:
     141                 :          0 :         mutex_unlock(&crypto_default_rng_lock);
     142                 :            : 
     143                 :          0 :         return err;
     144                 :            : }
     145                 :            : EXPORT_SYMBOL_GPL(crypto_get_default_rng);
     146                 :            : 
     147                 :          0 : void crypto_put_default_rng(void)
     148                 :            : {
     149                 :          0 :         mutex_lock(&crypto_default_rng_lock);
     150                 :          0 :         crypto_default_rng_refcnt--;
     151                 :          0 :         mutex_unlock(&crypto_default_rng_lock);
     152                 :          0 : }
     153                 :            : EXPORT_SYMBOL_GPL(crypto_put_default_rng);
     154                 :            : 
     155                 :            : #if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
     156                 :          0 : int crypto_del_default_rng(void)
     157                 :            : {
     158                 :          0 :         int err = -EBUSY;
     159                 :            : 
     160                 :          0 :         mutex_lock(&crypto_default_rng_lock);
     161         [ #  # ]:          0 :         if (crypto_default_rng_refcnt)
     162                 :          0 :                 goto out;
     163                 :            : 
     164                 :          0 :         crypto_free_rng(crypto_default_rng);
     165                 :          0 :         crypto_default_rng = NULL;
     166                 :            : 
     167                 :          0 :         err = 0;
     168                 :            : 
     169                 :          0 : out:
     170                 :          0 :         mutex_unlock(&crypto_default_rng_lock);
     171                 :            : 
     172                 :          0 :         return err;
     173                 :            : }
     174                 :            : EXPORT_SYMBOL_GPL(crypto_del_default_rng);
     175                 :            : #endif
     176                 :            : 
     177                 :        270 : int crypto_register_rng(struct rng_alg *alg)
     178                 :            : {
     179                 :        270 :         struct crypto_alg *base = &alg->base;
     180                 :            : 
     181         [ +  - ]:         30 :         if (alg->seedsize > PAGE_SIZE / 8)
     182                 :            :                 return -EINVAL;
     183                 :            : 
     184                 :        270 :         base->cra_type = &crypto_rng_type;
     185                 :        270 :         base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
     186                 :        270 :         base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
     187                 :            : 
     188                 :        270 :         return crypto_register_alg(base);
     189                 :            : }
     190                 :            : EXPORT_SYMBOL_GPL(crypto_register_rng);
     191                 :            : 
     192                 :          0 : void crypto_unregister_rng(struct rng_alg *alg)
     193                 :            : {
     194                 :          0 :         crypto_unregister_alg(&alg->base);
     195                 :          0 : }
     196                 :            : EXPORT_SYMBOL_GPL(crypto_unregister_rng);
     197                 :            : 
     198                 :         30 : int crypto_register_rngs(struct rng_alg *algs, int count)
     199                 :            : {
     200                 :         30 :         int i, ret;
     201                 :            : 
     202         [ +  + ]:        270 :         for (i = 0; i < count; i++) {
     203         [ +  - ]:        240 :                 ret = crypto_register_rng(algs + i);
     204         [ -  + ]:        240 :                 if (ret)
     205                 :          0 :                         goto err;
     206                 :            :         }
     207                 :            : 
     208                 :            :         return 0;
     209                 :            : 
     210                 :            : err:
     211         [ #  # ]:          0 :         for (--i; i >= 0; --i)
     212                 :          0 :                 crypto_unregister_rng(algs + i);
     213                 :            : 
     214                 :            :         return ret;
     215                 :            : }
     216                 :            : EXPORT_SYMBOL_GPL(crypto_register_rngs);
     217                 :            : 
     218                 :          0 : void crypto_unregister_rngs(struct rng_alg *algs, int count)
     219                 :            : {
     220                 :          0 :         int i;
     221                 :            : 
     222         [ #  # ]:          0 :         for (i = count - 1; i >= 0; --i)
     223                 :          0 :                 crypto_unregister_rng(algs + i);
     224                 :          0 : }
     225                 :            : EXPORT_SYMBOL_GPL(crypto_unregister_rngs);
     226                 :            : 
     227                 :            : MODULE_LICENSE("GPL");
     228                 :            : MODULE_DESCRIPTION("Random Number Generator");

Generated by: LCOV version 1.14