blob: e2f6373461f2a20309da3882e70d885450bb3fa5 [file] [log] [blame]
Jean-Paul Calderone8210b922013-02-09 09:03:18 -08001"""
2PRNG management routines, thin wrappers.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -08003"""
4
Alex Gaynor8a1de8d2017-07-06 22:40:07 -04005import warnings
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05006from functools import partial
Jean-Paul Calderone8210b922013-02-09 09:03:18 -08007
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05008from six import integer_types as _integer_types
9
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050010from OpenSSL._util import (
11 ffi as _ffi,
12 lib as _lib,
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -040013 exception_from_error_queue as _exception_from_error_queue,
14 path_string as _path_string)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050015
16
Alex Gaynor8a1de8d2017-07-06 22:40:07 -040017warnings.warn(
18 "OpenSSL.rand is deprecated - you should use os.urandom instead",
19 DeprecationWarning, stacklevel=3
20)
21
22
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080023class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050024 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020025 An error occurred in an :mod:`OpenSSL.rand` API.
26
27 If the current RAND method supports any errors, this is raised when needed.
28 The default method does not raise this when the entropy pool is depleted.
29
30 Whenever this exception is raised directly, it has a list of error messages
31 from the OpenSSL error queue, where each item is a tuple *(lib, function,
32 reason)*. Here *lib*, *function* and *reason* are all strings, describing
33 where and what the problem is.
34
35 See :manpage:`err(3)` for more information.
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050036 """
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080037
Alex Chanc6077062016-11-18 13:53:39 +000038
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050039_raise_current_error = partial(_exception_from_error_queue, Error)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080040
41_unspecified = object()
42
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -050043_builtin_bytes = bytes
44
Alex Gaynorca87ff62015-09-04 23:31:03 -040045
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080046def bytes(num_bytes):
47 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020048 Get some random bytes from the PRNG as a string.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080049
Hynek Schlawack80d005f2015-10-20 18:34:13 +020050 This is a wrapper for the C function ``RAND_bytes``.
51
52 :param num_bytes: The number of bytes to fetch.
53
54 :return: A string of random bytes.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080055 """
Jean-Paul Calderone53a5e132014-01-11 08:31:19 -050056 if not isinstance(num_bytes, _integer_types):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080057 raise TypeError("num_bytes must be an integer")
58
59 if num_bytes < 0:
60 raise ValueError("num_bytes must not be negative")
61
Paul Kehrer9f9113a2016-09-20 20:10:25 -050062 result_buffer = _ffi.new("unsigned char[]", num_bytes)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050063 result_code = _lib.RAND_bytes(result_buffer, num_bytes)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080064 if result_code == -1:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050065 # TODO: No tests for this code path. Triggering a RAND_bytes failure
66 # might involve supplying a custom ENGINE? That's hard.
67 _raise_current_error()
68
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050069 return _ffi.buffer(result_buffer)[:]
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080070
71
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080072def add(buffer, entropy):
73 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020074 Mix bytes from *string* into the PRNG state.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080075
Hynek Schlawack80d005f2015-10-20 18:34:13 +020076 The *entropy* argument is (the lower bound of) an estimate of how much
77 randomness is contained in *string*, measured in bytes.
78
79 For more information, see e.g. :rfc:`1750`.
80
81 :param buffer: Buffer with random data.
82 :param entropy: The entropy (in bytes) measurement of the buffer.
83
84 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080085 """
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -050086 if not isinstance(buffer, _builtin_bytes):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080087 raise TypeError("buffer must be a byte string")
88
89 if not isinstance(entropy, int):
90 raise TypeError("entropy must be an integer")
91
92 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050093 _lib.RAND_add(buffer, len(buffer), entropy)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080094
95
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080096def seed(buffer):
97 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020098 Equivalent to calling :func:`add` with *entropy* as the length of *buffer*.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080099
100 :param buffer: Buffer with random data
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200101
102 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800103 """
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -0500104 if not isinstance(buffer, _builtin_bytes):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800105 raise TypeError("buffer must be a byte string")
106
107 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500108 _lib.RAND_seed(buffer, len(buffer))
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800109
110
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800111def status():
112 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200113 Check whether the PRNG has been seeded with enough data.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800114
Alex Chan6b69c552016-10-24 16:34:41 +0100115 :return: 1 if the PRNG is seeded enough, 0 otherwise.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800116 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500117 return _lib.RAND_status()
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800118
119
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800120def cleanup():
121 """
122 Erase the memory used by the PRNG.
123
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200124 This is a wrapper for the C function ``RAND_cleanup``.
125
126 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800127 """
128 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500129 _lib.RAND_cleanup()
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800130
131
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800132def load_file(filename, maxbytes=_unspecified):
133 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200134 Read *maxbytes* of data from *filename* and seed the PRNG with it.
135
136 Read the whole file if *maxbytes* is not specified or negative.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800137
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400138 :param filename: The file to read data from (``bytes`` or ``unicode``).
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200139 :param maxbytes: (optional) The number of bytes to read. Default is to
140 read the entire file.
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400141
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800142 :return: The number of bytes read
143 """
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -0400144 filename = _path_string(filename)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800145
146 if maxbytes is _unspecified:
147 maxbytes = -1
148 elif not isinstance(maxbytes, int):
149 raise TypeError("maxbytes must be an integer")
150
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500151 return _lib.RAND_load_file(filename, maxbytes)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800152
153
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800154def write_file(filename):
155 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200156 Write a number of random bytes (currently 1024) to the file *path*. This
157 file can then be used with :func:`load_file` to seed the PRNG again.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800158
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400159 :param filename: The file to write data to (``bytes`` or ``unicode``).
160
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200161 :return: The number of bytes written.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800162 """
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -0400163 filename = _path_string(filename)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500164 return _lib.RAND_write_file(filename)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800165
166
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800167# TODO There are no tests for the RAND strings being loaded, whatever that
168# means.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500169_lib.ERR_load_RAND_strings()