Skip to content

gh-136968: fortify macro usage in cryptographic modules #136973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,15 +1251,11 @@ _hashlib_HASH(_hashlibstate *state, const char *digestname, PyObject *data_obj,
return (PyObject *)self;
}

// In Python 3.19, we can remove the "STRING" argument and would also be able
// to remove the macro (or keep it as an alias for better naming) since calls
// to _hashlib_HASH_new_impl() would fit on 80 characters.
#define CALL_HASHLIB_NEW(MODULE, NAME, DATA, STRING, USEDFORSECURITY) \
do { \
PyObject *data_obj; \
if (_Py_hashlib_data_argument(&data_obj, DATA, STRING) < 0) { \
return NULL; \
} \
_hashlibstate *state = get_hashlib_state(MODULE); \
return _hashlib_HASH(state, NAME, data_obj, USEDFORSECURITY); \
} while (0)
return _hashlib_HASH_new_impl(MODULE, NAME, DATA, USEDFORSECURITY, STRING)

/* The module-level function: new() */

Expand All @@ -1285,7 +1281,12 @@ _hashlib_HASH_new_impl(PyObject *module, const char *name, PyObject *data,
int usedforsecurity, PyObject *string)
/*[clinic end generated code: output=b905aaf9840c1bbd input=c34af6c6e696d44e]*/
{
CALL_HASHLIB_NEW(module, name, data, string, usedforsecurity);
PyObject *data_obj;
if (_Py_hashlib_data_argument(&data_obj, data, string) < 0) {
return NULL;
}
_hashlibstate *state = get_hashlib_state(module);
return _hashlib_HASH(state, name, data_obj, usedforsecurity);
}


Expand Down
69 changes: 43 additions & 26 deletions Modules/hashlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,51 @@
#define HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s"

/*
* Given a PyObject* obj, fill in the Py_buffer* viewp with the result
* of PyObject_GetBuffer. Sets an exception and issues the erraction
* on any errors, e.g. 'return NULL' or 'goto error'.
* Obtain a buffer view from a buffer-like object 'obj'.
*
* On success, store the result in 'view' and return 0.
* On error, set an exception and return -1.
*/
#define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \
if (PyUnicode_Check((obj))) { \
PyErr_SetString(PyExc_TypeError, \
"Strings must be encoded before hashing");\
erraction; \
} \
if (!PyObject_CheckBuffer((obj))) { \
PyErr_SetString(PyExc_TypeError, \
"object supporting the buffer API required"); \
erraction; \
} \
if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
erraction; \
} \
if ((viewp)->ndim > 1) { \
PyErr_SetString(PyExc_BufferError, \
"Buffer must be single dimension"); \
PyBuffer_Release((viewp)); \
erraction; \
} \
} while(0)
static inline int
_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view)
{
if (PyUnicode_Check(obj)) {
PyErr_SetString(PyExc_TypeError,
"Strings must be encoded before hashing");
return -1;
}
if (!PyObject_CheckBuffer(obj)) {
PyErr_SetString(PyExc_TypeError,
"object supporting the buffer API required");
return -1;
}
if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
return -1;
}
if (view->ndim > 1) {
PyErr_SetString(PyExc_BufferError,
"Buffer must be single dimension");
PyBuffer_Release(view);
return -1;
}
return 0;
}

/*
* Call _Py_hashlib_get_buffer_view() and check if it succeeded.
*
* On error, set an exception and execute the ERRACTION statements.
*/
#define GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, ERRACTION) \
do { \
if (_Py_hashlib_get_buffer_view(OBJ, VIEW) < 0) { \
assert(PyErr_Occurred()); \
ERRACTION; \
} \
} while (0)

#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \
GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL)
#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \
GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL)

/*
* Helper code to synchronize access to the hash object when the GIL is
Expand Down
106 changes: 63 additions & 43 deletions Modules/hmacmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1099,42 +1099,60 @@ _hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
}

/*
* One-shot HMAC-HASH using the given HACL_HID.
* Obtain a view for 'key' and 'msg', storing it in 'keyview' and 'msgview'.
*
* Return 0 on success; otherwise set an exception and return -1.
*
* The length of the key and message buffers must not exceed UINT32_MAX,
* lest an OverflowError is raised. The Python implementation takes care
* of dispatching to the OpenSSL implementation in this case.
*/
#define Py_HMAC_HACL_ONESHOT(HACL_HID, KEY, MSG) \
do { \
Py_buffer keyview, msgview; \
GET_BUFFER_VIEW_OR_ERROUT((KEY), &keyview); \
if (!has_uint32_t_buffer_length(&keyview)) { \
PyBuffer_Release(&keyview); \
set_invalid_key_length_error(); \
return NULL; \
} \
GET_BUFFER_VIEW_OR_ERROR((MSG), &msgview, \
PyBuffer_Release(&keyview); \
return NULL); \
if (!has_uint32_t_buffer_length(&msgview)) { \
PyBuffer_Release(&msgview); \
PyBuffer_Release(&keyview); \
set_invalid_msg_length_error(); \
return NULL; \
} \
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
Py_hmac_## HACL_HID ##_compute_func( \
out, \
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
); \
PyBuffer_Release(&msgview); \
PyBuffer_Release(&keyview); \
return PyBytes_FromStringAndSize( \
(const char *)out, \
Py_hmac_## HACL_HID ##_digest_size \
); \
static int
hmac_get_buffer_views(PyObject *key, Py_buffer *keyview,
PyObject *msg, Py_buffer *msgview)
{
if (_Py_hashlib_get_buffer_view(key, keyview) < 0) {
return -1;
}
if (!has_uint32_t_buffer_length(keyview)) {
PyBuffer_Release(keyview);
set_invalid_key_length_error();
return -1;
}
if (_Py_hashlib_get_buffer_view(msg, msgview) < 0) {
PyBuffer_Release(keyview);
return -1;
}
if (!has_uint32_t_buffer_length(msgview)) {
PyBuffer_Release(msgview);
PyBuffer_Release(keyview);
set_invalid_msg_length_error();
return -1;
}
return 0;
}

/*
* One-shot HMAC-HASH using the given HACL_HID.
*/
#define HACL_HMAC_COMPUTE_NAMED_DIGEST(HACL_HID, KEY, MSG) \
do { \
Py_buffer keyview, msgview; \
if (hmac_get_buffer_views(key, &keyview, msg, &msgview) < 0) { \
return NULL; \
} \
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
Py_hmac_## HACL_HID ##_compute_func( \
out, \
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
); \
PyBuffer_Release(&msgview); \
PyBuffer_Release(&keyview); \
return PyBytes_FromStringAndSize( \
(const char *)out, \
Py_hmac_## HACL_HID ##_digest_size \
); \
} while (0)

/*[clinic input]
Expand All @@ -1150,7 +1168,7 @@ static PyObject *
_hmac_compute_md5_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=7837a4ceccbbf636 input=77a4b774c7d61218]*/
{
Py_HMAC_HACL_ONESHOT(md5, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(md5, key, msg);
}

/*[clinic input]
Expand All @@ -1166,7 +1184,7 @@ static PyObject *
_hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=79fd7689c83691d8 input=3b64dccc6bdbe4ba]*/
{
Py_HMAC_HACL_ONESHOT(sha1, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha1, key, msg);
}

/*[clinic input]
Expand All @@ -1182,7 +1200,7 @@ static PyObject *
_hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=7f21f1613e53979e input=a1a75f25f23449af]*/
{
Py_HMAC_HACL_ONESHOT(sha2_224, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_224, key, msg);
}

/*[clinic input]
Expand All @@ -1198,7 +1216,7 @@ static PyObject *
_hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=d4a291f7d9a82459 input=5c9ccf2df048ace3]*/
{
Py_HMAC_HACL_ONESHOT(sha2_256, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_256, key, msg);
}

/*[clinic input]
Expand All @@ -1214,7 +1232,7 @@ static PyObject *
_hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=f211fa26e3700c27 input=2fee2c14766af231]*/
{
Py_HMAC_HACL_ONESHOT(sha2_384, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_384, key, msg);
}

/*[clinic input]
Expand All @@ -1230,7 +1248,7 @@ static PyObject *
_hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=d5c20373762cecca input=3371eaac315c7864]*/
{
Py_HMAC_HACL_ONESHOT(sha2_512, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_512, key, msg);
}

/*[clinic input]
Expand All @@ -1246,7 +1264,7 @@ static PyObject *
_hmac_compute_sha3_224_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=a242ccac9ad9c22b input=d0ab0c7d189c3d87]*/
{
Py_HMAC_HACL_ONESHOT(sha3_224, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_224, key, msg);
}

/*[clinic input]
Expand All @@ -1262,7 +1280,7 @@ static PyObject *
_hmac_compute_sha3_256_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=b539dbb61af2fe0b input=f05d7b6364b35d02]*/
{
Py_HMAC_HACL_ONESHOT(sha3_256, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_256, key, msg);
}

/*[clinic input]
Expand All @@ -1278,7 +1296,7 @@ static PyObject *
_hmac_compute_sha3_384_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=5eb372fb5c4ffd3a input=d842d393e7aa05ae]*/
{
Py_HMAC_HACL_ONESHOT(sha3_384, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_384, key, msg);
}

/*[clinic input]
Expand All @@ -1294,7 +1312,7 @@ static PyObject *
_hmac_compute_sha3_512_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=154bcbf8c2eacac1 input=166fe5baaeaabfde]*/
{
Py_HMAC_HACL_ONESHOT(sha3_512, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_512, key, msg);
}

/*[clinic input]
Expand All @@ -1310,7 +1328,7 @@ static PyObject *
_hmac_compute_blake2s_32_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=cfc730791bc62361 input=d22c36e7fe31a985]*/
{
Py_HMAC_HACL_ONESHOT(blake2s_32, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2s_32, key, msg);
}

/*[clinic input]
Expand All @@ -1326,9 +1344,11 @@ static PyObject *
_hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
/*[clinic end generated code: output=765c5c4fb9124636 input=4a35ee058d172f4b]*/
{
Py_HMAC_HACL_ONESHOT(blake2b_32, key, msg);
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2b_32, key, msg);
}

#undef HACL_HMAC_COMPUTE_NAMED_DIGEST

// --- HMAC module methods ----------------------------------------------------

static PyMethodDef hmacmodule_methods[] = {
Expand Down
Loading