Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
ossl_rand.c
Go to the documentation of this file.
1/*
2 * 'OpenSSL for Ruby' project
3 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4 *
5 * All rights reserved.
6 *
7 * This program is licensed under the same licence as Ruby.
8 * (See the file 'LICENCE'.)
9 */
10#include "ossl.h"
11
14
15/*
16 * call-seq:
17 * seed(str) -> str
18 *
19 * ::seed is equivalent to ::add where _entropy_ is length of _str_.
20 */
21static VALUE
22ossl_rand_seed(VALUE self, VALUE str)
23{
25 RAND_seed(RSTRING_PTR(str), RSTRING_LENINT(str));
26
27 return str;
28}
29
30/*
31 * call-seq:
32 * add(str, entropy) -> self
33 *
34 * Mixes the bytes from _str_ into the Pseudo Random Number Generator(PRNG)
35 * state.
36 *
37 * Thus, if the data from _str_ are unpredictable to an adversary, this
38 * increases the uncertainty about the state and makes the PRNG output less
39 * predictable.
40 *
41 * The _entropy_ argument is (the lower bound of) an estimate of how much
42 * randomness is contained in _str_, measured in bytes.
43 *
44 * === Example
45 *
46 * pid = $$
47 * now = Time.now
48 * ary = [now.to_i, now.nsec, 1000, pid]
49 * OpenSSL::Random.add(ary.join, 0.0)
50 * OpenSSL::Random.seed(ary.join)
51 */
52static VALUE
53ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
54{
56 RAND_add(RSTRING_PTR(str), RSTRING_LENINT(str), NUM2DBL(entropy));
57
58 return self;
59}
60
61/*
62 * call-seq:
63 * load_random_file(filename) -> true
64 *
65 * Reads bytes from _filename_ and adds them to the PRNG.
66 */
67static VALUE
68ossl_rand_load_file(VALUE self, VALUE filename)
69{
70 if(!RAND_load_file(StringValueCStr(filename), -1)) {
72 }
73 return Qtrue;
74}
75
76/*
77 * call-seq:
78 * write_random_file(filename) -> true
79 *
80 * Writes a number of random generated bytes (currently 1024) to _filename_
81 * which can be used to initialize the PRNG by calling ::load_random_file in a
82 * later session.
83 */
84static VALUE
85ossl_rand_write_file(VALUE self, VALUE filename)
86{
87 if (RAND_write_file(StringValueCStr(filename)) == -1) {
89 }
90 return Qtrue;
91}
92
93/*
94 * call-seq:
95 * random_bytes(length) -> string
96 *
97 * Generates a String with _length_ number of cryptographically strong
98 * pseudo-random bytes.
99 *
100 * === Example
101 *
102 * OpenSSL::Random.random_bytes(12)
103 * #=> "..."
104 */
105static VALUE
106ossl_rand_bytes(VALUE self, VALUE len)
107{
108 VALUE str;
109 int n = NUM2INT(len);
110 int ret;
111
112 str = rb_str_new(0, n);
113 ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
114 if (ret == 0) {
115 ossl_raise(eRandomError, "RAND_bytes");
116 } else if (ret == -1) {
117 ossl_raise(eRandomError, "RAND_bytes is not supported");
118 }
119
120 return str;
121}
122
123#if defined(HAVE_RAND_PSEUDO_BYTES)
124/*
125 * call-seq:
126 * pseudo_bytes(length) -> string
127 *
128 * Generates a String with _length_ number of pseudo-random bytes.
129 *
130 * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
131 * they are of sufficient length, but are not necessarily unpredictable.
132 *
133 * === Example
134 *
135 * OpenSSL::Random.pseudo_bytes(12)
136 * #=> "..."
137 */
138static VALUE
139ossl_rand_pseudo_bytes(VALUE self, VALUE len)
140{
141 VALUE str;
142 int n = NUM2INT(len);
143
144 str = rb_str_new(0, n);
145 if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
147 }
148
149 return str;
150}
151#endif
152
153#ifdef HAVE_RAND_EGD
154/*
155 * call-seq:
156 * egd(filename) -> true
157 *
158 * Same as ::egd_bytes but queries 255 bytes by default.
159 */
160static VALUE
161ossl_rand_egd(VALUE self, VALUE filename)
162{
163 if (RAND_egd(StringValueCStr(filename)) == -1) {
165 }
166 return Qtrue;
167}
168
169/*
170 * call-seq:
171 * egd_bytes(filename, length) -> true
172 *
173 * Queries the entropy gathering daemon EGD on socket path given by _filename_.
174 *
175 * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in
176 * PRNG.
177 */
178static VALUE
179ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
180{
181 int n = NUM2INT(len);
182
183 if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
185 }
186 return Qtrue;
187}
188#endif /* HAVE_RAND_EGD */
189
190/*
191 * call-seq:
192 * status? => true | false
193 *
194 * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise.
195 */
196static VALUE
197ossl_rand_status(VALUE self)
198{
199 return RAND_status() ? Qtrue : Qfalse;
200}
201
202/*
203 * INIT
204 */
205void
207{
208#if 0
209 mOSSL = rb_define_module("OpenSSL");
211#endif
212
214
216
217 rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
218 rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
219 rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
220 rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
221 rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
222#if defined(HAVE_RAND_PSEUDO_BYTES)
223 rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
224#endif
225#ifdef HAVE_RAND_EGD
226 rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
227 rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
228#endif /* HAVE_RAND_EGD */
229 rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
230}
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module(const char *)
Definition: class.c:785
VALUE rb_define_module_under(VALUE, const char *)
Definition: class.c:810
VALUE rb_eStandardError
Definition: error.c:921
VALUE mOSSL
Definition: ossl.c:231
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
VALUE eOSSLError
Definition: ossl.c:236
void Init_ossl_rand(void)
Definition: ossl_rand.c:206
VALUE eRandomError
Definition: ossl_rand.c:13
VALUE mRandom
Definition: ossl_rand.c:12
#define NULL
#define NUM2DBL(x)
use StringValue() instead")))
#define RSTRING_PTR(str)
#define rb_str_new(str, len)
#define RSTRING_LENINT(str)
const char size_t n
unsigned long VALUE
__inline__ const void *__restrict__ size_t len
void rb_define_module_function(VALUE, const char *, VALUE(*)(), int)
#define NUM2INT(x)
#define Qtrue
#define Qfalse
#define StringValueCStr(v)