Skip to content

Commit 31b8efe

Browse files
authored
[3.6] bpo-9146: Raise a ValueError if OpenSSL fails to init a hash func (#3274)
* [3.6] bpo-9146: Raise a ValueError if OpenSSL fails to init a hash func. (GH-1777) This helps people in weird FIPS mode environments where common things like MD5 are not available in the binary as a matter of policy. (cherry picked from commit 07244a8) * Include a NEWS entry.
1 parent d409735 commit 31b8efe

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a segmentation fault in _hashopenssl when standard hash functions
2+
such as md5 are not available in the linked OpenSSL library. As in
3+
some special FIPS-140 build environments.

Modules/_hashopenssl.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
139139
process = MUNCH_SIZE;
140140
else
141141
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
142-
EVP_DigestUpdate(self->ctx, (const void*)cp, process);
142+
if (!EVP_DigestUpdate(self->ctx, (const void*)cp, process)) {
143+
_setException(PyExc_ValueError);
144+
break;
145+
}
143146
len -= process;
144147
cp += process;
145148
}
@@ -209,7 +212,10 @@ EVP_digest(EVPobject *self, PyObject *unused)
209212
return _setException(PyExc_ValueError);
210213
}
211214
digest_size = EVP_MD_CTX_size(temp_ctx);
212-
EVP_DigestFinal(temp_ctx, digest, NULL);
215+
if (!EVP_DigestFinal(temp_ctx, digest, NULL)) {
216+
_setException(PyExc_ValueError);
217+
return NULL;
218+
}
213219

214220
retval = PyBytes_FromStringAndSize((const char *)digest, digest_size);
215221
EVP_MD_CTX_free(temp_ctx);
@@ -237,7 +243,10 @@ EVP_hexdigest(EVPobject *self, PyObject *unused)
237243
return _setException(PyExc_ValueError);
238244
}
239245
digest_size = EVP_MD_CTX_size(temp_ctx);
240-
EVP_DigestFinal(temp_ctx, digest, NULL);
246+
if (!EVP_DigestFinal(temp_ctx, digest, NULL)) {
247+
_setException(PyExc_ValueError);
248+
return NULL;
249+
}
241250

242251
EVP_MD_CTX_free(temp_ctx);
243252

@@ -362,7 +371,12 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
362371
PyBuffer_Release(&view);
363372
return -1;
364373
}
365-
EVP_DigestInit(self->ctx, digest);
374+
if (!EVP_DigestInit(self->ctx, digest)) {
375+
_setException(PyExc_ValueError);
376+
if (data_obj)
377+
PyBuffer_Release(&view);
378+
return -1;
379+
}
366380

367381
self->name = name_obj;
368382
Py_INCREF(self->name);
@@ -461,7 +475,11 @@ EVPnew(PyObject *name_obj,
461475
if (initial_ctx) {
462476
EVP_MD_CTX_copy(self->ctx, initial_ctx);
463477
} else {
464-
EVP_DigestInit(self->ctx, digest);
478+
if (!EVP_DigestInit(self->ctx, digest)) {
479+
_setException(PyExc_ValueError);
480+
Py_DECREF(self);
481+
return NULL;
482+
}
465483
}
466484

467485
if (cp && len) {
@@ -902,6 +920,8 @@ generate_hash_name_list(void)
902920
* the generic one passing it a python string and are noticeably
903921
* faster than calling a python new() wrapper. Thats important for
904922
* code that wants to make hashes of a bunch of small strings.
923+
* The first call will lazy-initialize, which reports an exception
924+
* if initialization fails.
905925
*/
906926
#define GEN_CONSTRUCTOR(NAME) \
907927
static PyObject * \
@@ -914,6 +934,17 @@ generate_hash_name_list(void)
914934
if (!PyArg_ParseTuple(args, "|O:" #NAME , &data_obj)) { \
915935
return NULL; \
916936
} \
937+
\
938+
if (CONST_new_ ## NAME ## _ctx_p == NULL) { \
939+
EVP_MD_CTX *ctx_p = EVP_MD_CTX_new(); \
940+
if (!EVP_get_digestbyname(#NAME) || \
941+
!EVP_DigestInit(ctx_p, EVP_get_digestbyname(#NAME))) { \
942+
_setException(PyExc_ValueError); \
943+
EVP_MD_CTX_free(ctx_p); \
944+
return NULL; \
945+
} \
946+
CONST_new_ ## NAME ## _ctx_p = ctx_p; \
947+
} \
917948
\
918949
if (data_obj) \
919950
GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
@@ -942,10 +973,6 @@ generate_hash_name_list(void)
942973
#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
943974
if (CONST_ ## NAME ## _name_obj == NULL) { \
944975
CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
945-
if (EVP_get_digestbyname(#NAME)) { \
946-
CONST_new_ ## NAME ## _ctx_p = EVP_MD_CTX_new(); \
947-
EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
948-
} \
949976
} \
950977
} while (0);
951978

0 commit comments

Comments
 (0)