Blame view

crypto/rng.c 3.32 KB
17f0f4a47   Neil Horman   crypto: rng - RNG...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * Cryptographic API.
   *
   * RNG operations.
   *
   * Copyright (c) 2008 Neil Horman <nhorman@tuxdriver.com>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   *
   */
60063497a   Arun Sharma   atomic: use <linu...
14
  #include <linux/atomic.h>
17f0f4a47   Neil Horman   crypto: rng - RNG...
15
16
17
18
19
20
  #include <crypto/internal/rng.h>
  #include <linux/err.h>
  #include <linux/module.h>
  #include <linux/mutex.h>
  #include <linux/random.h>
  #include <linux/seq_file.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
17f0f4a47   Neil Horman   crypto: rng - RNG...
22
  #include <linux/string.h>
792608e9c   Steffen Klassert   crypto: Add users...
23
24
  #include <linux/cryptouser.h>
  #include <net/netlink.h>
17f0f4a47   Neil Horman   crypto: rng - RNG...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  
  static DEFINE_MUTEX(crypto_default_rng_lock);
  struct crypto_rng *crypto_default_rng;
  EXPORT_SYMBOL_GPL(crypto_default_rng);
  static int crypto_default_rng_refcnt;
  
  static int rngapi_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
  {
  	u8 *buf = NULL;
  	int err;
  
  	if (!seed && slen) {
  		buf = kmalloc(slen, GFP_KERNEL);
  		if (!buf)
  			return -ENOMEM;
  
  		get_random_bytes(buf, slen);
  		seed = buf;
  	}
  
  	err = crypto_rng_alg(tfm)->rng_reset(tfm, seed, slen);
  
  	kfree(buf);
  	return err;
  }
  
  static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
  {
  	struct rng_alg *alg = &tfm->__crt_alg->cra_rng;
  	struct rng_tfm *ops = &tfm->crt_rng;
  
  	ops->rng_gen_random = alg->rng_make_random;
  	ops->rng_reset = rngapi_reset;
  
  	return 0;
  }
3acc84739   Herbert Xu   crypto: algapi - ...
61
  #ifdef CONFIG_NET
792608e9c   Steffen Klassert   crypto: Add users...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_rng rrng;
  
  	snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
  
  	rrng.seedsize = alg->cra_rng.seedsize;
  
  	NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
  		sizeof(struct crypto_report_rng), &rrng);
  
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
3acc84739   Herbert Xu   crypto: algapi - ...
78
79
80
81
82
83
  #else
  static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	return -ENOSYS;
  }
  #endif
792608e9c   Steffen Klassert   crypto: Add users...
84

17f0f4a47   Neil Horman   crypto: rng - RNG...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  	__attribute__ ((unused));
  static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
  {
  	seq_printf(m, "type         : rng
  ");
  	seq_printf(m, "seedsize     : %u
  ", alg->cra_rng.seedsize);
  }
  
  static unsigned int crypto_rng_ctxsize(struct crypto_alg *alg, u32 type,
  				       u32 mask)
  {
  	return alg->cra_ctxsize;
  }
  
  const struct crypto_type crypto_rng_type = {
  	.ctxsize = crypto_rng_ctxsize,
  	.init = crypto_init_rng_ops,
  #ifdef CONFIG_PROC_FS
  	.show = crypto_rng_show,
  #endif
792608e9c   Steffen Klassert   crypto: Add users...
107
  	.report = crypto_rng_report,
17f0f4a47   Neil Horman   crypto: rng - RNG...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  };
  EXPORT_SYMBOL_GPL(crypto_rng_type);
  
  int crypto_get_default_rng(void)
  {
  	struct crypto_rng *rng;
  	int err;
  
  	mutex_lock(&crypto_default_rng_lock);
  	if (!crypto_default_rng) {
  		rng = crypto_alloc_rng("stdrng", 0, 0);
  		err = PTR_ERR(rng);
  		if (IS_ERR(rng))
  			goto unlock;
  
  		err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
  		if (err) {
  			crypto_free_rng(rng);
  			goto unlock;
  		}
  
  		crypto_default_rng = rng;
  	}
  
  	crypto_default_rng_refcnt++;
  	err = 0;
  
  unlock:
  	mutex_unlock(&crypto_default_rng_lock);
  
  	return err;
  }
  EXPORT_SYMBOL_GPL(crypto_get_default_rng);
  
  void crypto_put_default_rng(void)
  {
  	mutex_lock(&crypto_default_rng_lock);
  	if (!--crypto_default_rng_refcnt) {
  		crypto_free_rng(crypto_default_rng);
  		crypto_default_rng = NULL;
  	}
  	mutex_unlock(&crypto_default_rng_lock);
  }
  EXPORT_SYMBOL_GPL(crypto_put_default_rng);
  
  MODULE_LICENSE("GPL");
a8ccc393d   Christian Kujau   crypto: rng - Fix...
154
  MODULE_DESCRIPTION("Random Number Generator");