summaryrefslogtreecommitdiffstats
path: root/Modules/_hashopenssl.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2010-09-06 08:30:23 (GMT)
committerGregory P. Smith <greg@mad-scientist.com>2010-09-06 08:30:23 (GMT)
commit13b55291ac84d2fb74f93c286a0bd5673f439e38 (patch)
tree3be269bb34eb782e9ec28a92b3f07d1b95b32c4f /Modules/_hashopenssl.c
parentc86adb4c5c616e6aa7dcf9e59c71ba66ab5ea553 (diff)
downloadcpython-13b55291ac84d2fb74f93c286a0bd5673f439e38.zip
cpython-13b55291ac84d2fb74f93c286a0bd5673f439e38.tar.gz
cpython-13b55291ac84d2fb74f93c286a0bd5673f439e38.tar.bz2
hashlib has two new constant attributes: algorithms_guaranteed and
algorithms_avaiable that respectively list the names of hash algorithms guaranteed to exist in all Python implementations and the names of hash algorithms available in the current process. Renames the attribute new in 3.2a0 'algorithms' to 'algorithms_guaranteed'.
Diffstat (limited to 'Modules/_hashopenssl.c')
-rw-r--r--Modules/_hashopenssl.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 9f550a6..dd4317f 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -38,6 +38,8 @@
/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
+/* We use the object interface to discover what hashes OpenSSL supports. */
+#include <openssl/objects.h>
#define MUNCH_SIZE INT_MAX
@@ -488,6 +490,62 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
return ret_obj;
}
+
+/* State for our callback function so that it can accumulate a result. */
+typedef struct _internal_name_mapper_state {
+ PyObject *set;
+ int error;
+} _InternalNameMapperState;
+
+
+/* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */
+static void
+_openssl_hash_name_mapper(const OBJ_NAME *openssl_obj_name, void *arg)
+{
+ _InternalNameMapperState *state = (_InternalNameMapperState *)arg;
+ PyObject *py_name;
+
+ assert(state != NULL);
+ if (openssl_obj_name == NULL)
+ return;
+ /* Ignore aliased names, they pollute the list and OpenSSL appears to
+ * have a its own definition of alias as the resulting list still
+ * contains duplicate and alternate names for several algorithms. */
+ if (openssl_obj_name->alias)
+ return;
+
+ py_name = PyUnicode_FromString(openssl_obj_name->name);
+ if (py_name == NULL) {
+ state->error = 1;
+ } else {
+ if (PySet_Add(state->set, py_name) != 0) {
+ Py_DECREF(py_name);
+ state->error = 1;
+ }
+ }
+}
+
+
+/* Ask OpenSSL for a list of supported ciphers, filling in a Python set. */
+static PyObject*
+generate_hash_name_list(void)
+{
+ _InternalNameMapperState state;
+ state.set = PyFrozenSet_New(NULL);
+ if (state.set == NULL)
+ return NULL;
+ state.error = 0;
+
+ OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, &_openssl_hash_name_mapper, &state);
+
+ if (state.error) {
+ Py_DECREF(state.set);
+ return NULL;
+ }
+ return state.set;
+}
+
+
/*
* This macro generates constructor function definitions for specific
* hash algorithms. These constructors are much faster than calling
@@ -581,7 +639,7 @@ static struct PyModuleDef _hashlibmodule = {
PyMODINIT_FUNC
PyInit__hashlib(void)
{
- PyObject *m;
+ PyObject *m, *openssl_md_meth_names;
OpenSSL_add_all_digests();
@@ -598,6 +656,16 @@ PyInit__hashlib(void)
if (m == NULL)
return NULL;
+ openssl_md_meth_names = generate_hash_name_list();
+ if (openssl_md_meth_names == NULL) {
+ Py_DECREF(m);
+ return NULL;
+ }
+ if (PyModule_AddObject(m, "openssl_md_meth_names", openssl_md_meth_names)) {
+ Py_DECREF(m);
+ return NULL;
+ }
+
#if HASH_OBJ_CONSTRUCTOR
Py_INCREF(&EVPtype);
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);