Ruby  2.5.0dev(2017-10-22revision60238)
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 {
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  rb_check_safe_obj(filename);
71 
72  if(!RAND_load_file(StringValueCStr(filename), -1)) {
74  }
75  return Qtrue;
76 }
77 
78 /*
79  * call-seq:
80  * write_random_file(filename) -> true
81  *
82  * Writes a number of random generated bytes (currently 1024) to _filename_
83  * which can be used to initialize the PRNG by calling ::load_random_file in a
84  * later session.
85  */
86 static VALUE
87 ossl_rand_write_file(VALUE self, VALUE filename)
88 {
89  rb_check_safe_obj(filename);
90 
91  if (RAND_write_file(StringValueCStr(filename)) == -1) {
93  }
94  return Qtrue;
95 }
96 
97 /*
98  * call-seq:
99  * random_bytes(length) -> string
100  *
101  * Generates a String with _length_ number of cryptographically strong
102  * pseudo-random bytes.
103  *
104  * === Example
105  *
106  * OpenSSL::Random.random_bytes(12)
107  * #=> "..."
108  */
109 static VALUE
110 ossl_rand_bytes(VALUE self, VALUE len)
111 {
112  VALUE str;
113  int n = NUM2INT(len);
114  int ret;
115 
116  str = rb_str_new(0, n);
117  ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
118  if (ret == 0) {
119  ossl_raise(eRandomError, "RAND_bytes");
120  } else if (ret == -1) {
121  ossl_raise(eRandomError, "RAND_bytes is not supported");
122  }
123 
124  return str;
125 }
126 
127 #if defined(HAVE_RAND_PSEUDO_BYTES)
128 /*
129  * call-seq:
130  * pseudo_bytes(length) -> string
131  *
132  * Generates a String with _length_ number of pseudo-random bytes.
133  *
134  * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
135  * they are of sufficient length, but are not necessarily unpredictable.
136  *
137  * === Example
138  *
139  * OpenSSL::Random.pseudo_bytes(12)
140  * #=> "..."
141  */
142 static VALUE
143 ossl_rand_pseudo_bytes(VALUE self, VALUE len)
144 {
145  VALUE str;
146  int n = NUM2INT(len);
147 
148  str = rb_str_new(0, n);
149  if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
151  }
152 
153  return str;
154 }
155 #endif
156 
157 #ifdef HAVE_RAND_EGD
158 /*
159  * call-seq:
160  * egd(filename) -> true
161  *
162  * Same as ::egd_bytes but queries 255 bytes by default.
163  */
164 static VALUE
165 ossl_rand_egd(VALUE self, VALUE filename)
166 {
167  rb_check_safe_obj(filename);
168 
169  if (RAND_egd(StringValueCStr(filename)) == -1) {
171  }
172  return Qtrue;
173 }
174 
175 /*
176  * call-seq:
177  * egd_bytes(filename, length) -> true
178  *
179  * Queries the entropy gathering daemon EGD on socket path given by _filename_.
180  *
181  * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in
182  * PRNG.
183  */
184 static VALUE
185 ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
186 {
187  int n = NUM2INT(len);
188 
189  rb_check_safe_obj(filename);
190 
191  if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
193  }
194  return Qtrue;
195 }
196 #endif /* HAVE_RAND_EGD */
197 
198 /*
199  * call-seq:
200  * status? => true | false
201  *
202  * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise.
203  */
204 static VALUE
205 ossl_rand_status(VALUE self)
206 {
207  return RAND_status() ? Qtrue : Qfalse;
208 }
209 
210 /*
211  * INIT
212  */
213 void
215 {
216 #if 0
217  mOSSL = rb_define_module("OpenSSL");
219 #endif
220 
221  mRandom = rb_define_module_under(mOSSL, "Random");
222 
224 
225  rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
226  rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
227  rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
228  rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
229  rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
230 #if defined(HAVE_RAND_PSEUDO_BYTES)
231  rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
232 #endif
233 #ifdef HAVE_RAND_EGD
234  rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
235  rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
236 #endif /* HAVE_RAND_EGD */
237  rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
238 }
VALUE mOSSL
Definition: ossl.c:231
#define NUM2INT(x)
Definition: ruby.h:684
#define Qtrue
Definition: ruby.h:437
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
void Init_ossl_rand(void)
Definition: ossl_rand.c:214
#define NUM2DBL(x)
Definition: ruby.h:743
VALUE eOSSLError
Definition: ossl.c:236
#define Qfalse
Definition: ruby.h:436
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1731
VALUE rb_eStandardError
Definition: error.c:799
unsigned long VALUE
Definition: ruby.h:85
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE eRandomError
Definition: ossl_rand.c:13
VALUE mRandom
Definition: ossl_rand.c:12
void rb_check_safe_obj(VALUE)
Definition: safe.c:117
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
#define RSTRING_LENINT(str)
Definition: ruby.h:983
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define NULL
Definition: _sdbm.c:102
#define StringValue(v)
Definition: ruby.h:569
VALUE rb_str_new(const char *, long)
Definition: string.c:737