summaryrefslogtreecommitdiff
path: root/Modules/_hashopenssl.c
diff options
context:
space:
mode:
authorChristian Heimes <christian@python.org>2016-09-05 23:23:24 +0200
committerChristian Heimes <christian@python.org>2016-09-05 23:23:24 +0200
commit01113faef983fc5c495fbacc00bbb55eab02dfc3 (patch)
tree0ee26fb3a14c2a9e45f293ad1297553c18f9b7e3 /Modules/_hashopenssl.c
parentae8298bfb78eebc6c1bf914c89ec397121640a94 (diff)
parent598894ff48e9c1171cb2ec1c798235826a75c7e0 (diff)
downloadcpython-git-01113faef983fc5c495fbacc00bbb55eab02dfc3.tar.gz
Issue #26470: Port ssl and hashlib module to OpenSSL 1.1.0.
Diffstat (limited to 'Modules/_hashopenssl.c')
-rw-r--r--Modules/_hashopenssl.c165
1 files changed, 106 insertions, 59 deletions
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index f45744a435..ff576144df 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -21,7 +21,6 @@
/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
-#include <openssl/hmac.h>
/* We use the object interface to discover what hashes OpenSSL supports. */
#include <openssl/objects.h>
#include "openssl/err.h"
@@ -32,11 +31,22 @@
#define HASH_OBJ_CONSTRUCTOR 0
#endif
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
+/* OpenSSL < 1.1.0 */
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 0
+#include <openssl/hmac.h>
+#else
+/* OpenSSL >= 1.1.0 */
+#define HAS_FAST_PKCS5_PBKDF2_HMAC 1
+#endif
+
typedef struct {
PyObject_HEAD
PyObject *name; /* name of this hash algorithm */
- EVP_MD_CTX ctx; /* OpenSSL message digest context */
+ EVP_MD_CTX *ctx; /* OpenSSL message digest context */
#ifdef WITH_THREAD
PyThread_type_lock lock; /* OpenSSL context lock */
#endif
@@ -48,7 +58,6 @@ static PyTypeObject EVPtype;
#define DEFINE_CONSTS_FOR_NEW(Name) \
static PyObject *CONST_ ## Name ## _name_obj = NULL; \
- static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
DEFINE_CONSTS_FOR_NEW(md5)
@@ -59,19 +68,57 @@ DEFINE_CONSTS_FOR_NEW(sha384)
DEFINE_CONSTS_FOR_NEW(sha512)
+/* LCOV_EXCL_START */
+static PyObject *
+_setException(PyObject *exc)
+{
+ unsigned long errcode;
+ const char *lib, *func, *reason;
+
+ errcode = ERR_peek_last_error();
+ if (!errcode) {
+ PyErr_SetString(exc, "unknown reasons");
+ return NULL;
+ }
+ ERR_clear_error();
+
+ lib = ERR_lib_error_string(errcode);
+ func = ERR_func_error_string(errcode);
+ reason = ERR_reason_error_string(errcode);
+
+ if (lib && func) {
+ PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
+ }
+ else if (lib) {
+ PyErr_Format(exc, "[%s] %s", lib, reason);
+ }
+ else {
+ PyErr_SetString(exc, reason);
+ }
+ return NULL;
+}
+/* LCOV_EXCL_STOP */
+
static EVPobject *
newEVPobject(PyObject *name)
{
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
+ if (retval == NULL) {
+ return NULL;
+ }
+
+ retval->ctx = EVP_MD_CTX_new();
+ if (retval->ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
/* save the name for .name to return */
- if (retval != NULL) {
- Py_INCREF(name);
- retval->name = name;
+ Py_INCREF(name);
+ retval->name = name;
#ifdef WITH_THREAD
- retval->lock = NULL;
+ retval->lock = NULL;
#endif
- }
return retval;
}
@@ -86,7 +133,7 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
process = MUNCH_SIZE;
else
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
- EVP_DigestUpdate(&self->ctx, (const void*)cp, process);
+ EVP_DigestUpdate(self->ctx, (const void*)cp, process);
len -= process;
cp += process;
}
@@ -101,16 +148,19 @@ EVP_dealloc(EVPobject *self)
if (self->lock != NULL)
PyThread_free_lock(self->lock);
#endif
- EVP_MD_CTX_cleanup(&self->ctx);
+ EVP_MD_CTX_free(self->ctx);
Py_XDECREF(self->name);
PyObject_Del(self);
}
-static void locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
+static int
+locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
{
+ int result;
ENTER_HASHLIB(self);
- EVP_MD_CTX_copy(new_ctx_p, &self->ctx);
+ result = EVP_MD_CTX_copy(new_ctx_p, self->ctx);
LEAVE_HASHLIB(self);
+ return result;
}
/* External methods for a hash object */
@@ -126,7 +176,9 @@ EVP_copy(EVPobject *self, PyObject *unused)
if ( (newobj = newEVPobject(self->name))==NULL)
return NULL;
- locked_EVP_MD_CTX_copy(&newobj->ctx, self);
+ if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) {
+ return _setException(PyExc_ValueError);
+ }
return (PyObject *)newobj;
}
@@ -137,16 +189,24 @@ static PyObject *
EVP_digest(EVPobject *self, PyObject *unused)
{
unsigned char digest[EVP_MAX_MD_SIZE];
- EVP_MD_CTX temp_ctx;
+ EVP_MD_CTX *temp_ctx;
PyObject *retval;
unsigned int digest_size;
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
- digest_size = EVP_MD_CTX_size(&temp_ctx);
- EVP_DigestFinal(&temp_ctx, digest, NULL);
+ temp_ctx = EVP_MD_CTX_new();
+ if (temp_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ return _setException(PyExc_ValueError);
+ }
+ digest_size = EVP_MD_CTX_size(temp_ctx);
+ EVP_DigestFinal(temp_ctx, digest, NULL);
retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
- EVP_MD_CTX_cleanup(&temp_ctx);
+ EVP_MD_CTX_free(temp_ctx);
return retval;
}
@@ -157,15 +217,23 @@ static PyObject *
EVP_hexdigest(EVPobject *self, PyObject *unused)
{
unsigned char digest[EVP_MAX_MD_SIZE];
- EVP_MD_CTX temp_ctx;
+ EVP_MD_CTX *temp_ctx;
unsigned int digest_size;
+ temp_ctx = EVP_MD_CTX_new();
+ if (temp_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
/* Get the raw (binary) digest value */
- locked_EVP_MD_CTX_copy(&temp_ctx, self);
- digest_size = EVP_MD_CTX_size(&temp_ctx);
- EVP_DigestFinal(&temp_ctx, digest, NULL);
+ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ return _setException(PyExc_ValueError);
+ }
+ digest_size = EVP_MD_CTX_size(temp_ctx);
+ EVP_DigestFinal(temp_ctx, digest, NULL);
- EVP_MD_CTX_cleanup(&temp_ctx);
+ EVP_MD_CTX_free(temp_ctx);
return _Py_strhex((const char *)digest, digest_size);
}
@@ -219,7 +287,7 @@ static PyObject *
EVP_get_block_size(EVPobject *self, void *closure)
{
long block_size;
- block_size = EVP_MD_CTX_block_size(&self->ctx);
+ block_size = EVP_MD_CTX_block_size(self->ctx);
return PyLong_FromLong(block_size);
}
@@ -227,7 +295,7 @@ static PyObject *
EVP_get_digest_size(EVPobject *self, void *closure)
{
long size;
- size = EVP_MD_CTX_size(&self->ctx);
+ size = EVP_MD_CTX_size(self->ctx);
return PyLong_FromLong(size);
}
@@ -288,7 +356,7 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
PyBuffer_Release(&view);
return -1;
}
- EVP_DigestInit(&self->ctx, digest);
+ EVP_DigestInit(self->ctx, digest);
self->name = name_obj;
Py_INCREF(self->name);
@@ -385,9 +453,9 @@ EVPnew(PyObject *name_obj,
return NULL;
if (initial_ctx) {
- EVP_MD_CTX_copy(&self->ctx, initial_ctx);
+ EVP_MD_CTX_copy(self->ctx, initial_ctx);
} else {
- EVP_DigestInit(&self->ctx, digest);
+ EVP_DigestInit(self->ctx, digest);
}
if (cp && len) {
@@ -453,6 +521,7 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
#define PY_PBKDF2_HMAC 1
+#if !HAS_FAST_PKCS5_PBKDF2_HMAC
/* Improved implementation of PKCS5_PBKDF2_HMAC()
*
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
@@ -534,37 +603,8 @@ PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen,
HMAC_CTX_cleanup(&hctx_tpl);
return 1;
}
+#endif
-/* LCOV_EXCL_START */
-static PyObject *
-_setException(PyObject *exc)
-{
- unsigned long errcode;
- const char *lib, *func, *reason;
-
- errcode = ERR_peek_last_error();
- if (!errcode) {
- PyErr_SetString(exc, "unknown reasons");
- return NULL;
- }
- ERR_clear_error();
-
- lib = ERR_lib_error_string(errcode);
- func = ERR_func_error_string(errcode);
- reason = ERR_reason_error_string(errcode);
-
- if (lib && func) {
- PyErr_Format(exc, "[%s: %s] %s", lib, func, reason);
- }
- else if (lib) {
- PyErr_Format(exc, "[%s] %s", lib, reason);
- }
- else {
- PyErr_SetString(exc, reason);
- }
- return NULL;
-}
-/* LCOV_EXCL_STOP */
PyDoc_STRVAR(pbkdf2_hmac__doc__,
"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\
@@ -646,10 +686,17 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict)
key = PyBytes_AS_STRING(key_obj);
Py_BEGIN_ALLOW_THREADS
+#if HAS_FAST_PKCS5_PBKDF2_HMAC
+ retval = PKCS5_PBKDF2_HMAC((char*)password.buf, (int)password.len,
+ (unsigned char *)salt.buf, (int)salt.len,
+ iterations, digest, dklen,
+ (unsigned char *)key);
+#else
retval = PKCS5_PBKDF2_HMAC_fast((char*)password.buf, (int)password.len,
(unsigned char *)salt.buf, (int)salt.len,
iterations, digest, dklen,
(unsigned char *)key);
+#endif
Py_END_ALLOW_THREADS
if (!retval) {
@@ -768,7 +815,7 @@ generate_hash_name_list(void)
if (CONST_ ## NAME ## _name_obj == NULL) { \
CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
if (EVP_get_digestbyname(#NAME)) { \
- CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
+ CONST_new_ ## NAME ## _ctx_p = EVP_MD_CTX_new(); \
EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
} \
} \