Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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
12 VALUE mRandom;
13 VALUE eRandomError;
14
15 /*
16 * call-seq:
17 * seed(str) -> str
18 *
19 * ::seed is equivalent to ::add where _entropy_ is length of _str_.
20 */
21 static VALUE
22 ossl_rand_seed(VALUE self, VALUE str)
23 {
24 StringValue(str);
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 */
52 static VALUE
53 ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
54 {
55 StringValue(str);
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 */
67 static VALUE
68 ossl_rand_load_file(VALUE self, VALUE filename)
69 {
70 if(!RAND_load_file(StringValueCStr(filename), -1)) {
71 ossl_raise(eRandomError, NULL);
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 */
84 static VALUE
85 ossl_rand_write_file(VALUE self, VALUE filename)
86 {
87 if (RAND_write_file(StringValueCStr(filename)) == -1) {
88 ossl_raise(eRandomError, NULL);
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 */
105 static VALUE
106 ossl_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 */
138 static VALUE
139 ossl_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) {
146 ossl_raise(eRandomError, NULL);
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 */
160 static VALUE
161 ossl_rand_egd(VALUE self, VALUE filename)
162 {
163 if (RAND_egd(StringValueCStr(filename)) == -1) {
164 ossl_raise(eRandomError, NULL);
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 */
178 static VALUE
179 ossl_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) {
184 ossl_raise(eRandomError, NULL);
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 */
196 static VALUE
197 ossl_rand_status(VALUE self)
198 {
199 return RAND_status() ? Qtrue : Qfalse;
200 }
201
202 /*
203 * INIT
204 */
205 void
206 Init_ossl_rand(void)
207 {
208 #if 0
209 mOSSL = rb_define_module("OpenSSL");
210 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
211 #endif
212
213 mRandom = rb_define_module_under(mOSSL, "Random");
214
215 eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
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 }
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
eRandomError
VALUE eRandomError
Definition: ossl_rand.c:13
VALUE
unsigned long VALUE
Definition: ruby.h:102
RSTRING_LENINT
#define RSTRING_LENINT(str)
Definition: ruby.h:1017
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
Init_ossl_rand
void Init_ossl_rand(void)
Definition: ossl_rand.c:206
ossl.h
StringValue
use StringValue() instead")))
Qfalse
#define Qfalse
Definition: ruby.h:467
NULL
#define NULL
Definition: _sdbm.c:101
mOSSL
VALUE mOSSL
Definition: ossl.c:231
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
mRandom
VALUE mRandom
Definition: ossl_rand.c:12
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
rb_define_module_function
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1771
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
NUM2DBL
#define NUM2DBL(x)
Definition: ruby.h:774
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919