https://github.com/python/cpython/commit/eefd70f0ed51e46fa9ff3d465dcf977bd4af28de
commit: eefd70f0ed51e46fa9ff3d465dcf977bd4af28de
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-07-28T07:36:15Z
summary:
gh-136968: fortify macro usage in cryptographic modules (#136973)
Macros used in cryptographic extension modules are partially rewritten
to use `static inline` functions when possible to help code completion.
files:
M Modules/_hashopenssl.c
M Modules/hashlib.h
M Modules/hmacmodule.c
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index d79e4b360e95c5..00f98c090b3952 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -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() */
@@ -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);
}
diff --git a/Modules/hashlib.h b/Modules/hashlib.h
index 5de5922c345047..5ada4ef4b863ec 100644
--- a/Modules/hashlib.h
+++ b/Modules/hashlib.h
@@ -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
diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c
index b5405c99f1f8ce..694e2a095744ff 100644
--- a/Modules/hmacmodule.c
+++ b/Modules/hmacmodule.c
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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]
@@ -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[] = {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]