Skip to content

Commit eefd70f

Browse files
authored
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.
1 parent 4e40f2b commit eefd70f

File tree

3 files changed

+116
-78
lines changed

3 files changed

+116
-78
lines changed

Modules/_hashopenssl.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,15 +1251,11 @@ _hashlib_HASH(_hashlibstate *state, const char *digestname, PyObject *data_obj,
12511251
return (PyObject *)self;
12521252
}
12531253

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

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

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

12911292

Modules/hashlib.h

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,51 @@
1212
#define HASHLIB_UNSUPPORTED_STR_ALGORITHM "unsupported hash algorithm %s"
1313

1414
/*
15-
* Given a PyObject* obj, fill in the Py_buffer* viewp with the result
16-
* of PyObject_GetBuffer. Sets an exception and issues the erraction
17-
* on any errors, e.g. 'return NULL' or 'goto error'.
15+
* Obtain a buffer view from a buffer-like object 'obj'.
16+
*
17+
* On success, store the result in 'view' and return 0.
18+
* On error, set an exception and return -1.
1819
*/
19-
#define GET_BUFFER_VIEW_OR_ERROR(obj, viewp, erraction) do { \
20-
if (PyUnicode_Check((obj))) { \
21-
PyErr_SetString(PyExc_TypeError, \
22-
"Strings must be encoded before hashing");\
23-
erraction; \
24-
} \
25-
if (!PyObject_CheckBuffer((obj))) { \
26-
PyErr_SetString(PyExc_TypeError, \
27-
"object supporting the buffer API required"); \
28-
erraction; \
29-
} \
30-
if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \
31-
erraction; \
32-
} \
33-
if ((viewp)->ndim > 1) { \
34-
PyErr_SetString(PyExc_BufferError, \
35-
"Buffer must be single dimension"); \
36-
PyBuffer_Release((viewp)); \
37-
erraction; \
38-
} \
39-
} while(0)
20+
static inline int
21+
_Py_hashlib_get_buffer_view(PyObject *obj, Py_buffer *view)
22+
{
23+
if (PyUnicode_Check(obj)) {
24+
PyErr_SetString(PyExc_TypeError,
25+
"Strings must be encoded before hashing");
26+
return -1;
27+
}
28+
if (!PyObject_CheckBuffer(obj)) {
29+
PyErr_SetString(PyExc_TypeError,
30+
"object supporting the buffer API required");
31+
return -1;
32+
}
33+
if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE) == -1) {
34+
return -1;
35+
}
36+
if (view->ndim > 1) {
37+
PyErr_SetString(PyExc_BufferError,
38+
"Buffer must be single dimension");
39+
PyBuffer_Release(view);
40+
return -1;
41+
}
42+
return 0;
43+
}
44+
45+
/*
46+
* Call _Py_hashlib_get_buffer_view() and check if it succeeded.
47+
*
48+
* On error, set an exception and execute the ERRACTION statements.
49+
*/
50+
#define GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, ERRACTION) \
51+
do { \
52+
if (_Py_hashlib_get_buffer_view(OBJ, VIEW) < 0) { \
53+
assert(PyErr_Occurred()); \
54+
ERRACTION; \
55+
} \
56+
} while (0)
4057

41-
#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \
42-
GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL)
58+
#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \
59+
GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL)
4360

4461
/*
4562
* Helper code to synchronize access to the hash object when the GIL is

Modules/hmacmodule.c

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,42 +1099,60 @@ _hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
10991099
}
11001100

11011101
/*
1102-
* One-shot HMAC-HASH using the given HACL_HID.
1102+
* Obtain a view for 'key' and 'msg', storing it in 'keyview' and 'msgview'.
1103+
*
1104+
* Return 0 on success; otherwise set an exception and return -1.
11031105
*
11041106
* The length of the key and message buffers must not exceed UINT32_MAX,
11051107
* lest an OverflowError is raised. The Python implementation takes care
11061108
* of dispatching to the OpenSSL implementation in this case.
11071109
*/
1108-
#define Py_HMAC_HACL_ONESHOT(HACL_HID, KEY, MSG) \
1109-
do { \
1110-
Py_buffer keyview, msgview; \
1111-
GET_BUFFER_VIEW_OR_ERROUT((KEY), &keyview); \
1112-
if (!has_uint32_t_buffer_length(&keyview)) { \
1113-
PyBuffer_Release(&keyview); \
1114-
set_invalid_key_length_error(); \
1115-
return NULL; \
1116-
} \
1117-
GET_BUFFER_VIEW_OR_ERROR((MSG), &msgview, \
1118-
PyBuffer_Release(&keyview); \
1119-
return NULL); \
1120-
if (!has_uint32_t_buffer_length(&msgview)) { \
1121-
PyBuffer_Release(&msgview); \
1122-
PyBuffer_Release(&keyview); \
1123-
set_invalid_msg_length_error(); \
1124-
return NULL; \
1125-
} \
1126-
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
1127-
Py_hmac_## HACL_HID ##_compute_func( \
1128-
out, \
1129-
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
1130-
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
1131-
); \
1132-
PyBuffer_Release(&msgview); \
1133-
PyBuffer_Release(&keyview); \
1134-
return PyBytes_FromStringAndSize( \
1135-
(const char *)out, \
1136-
Py_hmac_## HACL_HID ##_digest_size \
1137-
); \
1110+
static int
1111+
hmac_get_buffer_views(PyObject *key, Py_buffer *keyview,
1112+
PyObject *msg, Py_buffer *msgview)
1113+
{
1114+
if (_Py_hashlib_get_buffer_view(key, keyview) < 0) {
1115+
return -1;
1116+
}
1117+
if (!has_uint32_t_buffer_length(keyview)) {
1118+
PyBuffer_Release(keyview);
1119+
set_invalid_key_length_error();
1120+
return -1;
1121+
}
1122+
if (_Py_hashlib_get_buffer_view(msg, msgview) < 0) {
1123+
PyBuffer_Release(keyview);
1124+
return -1;
1125+
}
1126+
if (!has_uint32_t_buffer_length(msgview)) {
1127+
PyBuffer_Release(msgview);
1128+
PyBuffer_Release(keyview);
1129+
set_invalid_msg_length_error();
1130+
return -1;
1131+
}
1132+
return 0;
1133+
}
1134+
1135+
/*
1136+
* One-shot HMAC-HASH using the given HACL_HID.
1137+
*/
1138+
#define HACL_HMAC_COMPUTE_NAMED_DIGEST(HACL_HID, KEY, MSG) \
1139+
do { \
1140+
Py_buffer keyview, msgview; \
1141+
if (hmac_get_buffer_views(key, &keyview, msg, &msgview) < 0) { \
1142+
return NULL; \
1143+
} \
1144+
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
1145+
Py_hmac_## HACL_HID ##_compute_func( \
1146+
out, \
1147+
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
1148+
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
1149+
); \
1150+
PyBuffer_Release(&msgview); \
1151+
PyBuffer_Release(&keyview); \
1152+
return PyBytes_FromStringAndSize( \
1153+
(const char *)out, \
1154+
Py_hmac_## HACL_HID ##_digest_size \
1155+
); \
11381156
} while (0)
11391157

11401158
/*[clinic input]
@@ -1150,7 +1168,7 @@ static PyObject *
11501168
_hmac_compute_md5_impl(PyObject *module, PyObject *key, PyObject *msg)
11511169
/*[clinic end generated code: output=7837a4ceccbbf636 input=77a4b774c7d61218]*/
11521170
{
1153-
Py_HMAC_HACL_ONESHOT(md5, key, msg);
1171+
HACL_HMAC_COMPUTE_NAMED_DIGEST(md5, key, msg);
11541172
}
11551173

11561174
/*[clinic input]
@@ -1166,7 +1184,7 @@ static PyObject *
11661184
_hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg)
11671185
/*[clinic end generated code: output=79fd7689c83691d8 input=3b64dccc6bdbe4ba]*/
11681186
{
1169-
Py_HMAC_HACL_ONESHOT(sha1, key, msg);
1187+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha1, key, msg);
11701188
}
11711189

11721190
/*[clinic input]
@@ -1182,7 +1200,7 @@ static PyObject *
11821200
_hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg)
11831201
/*[clinic end generated code: output=7f21f1613e53979e input=a1a75f25f23449af]*/
11841202
{
1185-
Py_HMAC_HACL_ONESHOT(sha2_224, key, msg);
1203+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_224, key, msg);
11861204
}
11871205

11881206
/*[clinic input]
@@ -1198,7 +1216,7 @@ static PyObject *
11981216
_hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg)
11991217
/*[clinic end generated code: output=d4a291f7d9a82459 input=5c9ccf2df048ace3]*/
12001218
{
1201-
Py_HMAC_HACL_ONESHOT(sha2_256, key, msg);
1219+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_256, key, msg);
12021220
}
12031221

12041222
/*[clinic input]
@@ -1214,7 +1232,7 @@ static PyObject *
12141232
_hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg)
12151233
/*[clinic end generated code: output=f211fa26e3700c27 input=2fee2c14766af231]*/
12161234
{
1217-
Py_HMAC_HACL_ONESHOT(sha2_384, key, msg);
1235+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_384, key, msg);
12181236
}
12191237

12201238
/*[clinic input]
@@ -1230,7 +1248,7 @@ static PyObject *
12301248
_hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg)
12311249
/*[clinic end generated code: output=d5c20373762cecca input=3371eaac315c7864]*/
12321250
{
1233-
Py_HMAC_HACL_ONESHOT(sha2_512, key, msg);
1251+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_512, key, msg);
12341252
}
12351253

12361254
/*[clinic input]
@@ -1246,7 +1264,7 @@ static PyObject *
12461264
_hmac_compute_sha3_224_impl(PyObject *module, PyObject *key, PyObject *msg)
12471265
/*[clinic end generated code: output=a242ccac9ad9c22b input=d0ab0c7d189c3d87]*/
12481266
{
1249-
Py_HMAC_HACL_ONESHOT(sha3_224, key, msg);
1267+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_224, key, msg);
12501268
}
12511269

12521270
/*[clinic input]
@@ -1262,7 +1280,7 @@ static PyObject *
12621280
_hmac_compute_sha3_256_impl(PyObject *module, PyObject *key, PyObject *msg)
12631281
/*[clinic end generated code: output=b539dbb61af2fe0b input=f05d7b6364b35d02]*/
12641282
{
1265-
Py_HMAC_HACL_ONESHOT(sha3_256, key, msg);
1283+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_256, key, msg);
12661284
}
12671285

12681286
/*[clinic input]
@@ -1278,7 +1296,7 @@ static PyObject *
12781296
_hmac_compute_sha3_384_impl(PyObject *module, PyObject *key, PyObject *msg)
12791297
/*[clinic end generated code: output=5eb372fb5c4ffd3a input=d842d393e7aa05ae]*/
12801298
{
1281-
Py_HMAC_HACL_ONESHOT(sha3_384, key, msg);
1299+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_384, key, msg);
12821300
}
12831301

12841302
/*[clinic input]
@@ -1294,7 +1312,7 @@ static PyObject *
12941312
_hmac_compute_sha3_512_impl(PyObject *module, PyObject *key, PyObject *msg)
12951313
/*[clinic end generated code: output=154bcbf8c2eacac1 input=166fe5baaeaabfde]*/
12961314
{
1297-
Py_HMAC_HACL_ONESHOT(sha3_512, key, msg);
1315+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_512, key, msg);
12981316
}
12991317

13001318
/*[clinic input]
@@ -1310,7 +1328,7 @@ static PyObject *
13101328
_hmac_compute_blake2s_32_impl(PyObject *module, PyObject *key, PyObject *msg)
13111329
/*[clinic end generated code: output=cfc730791bc62361 input=d22c36e7fe31a985]*/
13121330
{
1313-
Py_HMAC_HACL_ONESHOT(blake2s_32, key, msg);
1331+
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2s_32, key, msg);
13141332
}
13151333

13161334
/*[clinic input]
@@ -1326,9 +1344,11 @@ static PyObject *
13261344
_hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
13271345
/*[clinic end generated code: output=765c5c4fb9124636 input=4a35ee058d172f4b]*/
13281346
{
1329-
Py_HMAC_HACL_ONESHOT(blake2b_32, key, msg);
1347+
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2b_32, key, msg);
13301348
}
13311349

1350+
#undef HACL_HMAC_COMPUTE_NAMED_DIGEST
1351+
13321352
// --- HMAC module methods ----------------------------------------------------
13331353

13341354
static PyMethodDef hmacmodule_methods[] = {

0 commit comments

Comments
 (0)