blob: cf2053f67b33ff19e5e259fde22d617fef811907 [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
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05005from functools import partial
Jean-Paul Calderone8210b922013-02-09 09:03:18 -08006
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05007from six import integer_types as _integer_types
8
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05009from OpenSSL._util import (
10 ffi as _ffi,
11 lib as _lib,
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -040012 exception_from_error_queue as _exception_from_error_queue,
13 path_string as _path_string)
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050014
15
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080016class Error(Exception):
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050017 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020018 An error occurred in an :mod:`OpenSSL.rand` API.
19
20 If the current RAND method supports any errors, this is raised when needed.
21 The default method does not raise this when the entropy pool is depleted.
22
23 Whenever this exception is raised directly, it has a list of error messages
24 from the OpenSSL error queue, where each item is a tuple *(lib, function,
25 reason)*. Here *lib*, *function* and *reason* are all strings, describing
26 where and what the problem is.
27
28 See :manpage:`err(3)` for more information.
Jean-Paul Calderone511cde02013-12-29 10:31:13 -050029 """
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080030
Alex Chanc6077062016-11-18 13:53:39 +000031
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050032_raise_current_error = partial(_exception_from_error_queue, Error)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080033
34_unspecified = object()
35
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -050036_builtin_bytes = bytes
37
Alex Gaynorca87ff62015-09-04 23:31:03 -040038
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080039def bytes(num_bytes):
40 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020041 Get some random bytes from the PRNG as a string.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080042
Hynek Schlawack80d005f2015-10-20 18:34:13 +020043 This is a wrapper for the C function ``RAND_bytes``.
44
45 :param num_bytes: The number of bytes to fetch.
46
47 :return: A string of random bytes.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080048 """
Jean-Paul Calderone53a5e132014-01-11 08:31:19 -050049 if not isinstance(num_bytes, _integer_types):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080050 raise TypeError("num_bytes must be an integer")
51
52 if num_bytes < 0:
53 raise ValueError("num_bytes must not be negative")
54
Paul Kehrer9f9113a2016-09-20 20:10:25 -050055 result_buffer = _ffi.new("unsigned char[]", num_bytes)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050056 result_code = _lib.RAND_bytes(result_buffer, num_bytes)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080057 if result_code == -1:
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050058 # TODO: No tests for this code path. Triggering a RAND_bytes failure
59 # might involve supplying a custom ENGINE? That's hard.
60 _raise_current_error()
61
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050062 return _ffi.buffer(result_buffer)[:]
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080063
64
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080065def add(buffer, entropy):
66 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020067 Mix bytes from *string* into the PRNG state.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080068
Hynek Schlawack80d005f2015-10-20 18:34:13 +020069 The *entropy* argument is (the lower bound of) an estimate of how much
70 randomness is contained in *string*, measured in bytes.
71
72 For more information, see e.g. :rfc:`1750`.
73
74 :param buffer: Buffer with random data.
75 :param entropy: The entropy (in bytes) measurement of the buffer.
76
77 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080078 """
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -050079 if not isinstance(buffer, _builtin_bytes):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080080 raise TypeError("buffer must be a byte string")
81
82 if not isinstance(entropy, int):
83 raise TypeError("entropy must be an integer")
84
85 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -050086 _lib.RAND_add(buffer, len(buffer), entropy)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080087
88
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080089def seed(buffer):
90 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +020091 Equivalent to calling :func:`add` with *entropy* as the length of *buffer*.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080092
93 :param buffer: Buffer with random data
Hynek Schlawack80d005f2015-10-20 18:34:13 +020094
95 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080096 """
Jean-Paul Calderonee80a25a2014-01-09 14:33:42 -050097 if not isinstance(buffer, _builtin_bytes):
Jean-Paul Calderone8210b922013-02-09 09:03:18 -080098 raise TypeError("buffer must be a byte string")
99
100 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500101 _lib.RAND_seed(buffer, len(buffer))
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800102
103
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800104def status():
105 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200106 Check whether the PRNG has been seeded with enough data.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800107
Alex Chan6b69c552016-10-24 16:34:41 +0100108 :return: 1 if the PRNG is seeded enough, 0 otherwise.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800109 """
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500110 return _lib.RAND_status()
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800111
112
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800113def cleanup():
114 """
115 Erase the memory used by the PRNG.
116
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200117 This is a wrapper for the C function ``RAND_cleanup``.
118
119 :return: :obj:`None`
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800120 """
121 # TODO Nothing tests this call actually being made, or made properly.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500122 _lib.RAND_cleanup()
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800123
124
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800125def load_file(filename, maxbytes=_unspecified):
126 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200127 Read *maxbytes* of data from *filename* and seed the PRNG with it.
128
129 Read the whole file if *maxbytes* is not specified or negative.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800130
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400131 :param filename: The file to read data from (``bytes`` or ``unicode``).
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200132 :param maxbytes: (optional) The number of bytes to read. Default is to
133 read the entire file.
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400134
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800135 :return: The number of bytes read
136 """
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -0400137 filename = _path_string(filename)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800138
139 if maxbytes is _unspecified:
140 maxbytes = -1
141 elif not isinstance(maxbytes, int):
142 raise TypeError("maxbytes must be an integer")
143
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500144 return _lib.RAND_load_file(filename, maxbytes)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800145
146
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800147def write_file(filename):
148 """
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200149 Write a number of random bytes (currently 1024) to the file *path*. This
150 file can then be used with :func:`load_file` to seed the PRNG again.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800151
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -0400152 :param filename: The file to write data to (``bytes`` or ``unicode``).
153
Hynek Schlawack80d005f2015-10-20 18:34:13 +0200154 :return: The number of bytes written.
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800155 """
Jean-Paul Calderonecbb68cc2015-04-11 12:41:30 -0400156 filename = _path_string(filename)
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500157 return _lib.RAND_write_file(filename)
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800158
159
Jean-Paul Calderone8210b922013-02-09 09:03:18 -0800160# TODO There are no tests for the RAND strings being loaded, whatever that
161# means.
Jean-Paul Calderone6037d072013-12-28 18:04:00 -0500162_lib.ERR_load_RAND_strings()