Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
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  */
21 static VALUE
22 ossl_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  */
52 static VALUE
53 ossl_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  */
67 static VALUE
68 ossl_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  */
84 static VALUE
85 ossl_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  */
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) {
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) {
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) {
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
207 {
208 #if 0
209  mOSSL = rb_define_module("OpenSSL");
211 #endif
212 
213  mRandom = rb_define_module_under(mOSSL, "Random");
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 }
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
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
StringValue
use StringValue() instead")))
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
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
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.2.h:6112
NUM2DBL
#define NUM2DBL(x)
Definition: ruby.h:774
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:921
n
const char size_t n
Definition: rb_mjit_min_header-2.7.2.h:5452