From: Toni A. <to...@so...> - 2003-02-11 03:53:13
|
Hi, i'd like to access the OpenSSL PRNG, but neither RAND_bytes() nor RAND_pseudo_bytes() have been implemented in OpenSSL.rand, so here is a patch which adds them. Index: src/rand/rand.c =================================================================== RCS file: /u/cvs/pyopenssl/pyOpenSSL/src/rand/rand.c,v retrieving revision 1.10 diff -u -U1 -r1.10 rand.c --- src/rand/rand.c 8 Jul 2002 11:06:01 -0000 1.10 +++ src/rand/rand.c 11 Feb 2003 03:12:11 -0000 @@ -11,2 +11,14 @@ #include <Python.h> +#include "../util.h" + +PyObject *rand_Error; + +#ifdef exception_from_error_queue +# undef exception_from_error_queue +#endif +#define exception_from_error_queue() do { \ + PyObject *errlist = error_queue_to_list(); \ + PyErr_SetObject(rand_Error, errlist); \ + Py_DECREF(errlist); \ +} while (0) @@ -79,2 +91,88 @@ +/* + RAND_bytes() is available in all versions of SSLeay and + OpenSSL. It has a return value since OpenSSL 0.9.5. + RAND_pseudo_bytes() was added in OpenSSL 0.9.5. +*/ +static char rand_bytes_doc[] = "\n\ +Produce cryptographically strong pseudo-random bytes.\n\ +An error occurs if the PRNG has not been seeded with enough\n\ +randomness to ensure an unpredictable byte sequence.\n\ +\n\ +Arguments: spam - Always NULL\n\ + args - The Python argument tuple, should be:\n\ + num - How many bytes to produce\n\ +Returns: A string of pseudo-random bytes. Throws a rand.Error\n\ + exception if there wasn't enough randomness\n\ +"; + +static PyObject * +rand_bytes(PyObject *spam, PyObject *args) +{ + int num, rc; + PyObject *rv; + unsigned char *buf; + + if (!PyArg_ParseTuple(args, "i:bytes", &num)) + return NULL; + + buf = (unsigned char *) PyMem_NEW(unsigned char *, num); + if (!buf) { + PyErr_NoMemory(); + return NULL; + } + + rc = RAND_bytes(buf, num); + if (rc != 1) { + exception_from_error_queue(); + return NULL; + } + rv = Py_BuildValue("s#", buf, num); + PyMem_DEL(buf); + return rv; +} + +static char rand_pseudo_bytes_doc[] = "\n\ +Produce pseudo-random bytes.\n\ +Pseudo-random byte sequences generated by pseudo_bytes()\n\ +will be unique if they are of sufficient length, but are not\n\ +necessarily unpredictable. They can be used for non-cryptographic\n\ +purposes and for certain purposes in cryptographic protocols, but\n\ +usually not for key generation etc.\n\ +\n\ +Arguments: spam - Always NULL\n\ + args - The Python argument tuple, should be:\n\ + num - How many bytes to produce\n\ +Returns: A string of pseudo-random bytes\n\ +"; + +static PyObject * +rand_pseudo_bytes(PyObject *spam, PyObject *args) +{ + int num, rc; + PyObject *rv; + unsigned char *buf; + + if (!PyArg_ParseTuple(args, "i:pseudo_bytes", &num)) + return NULL; + + buf = (unsigned char *) PyMem_NEW(unsigned char *, num); + if (!buf) { + PyErr_NoMemory(); + return NULL; + } + + rc = RAND_pseudo_bytes(buf, num); + /* + RAND_pseudo_bytes() returns 1 if the bytes generated are + cryptographically strong, 0 otherwise. + + Maybe this should return a list in order to pass the + RAND_pseudo_bytes() return value. + */ + rv = Py_BuildValue("s#", buf, num); + PyMem_DEL(buf); + return rv; +} + static char rand_status_doc[] = "\n\ @@ -211,2 +309,4 @@ { "seed", (PyCFunction)rand_seed, METH_VARARGS, rand_seed_doc }, + { "bytes", (PyCFunction)rand_bytes, METH_VARARGS, rand_bytes_doc }, + { "pseudo_bytes", (PyCFunction)rand_pseudo_bytes, METH_VARARGS, rand_pseudo_bytes_doc }, { "status", (PyCFunction)rand_status, METH_VARARGS, rand_status_doc }, @@ -238,2 +338,11 @@ return; + + rand_Error = PyErr_NewException("rand.Error", NULL, NULL); + if (rand_Error == NULL) + goto error; + if (PyModule_AddObject(module, "Error", rand_Error) != 0) + goto error; + +error: + ; } -- Toni Andjelkovic <to...@so...> |