blob: ff04cd77c5bb806d284518c77a87f65b8f574965 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * rand.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
5 *
6 * PRNG management routines, thin wrappers.
7 * See the file RATIONALE for a short explanation of why this module was written.
8 *
9 * Reviewed 2001-07-23
10 */
11#include <Python.h>
12
13/*
14 * In order to get the RAND_screen definition from the rand.h
15 * WIN32 or WINDOWS needs to be defined, otherwise we get a
16 * warning.
17 */
Jean-Paul Calderone7ef4ee22008-12-29 16:45:27 -050018#ifdef MS_WINDOWS
19# ifndef WIN32
20# define WIN32
21# endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050022#endif
23#include <openssl/rand.h>
Rick Deanb84bdcf2009-07-08 10:54:54 -050024#include "../util.h"
25
26PyObject *rand_Error;
27
28static void exception_from_error_queue(void)
29{
30 PyObject *errlist = error_queue_to_list();
31 PyErr_SetObject(rand_Error, errlist);
32 Py_DECREF(errlist);
33}
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050034
35static char rand_doc[] = "\n\
36PRNG management routines, thin wrappers.\n\
37See the file RATIONALE for a short explanation of why this module was written.\n\
38";
39
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050040static char rand_add_doc[] = "\n\
41Add data with a given entropy to the PRNG\n\
42\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040043@param buffer: Buffer with random data\n\
44@param entropy: The entropy (in bytes) measurement of the buffer\n\
45@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050046";
47
48static PyObject *
49rand_add(PyObject *spam, PyObject *args)
50{
51 char *buf;
52 int size;
53 double entropy;
54
55 if (!PyArg_ParseTuple(args, "s#d:add", &buf, &size, &entropy))
56 return NULL;
57
58 RAND_add(buf, size, entropy);
59
60 Py_INCREF(Py_None);
61 return Py_None;
62}
63
64static char rand_seed_doc[] = "\n\
65Alias for rand_add, with entropy equal to length\n\
66\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040067@param buffer: Buffer with random data\n\
68@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050069";
70
71static PyObject *
72rand_seed(PyObject *spam, PyObject *args)
73{
74 char *buf;
75 int size;
76
77 if (!PyArg_ParseTuple(args, "s#:seed", &buf, &size))
78 return NULL;
79
80 RAND_seed(buf, size);
81
82 Py_INCREF(Py_None);
83 return Py_None;
84}
85
86static char rand_status_doc[] = "\n\
87Retrieve the status of the PRNG\n\
88\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040089@return: True if the PRNG is seeded enough, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050090";
91
92static PyObject *
93rand_status(PyObject *spam, PyObject *args)
94{
95 if (!PyArg_ParseTuple(args, ":status"))
96 return NULL;
97
98 return PyInt_FromLong((long)RAND_status());
99}
100
101#ifdef MS_WINDOWS
102static char rand_screen_doc[] = "\n\
103Add the current contents of the screen to the PRNG state. Availability:\n\
104Windows.\n\
105\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400106@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500107";
108
109static PyObject *
110rand_screen(PyObject *spam, PyObject *args)
111{
112 if (!PyArg_ParseTuple(args, ":screen"))
113 return NULL;
114
115 RAND_screen();
116 Py_INCREF(Py_None);
117 return Py_None;
118}
119#endif
120
121static char rand_egd_doc[] = "\n\
122Query an entropy gathering daemon (EGD) for random data and add it to the\n\
123PRNG. I haven't found any problems when the socket is missing, the function\n\
124just returns 0.\n\
125\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400126@param path: The path to the EGD socket\n\
127@param bytes: (optional) The number of bytes to read, default is 255\n\
128@returns: The number of bytes read (NB: a value of 0 isn't necessarily an\n\
129 error, check rand.status())\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500130";
131
132static PyObject *
133rand_egd(PyObject *spam, PyObject *args)
134{
135 char *path;
136 int bytes = 255;
137
138 if (!PyArg_ParseTuple(args, "s|i:egd", &path, &bytes))
139 return NULL;
140
141 return PyInt_FromLong((long)RAND_egd_bytes(path, bytes));
142}
143
144static char rand_cleanup_doc[] = "\n\
145Erase the memory used by the PRNG.\n\
146\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400147@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500148";
149
150static PyObject *
151rand_cleanup(PyObject *spam, PyObject *args)
152{
153 if (!PyArg_ParseTuple(args, ":cleanup"))
154 return NULL;
155
156 RAND_cleanup();
157
158 Py_INCREF(Py_None);
159 return Py_None;
160}
161
162static char rand_load_file_doc[] = "\n\
163Seed the PRNG with data from a file\n\
164\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400165@param filename: The file to read data from\n\
166@param maxbytes: (optional) The number of bytes to read, default is\n\
167 to read the entire file\n\
168@return: The number of bytes read\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500169";
170
171static PyObject *
172rand_load_file(PyObject *spam, PyObject *args)
173{
174 char *filename;
175 int maxbytes = -1;
176
177 if (!PyArg_ParseTuple(args, "s|i:load_file", &filename, &maxbytes))
178 return NULL;
179
180 return PyInt_FromLong((long)RAND_load_file(filename, maxbytes));
181}
182
183static char rand_write_file_doc[] = "\n\
184Save PRNG state to a file\n\
185\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400186@param filename: The file to write data to\n\
187@return: The number of bytes written\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500188";
189
190static PyObject *
191rand_write_file(PyObject *spam, PyObject *args)
192{
193 char *filename;
194
195 if (!PyArg_ParseTuple(args, "s:write_file", &filename))
196 return NULL;
197
198 return PyInt_FromLong((long)RAND_write_file(filename));
199}
200
Rick Dean433dc642009-07-07 13:11:55 -0500201static char rand_bytes_doc[] = "\n\
202Get some randomm bytes as a string.\n\
203\n\
204@param num_bytes: The number of bytes to fetch\n\
205@return: A string of random bytes\n\
206";
207
208static PyObject *
209rand_bytes(PyObject *spam, PyObject *args, PyObject *keywds)
210{
211 int num_bytes;
212 static char *kwlist[] = {"num_bytes", NULL};
213 char *buf;
Rick Deanb84bdcf2009-07-08 10:54:54 -0500214 unsigned int rc;
215 PyObject *obj = NULL;
Rick Dean433dc642009-07-07 13:11:55 -0500216
217 if (!PyArg_ParseTupleAndKeywords(args, keywds, "i:bytes", kwlist, &num_bytes))
218 return NULL;
219 if(num_bytes < 0) {
220 PyErr_SetString(PyExc_ValueError, "num_bytes must not be negative");
221 return NULL;
222 }
223 buf = malloc(num_bytes);
224 if (buf == NULL) /* out of memory */
225 return NULL;
Rick Deanb84bdcf2009-07-08 10:54:54 -0500226 rc = RAND_bytes((unsigned char *) buf, num_bytes);
227 if(rc != 1) { /* if unsuccessful */
228 exception_from_error_queue();
229 goto done;
230 }
231 obj = PyString_FromStringAndSize(buf, (unsigned) num_bytes);
232 done:
Rick Dean433dc642009-07-07 13:11:55 -0500233 free(buf);
234 return obj;
235}
236
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500237
238/* Methods in the OpenSSL.rand module */
239static PyMethodDef rand_methods[] = {
240 { "add", (PyCFunction)rand_add, METH_VARARGS, rand_add_doc },
241 { "seed", (PyCFunction)rand_seed, METH_VARARGS, rand_seed_doc },
242 { "status", (PyCFunction)rand_status, METH_VARARGS, rand_status_doc },
243#ifdef MS_WINDOWS
244 { "screen", (PyCFunction)rand_screen, METH_VARARGS, rand_screen_doc },
245#endif
246 { "egd", (PyCFunction)rand_egd, METH_VARARGS, rand_egd_doc },
247 { "cleanup", (PyCFunction)rand_cleanup, METH_VARARGS, rand_cleanup_doc },
248 { "load_file", (PyCFunction)rand_load_file, METH_VARARGS, rand_load_file_doc },
249 { "write_file",(PyCFunction)rand_write_file, METH_VARARGS, rand_write_file_doc },
Rick Dean433dc642009-07-07 13:11:55 -0500250 { "bytes", (PyCFunction)rand_bytes, METH_VARARGS|METH_KEYWORDS, rand_bytes_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500251 { NULL, NULL }
252};
253
254
255/*
256 * Initialize the rand sub module
257 *
258 * Arguments: None
259 * Returns: None
260 */
261void
262initrand(void)
263{
264 PyObject *module;
265
266 ERR_load_RAND_strings();
267
268 if ((module = Py_InitModule3("rand", rand_methods, rand_doc)) == NULL)
269 return;
Rick Deanb84bdcf2009-07-08 10:54:54 -0500270
271 rand_Error = PyErr_NewException("OpenSSL.SSL.Error", NULL, NULL);
272 if (rand_Error == NULL)
273 goto error;
274 if (PyModule_AddObject(module, "Error", rand_Error) != 0)
275 goto error;
276 error:
277 ;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500278}
279