summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2011-05-24 10:05:19 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2011-05-24 10:05:19 (GMT)
commit99c8b1614319ce0161835ade223cdd395f0126d4 (patch)
treeabe0d388da458164d5fe6fcfe6a3cac5619e531d
parentb7b1930fe374317c380e49add9fb4cc2267367e9 (diff)
downloadcpython-99c8b1614319ce0161835ade223cdd395f0126d4.zip
cpython-99c8b1614319ce0161835ade223cdd395f0126d4.tar.gz
cpython-99c8b1614319ce0161835ade223cdd395f0126d4.tar.bz2
Issue #12049: Add RAND_bytes() and RAND_pseudo_bytes() functions to the ssl
module.
-rw-r--r--Doc/library/ssl.rst20
-rw-r--r--Doc/whatsnew/3.3.rst10
-rw-r--r--Lib/ssl.py2
-rw-r--r--Lib/test/test_ssl.py8
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_ssl.c67
6 files changed, 106 insertions, 4 deletions
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
index 5ece8cf..a528a03 100644
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -162,6 +162,20 @@ instead.
Random generation
^^^^^^^^^^^^^^^^^
+.. function:: RAND_bytes(num)
+
+ Returns *num* cryptographically strong pseudo-random bytes.
+
+ .. versionadded:: 3.3
+
+.. function:: RAND_pseudo_bytes(num)
+
+ Returns (bytes, is_cryptographic): bytes are *num* pseudo-random bytes,
+ is_cryptographic is True if the bytes generated are cryptographically
+ strong.
+
+ .. versionadded:: 3.3
+
.. function:: RAND_status()
Returns True if the SSL pseudo-random number generator has been seeded with
@@ -171,7 +185,7 @@ Random generation
.. function:: RAND_egd(path)
- If you are running an entropy-gathering daemon (EGD) somewhere, and ``path``
+ If you are running an entropy-gathering daemon (EGD) somewhere, and *path*
is the pathname of a socket connection open to it, this will read 256 bytes
of randomness from the socket, and add it to the SSL pseudo-random number
generator to increase the security of generated secret keys. This is
@@ -182,8 +196,8 @@ Random generation
.. function:: RAND_add(bytes, entropy)
- Mixes the given ``bytes`` into the SSL pseudo-random number generator. The
- parameter ``entropy`` (a float) is a lower bound on the entropy contained in
+ Mixes the given *bytes* into the SSL pseudo-random number generator. The
+ parameter *entropy* (a float) is a lower bound on the entropy contained in
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
information on sources of entropy.
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index d442665..529665f 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -152,6 +152,16 @@ signal
instead of a RuntimeError: OSError has an errno attribute.
+ssl
+---
+
+The :mod:`ssl` module has new functions:
+
+ * :func:`~ssl.RAND_bytes`: generate cryptographically strong
+ pseudo-random bytes.
+ * :func:`~ssl.RAND_pseudo_bytes`: generate pseudo-random bytes.
+
+
Optimizations
=============
diff --git a/Lib/ssl.py b/Lib/ssl.py
index f938dc9..1a7f599 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -63,7 +63,7 @@ from _ssl import OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_INFO, OPENSSL_VERSION
from _ssl import _SSLContext, SSLError
from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
from _ssl import OP_ALL, OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1
-from _ssl import RAND_status, RAND_egd, RAND_add
+from _ssl import RAND_status, RAND_egd, RAND_add, RAND_bytes, RAND_pseudo_bytes
from _ssl import (
SSL_ERROR_ZERO_RETURN,
SSL_ERROR_WANT_READ,
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index aef51e3..8c21975 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -102,6 +102,14 @@ class BasicSocketTests(unittest.TestCase):
sys.stdout.write("\n RAND_status is %d (%s)\n"
% (v, (v and "sufficient randomness") or
"insufficient randomness"))
+
+ data, is_cryptographic = ssl.RAND_pseudo_bytes(16)
+ self.assertEqual(len(data), 16)
+ self.assertEqual(is_cryptographic, v == 1)
+ if v:
+ data = ssl.RAND_bytes(16)
+ self.assertEqual(len(data), 16)
+
try:
ssl.RAND_egd(1)
except TypeError:
diff --git a/Misc/NEWS b/Misc/NEWS
index 22c3cf4..967e2ef 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -156,6 +156,9 @@ Core and Builtins
Library
-------
+- Issue #12049: Add RAND_bytes() and RAND_pseudo_bytes() functions to the ssl
+ module.
+
- Issue #12125: fixed the failures under Solaris due to improper test cleanup.
- Issue #6501: os.device_encoding() returns None on Windows if the application
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index dc11fc8..3f631e3 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -1887,6 +1887,69 @@ Mix string into the OpenSSL PRNG state. entropy (a float) is a lower\n\
bound on the entropy contained in string. See RFC 1750.");
static PyObject *
+PySSL_RAND(int len, int pseudo)
+{
+ int ok;
+ PyObject *bytes;
+ unsigned long err;
+ const char *errstr;
+ PyObject *v;
+
+ bytes = PyBytes_FromStringAndSize(NULL, len);
+ if (bytes == NULL)
+ return NULL;
+ if (pseudo) {
+ ok = RAND_pseudo_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
+ if (ok == 0 || ok == 1)
+ return Py_BuildValue("NO", bytes, ok == 1 ? Py_True : Py_False);
+ }
+ else {
+ ok = RAND_bytes((unsigned char*)PyBytes_AS_STRING(bytes), len);
+ if (ok == 1)
+ return bytes;
+ }
+ Py_DECREF(bytes);
+
+ err = ERR_get_error();
+ errstr = ERR_reason_error_string(err);
+ v = Py_BuildValue("(ks)", err, errstr);
+ if (v != NULL) {
+ PyErr_SetObject(PySSLErrorObject, v);
+ Py_DECREF(v);
+ }
+ return NULL;
+}
+
+static PyObject *
+PySSL_RAND_bytes(PyObject *self, PyObject *args)
+{
+ int len;
+ if (!PyArg_ParseTuple(args, "i:RAND_bytes", &len))
+ return NULL;
+ return PySSL_RAND(len, 0);
+}
+
+PyDoc_STRVAR(PySSL_RAND_bytes_doc,
+"RAND_bytes(n) -> bytes\n\
+\n\
+Generate n cryptographically strong pseudo-random bytes.");
+
+static PyObject *
+PySSL_RAND_pseudo_bytes(PyObject *self, PyObject *args)
+{
+ int len;
+ if (!PyArg_ParseTuple(args, "i:RAND_pseudo_bytes", &len))
+ return NULL;
+ return PySSL_RAND(len, 1);
+}
+
+PyDoc_STRVAR(PySSL_RAND_pseudo_bytes_doc,
+"RAND_pseudo_bytes(n) -> (bytes, is_cryptographic)\n\
+\n\
+Generate n pseudo-random bytes. is_cryptographic is True if the bytes\
+generated are cryptographically strong.");
+
+static PyObject *
PySSL_RAND_status(PyObject *self)
{
return PyLong_FromLong(RAND_status());
@@ -1939,6 +2002,10 @@ static PyMethodDef PySSL_methods[] = {
#ifdef HAVE_OPENSSL_RAND
{"RAND_add", PySSL_RAND_add, METH_VARARGS,
PySSL_RAND_add_doc},
+ {"RAND_bytes", PySSL_RAND_bytes, METH_VARARGS,
+ PySSL_RAND_bytes_doc},
+ {"RAND_pseudo_bytes", PySSL_RAND_pseudo_bytes, METH_VARARGS,
+ PySSL_RAND_pseudo_bytes_doc},
{"RAND_egd", PySSL_RAND_egd, METH_VARARGS,
PySSL_RAND_egd_doc},
{"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS,