Skip to content

Commit 07244a8

Browse files
authored
bpo-9146: Raise a ValueError if OpenSSL fails to init a hash func. (#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.
1 parent c9d6dbc commit 07244a8

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

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 * \
@@ -918,6 +938,17 @@ generate_hash_name_list(void)
918938
if (!_PyArg_NoStackKeywords(#NAME, kwnames)) { \
919939
return NULL; \
920940
} \
941+
\
942+
if (CONST_new_ ## NAME ## _ctx_p == NULL) { \
943+
EVP_MD_CTX *ctx_p = EVP_MD_CTX_new(); \
944+
if (!EVP_get_digestbyname(#NAME) || \
945+
!EVP_DigestInit(ctx_p, EVP_get_digestbyname(#NAME))) { \
946+
_setException(PyExc_ValueError); \
947+
EVP_MD_CTX_free(ctx_p); \
948+
return NULL; \
949+
} \
950+
CONST_new_ ## NAME ## _ctx_p = ctx_p; \
951+
} \
921952
\
922953
if (data_obj) \
923954
GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); \
@@ -946,10 +977,6 @@ generate_hash_name_list(void)
946977
#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
947978
if (CONST_ ## NAME ## _name_obj == NULL) { \
948979
CONST_ ## NAME ## _name_obj = PyUnicode_FromString(#NAME); \
949-
if (EVP_get_digestbyname(#NAME)) { \
950-
CONST_new_ ## NAME ## _ctx_p = EVP_MD_CTX_new(); \
951-
EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
952-
} \
953980
} \
954981
} while (0);
955982

0 commit comments

Comments
 (0)