Ruby: ext/openssl/ossl_rand.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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 */
21static VALUE
22ossl_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 */
52static VALUE
53ossl_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 */
67static VALUE
68ossl_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 */
84static VALUE
85ossl_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 */
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#ifdef HAVE_RAND_EGD
124/*
125 * call-seq:
126 * egd(filename) -> true
127 *
128 * Same as ::egd_bytes but queries 255 bytes by default.
129 */
130static VALUE
131ossl_rand_egd(VALUE self, VALUE filename)
132{
133 if (RAND_egd(StringValueCStr(filename)) == -1) {
134 ossl_raise(eRandomError, NULL);
135 }
136 return Qtrue;
137}
138
139/*
140 * call-seq:
141 * egd_bytes(filename, length) -> true
142 *
143 * Queries the entropy gathering daemon EGD on socket path given by _filename_.
144 *
145 * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in
146 * PRNG.
147 */
148static VALUE
149ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
150{
151 int n = NUM2INT(len);
152
153 if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
154 ossl_raise(eRandomError, NULL);
155 }
156 return Qtrue;
157}
158#endif /* HAVE_RAND_EGD */
159
160/*
161 * call-seq:
162 * status? => true | false
163 *
164 * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise.
165 */
166static VALUE
167ossl_rand_status(VALUE self)
168{
169 return RAND_status() ? Qtrue : Qfalse;
170}
171
172/*
173 * INIT
174 */
175void
176Init_ossl_rand(void)
177{
178#if 0
179 mOSSL = rb_define_module("OpenSSL");
180 eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
181#endif
182
183 mRandom = rb_define_module_under(mOSSL, "Random");
184
185 eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
186
187 rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
188 rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
189 rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
190 rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
191 rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
192#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
193 rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes");
194#endif
195#ifdef HAVE_RAND_EGD
196 rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
197 rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
198#endif /* HAVE_RAND_EGD */
199 rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
200}
rb_define_module_function
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
Definition: cxxanyargs.hpp:672
NUM2DBL
#define NUM2DBL
Definition: double.h:27
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
rb_singleton_class
VALUE rb_singleton_class(VALUE obj)
Returns the singleton class of obj.
Definition: class.c:1924
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:797
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:871
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:895
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1999
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1054
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
NUM2INT
#define NUM2INT
Definition: int.h:44
filename
const char * filename
Definition: ioapi.h:137
mOSSL
VALUE mOSSL
Definition: ossl.c:231
ossl_raise
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:293
eOSSLError
VALUE eOSSLError
Definition: ossl.c:236
ossl.h
Init_ossl_rand
void Init_ossl_rand(void)
Definition: ossl_rand.c:176
eRandomError
VALUE eRandomError
Definition: ossl_rand.c:13
mRandom
VALUE mRandom
Definition: ossl_rand.c:12
NULL
#define NULL
Definition: regenc.h:69
StringValue
#define StringValue(v)
Definition: rstring.h:50
StringValueCStr
#define StringValueCStr(v)
Definition: rstring.h:52
Qtrue
#define Qtrue
Definition: special_consts.h:52
Qfalse
#define Qfalse
Definition: special_consts.h:50
VALUE
unsigned long VALUE
Definition: value.h:38