diff options
Diffstat (limited to 'src/lib/tlslite/utils/entropy.c')
-rwxr-xr-x | src/lib/tlslite/utils/entropy.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/lib/tlslite/utils/entropy.c b/src/lib/tlslite/utils/entropy.c new file mode 100755 index 000000000..c627794d2 --- /dev/null +++ b/src/lib/tlslite/utils/entropy.c @@ -0,0 +1,173 @@ + +#include "Python.h" + + +#ifdef MS_WINDOWS + +/* The following #define is not needed on VC6 with the Platform SDK, and it +may not be needed on VC7, I'm not sure. I don't think it hurts anything.*/ +#define _WIN32_WINNT 0x0400 + +#include <windows.h> + + +typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\ + LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\ + DWORD dwFlags ); +typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\ + BYTE *pbBuffer ); +typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv,\ + DWORD dwFlags); + + +static PyObject* entropy(PyObject *self, PyObject *args) +{ + int howMany = 0; + HINSTANCE hAdvAPI32 = NULL; + CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL; + CRYPTGENRANDOM pCryptGenRandom = NULL; + CRYPTRELEASECONTEXT pCryptReleaseContext = NULL; + HCRYPTPROV hCryptProv = 0; + unsigned char* bytes = NULL; + PyObject* returnVal = NULL; + + + /* Read arguments */ + if (!PyArg_ParseTuple(args, "i", &howMany)) + return(NULL); + + /* Obtain handle to the DLL containing CryptoAPI + This should not fail */ + if( (hAdvAPI32 = GetModuleHandle("advapi32.dll")) == NULL) { + PyErr_Format(PyExc_SystemError, + "Advapi32.dll not found"); + return NULL; + } + + /* Obtain pointers to the CryptoAPI functions + This will fail on some early version of Win95 */ + pCryptAcquireContextA = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32,\ + "CryptAcquireContextA"); + pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32,\ + "CryptGenRandom"); + pCryptReleaseContext = (CRYPTRELEASECONTEXT) GetProcAddress(hAdvAPI32,\ + "CryptReleaseContext"); + if (pCryptAcquireContextA == NULL || pCryptGenRandom == NULL || + pCryptReleaseContext == NULL) { + PyErr_Format(PyExc_NotImplementedError, + "CryptoAPI not available on this version of Windows"); + return NULL; + } + + /* Allocate bytes */ + if ((bytes = (unsigned char*)PyMem_Malloc(howMany)) == NULL) + return PyErr_NoMemory(); + + + /* Acquire context */ + if(!pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + PyErr_Format(PyExc_SystemError, + "CryptAcquireContext failed, error %d", GetLastError()); + PyMem_Free(bytes); + return NULL; + } + + /* Get random data */ + if(!pCryptGenRandom(hCryptProv, howMany, bytes)) { + PyErr_Format(PyExc_SystemError, + "CryptGenRandom failed, error %d", GetLastError()); + PyMem_Free(bytes); + CryptReleaseContext(hCryptProv, 0); + return NULL; + } + + /* Build return value */ + returnVal = Py_BuildValue("s#", bytes, howMany); + PyMem_Free(bytes); + + /* Release context */ + if (!pCryptReleaseContext(hCryptProv, 0)) { + PyErr_Format(PyExc_SystemError, + "CryptReleaseContext failed, error %d", GetLastError()); + return NULL; + } + + return returnVal; +} + +#elif defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL_H) + +#include <unistd.h> +#include <fcntl.h> + +static PyObject* entropy(PyObject *self, PyObject *args) +{ + int howMany; + int fd; + unsigned char* bytes = NULL; + PyObject* returnVal = NULL; + + + /* Read arguments */ + if (!PyArg_ParseTuple(args, "i", &howMany)) + return(NULL); + + /* Allocate bytes */ + if ((bytes = (unsigned char*)PyMem_Malloc(howMany)) == NULL) + return PyErr_NoMemory(); + + /* Open device */ + if ((fd = open("/dev/urandom", O_RDONLY, 0)) == -1) { + PyErr_Format(PyExc_NotImplementedError, + "No entropy source found"); + PyMem_Free(bytes); + return NULL; + } + + /* Get random data */ + if (read(fd, bytes, howMany) < howMany) { + PyErr_Format(PyExc_SystemError, + "Reading from /dev/urandom failed"); + PyMem_Free(bytes); + close(fd); + return NULL; + } + + /* Build return value */ + returnVal = Py_BuildValue("s#", bytes, howMany); + PyMem_Free(bytes); + + /* Close device */ + close(fd); + + return returnVal; +} + +#else + +static PyObject* entropy(PyObject *self, PyObject *args) +{ + PyErr_Format(PyExc_NotImplementedError, + "Function not supported"); + return NULL; +} + +#endif + + + +/* List of functions exported by this module */ + +static struct PyMethodDef entropy_functions[] = { + {"entropy", (PyCFunction)entropy, METH_VARARGS, "Return a string of random bytes produced by a platform-specific\nentropy source."}, + {NULL, NULL} /* Sentinel */ +}; + + +/* Initialize this module. */ + +PyMODINIT_FUNC initentropy(void) +{ + Py_InitModule("entropy", entropy_functions); +}
\ No newline at end of file |