Skip to content

Commit a46976a

Browse files
committed
[3.14] pythongh-136968: fortify macro usage in cryptographic modules (pythonGH-136973)
Macros used in cryptographic extension modules are partially rewritten to use `static inline` functions when possible to help code completion. (cherry picked from commit eefd70f) Co-authored-by: Bénédikt Tran <[email protected]>
1 parent 47a2109 commit a46976a

File tree

3 files changed

+115
-77
lines changed

3 files changed

+115
-77
lines changed

Modules/_hashopenssl.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,14 +1017,11 @@ _hashlib_HASH(PyObject *module, const char *digestname, PyObject *data_obj,
10171017
return (PyObject *)self;
10181018
}
10191019

1020+
// In Python 3.19, we can remove the "STRING" argument and would also be able
1021+
// to remove the macro (or keep it as an alias for better naming) since calls
1022+
// to _hashlib_new_impl() would fit on 80 characters.
10201023
#define CALL_HASHLIB_NEW(MODULE, NAME, DATA, STRING, USEDFORSECURITY) \
1021-
do { \
1022-
PyObject *data_obj; \
1023-
if (_Py_hashlib_data_argument(&data_obj, DATA, STRING) < 0) { \
1024-
return NULL; \
1025-
} \
1026-
return _hashlib_HASH(MODULE, NAME, data_obj, USEDFORSECURITY); \
1027-
} while (0)
1024+
return _hashlib_new_impl(MODULE, NAME, DATA, USEDFORSECURITY, STRING)
10281025

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

@@ -1050,7 +1047,11 @@ _hashlib_new_impl(PyObject *module, const char *name, PyObject *data,
10501047
int usedforsecurity, PyObject *string)
10511048
/*[clinic end generated code: output=c01feb4ad6a6303d input=f5ec9bf1fa749d07]*/
10521049
{
1053-
CALL_HASHLIB_NEW(module, name, data, string, usedforsecurity);
1050+
PyObject *data_obj;
1051+
if (_Py_hashlib_data_argument(&data_obj, data, string) < 0) {
1052+
return NULL;
1053+
}
1054+
return _hashlib_HASH(module, name, data_obj, usedforsecurity);
10541055
}
10551056

10561057

Modules/hashlib.h

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,51 @@
33
#include "pycore_lock.h" // PyMutex
44

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

32-
#define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) \
33-
GET_BUFFER_VIEW_OR_ERROR(obj, viewp, return NULL)
49+
#define GET_BUFFER_VIEW_OR_ERROUT(OBJ, VIEW) \
50+
GET_BUFFER_VIEW_OR_ERROR(OBJ, VIEW, return NULL)
3451

3552
/*
3653
* 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
@@ -1259,42 +1259,60 @@ _hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
12591259
}
12601260

12611261
/*
1262-
* One-shot HMAC-HASH using the given HACL_HID.
1262+
* Obtain a view for 'key' and 'msg', storing it in 'keyview' and 'msgview'.
1263+
*
1264+
* Return 0 on success; otherwise set an exception and return -1.
12631265
*
12641266
* The length of the key and message buffers must not exceed UINT32_MAX,
12651267
* lest an OverflowError is raised. The Python implementation takes care
12661268
* of dispatching to the OpenSSL implementation in this case.
12671269
*/
1268-
#define Py_HMAC_HACL_ONESHOT(HACL_HID, KEY, MSG) \
1269-
do { \
1270-
Py_buffer keyview, msgview; \
1271-
GET_BUFFER_VIEW_OR_ERROUT((KEY), &keyview); \
1272-
if (!has_uint32_t_buffer_length(&keyview)) { \
1273-
PyBuffer_Release(&keyview); \
1274-
set_invalid_key_length_error(); \
1275-
return NULL; \
1276-
} \
1277-
GET_BUFFER_VIEW_OR_ERROR((MSG), &msgview, \
1278-
PyBuffer_Release(&keyview); \
1279-
return NULL); \
1280-
if (!has_uint32_t_buffer_length(&msgview)) { \
1281-
PyBuffer_Release(&msgview); \
1282-
PyBuffer_Release(&keyview); \
1283-
set_invalid_msg_length_error(); \
1284-
return NULL; \
1285-
} \
1286-
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
1287-
Py_hmac_## HACL_HID ##_compute_func( \
1288-
out, \
1289-
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
1290-
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
1291-
); \
1292-
PyBuffer_Release(&msgview); \
1293-
PyBuffer_Release(&keyview); \
1294-
return PyBytes_FromStringAndSize( \
1295-
(const char *)out, \
1296-
Py_hmac_## HACL_HID ##_digest_size \
1297-
); \
1270+
static int
1271+
hmac_get_buffer_views(PyObject *key, Py_buffer *keyview,
1272+
PyObject *msg, Py_buffer *msgview)
1273+
{
1274+
if (_Py_hashlib_get_buffer_view(key, keyview) < 0) {
1275+
return -1;
1276+
}
1277+
if (!has_uint32_t_buffer_length(keyview)) {
1278+
PyBuffer_Release(keyview);
1279+
set_invalid_key_length_error();
1280+
return -1;
1281+
}
1282+
if (_Py_hashlib_get_buffer_view(msg, msgview) < 0) {
1283+
PyBuffer_Release(keyview);
1284+
return -1;
1285+
}
1286+
if (!has_uint32_t_buffer_length(msgview)) {
1287+
PyBuffer_Release(msgview);
1288+
PyBuffer_Release(keyview);
1289+
set_invalid_msg_length_error();
1290+
return -1;
1291+
}
1292+
return 0;
1293+
}
1294+
1295+
/*
1296+
* One-shot HMAC-HASH using the given HACL_HID.
1297+
*/
1298+
#define HACL_HMAC_COMPUTE_NAMED_DIGEST(HACL_HID, KEY, MSG) \
1299+
do { \
1300+
Py_buffer keyview, msgview; \
1301+
if (hmac_get_buffer_views(key, &keyview, msg, &msgview) < 0) { \
1302+
return NULL; \
1303+
} \
1304+
uint8_t out[Py_hmac_## HACL_HID ##_digest_size]; \
1305+
Py_hmac_## HACL_HID ##_compute_func( \
1306+
out, \
1307+
(uint8_t *)keyview.buf, (uint32_t)keyview.len, \
1308+
(uint8_t *)msgview.buf, (uint32_t)msgview.len \
1309+
); \
1310+
PyBuffer_Release(&msgview); \
1311+
PyBuffer_Release(&keyview); \
1312+
return PyBytes_FromStringAndSize( \
1313+
(const char *)out, \
1314+
Py_hmac_## HACL_HID ##_digest_size \
1315+
); \
12981316
} while (0)
12991317

13001318
/*[clinic input]
@@ -1310,7 +1328,7 @@ static PyObject *
13101328
_hmac_compute_md5_impl(PyObject *module, PyObject *key, PyObject *msg)
13111329
/*[clinic end generated code: output=7837a4ceccbbf636 input=77a4b774c7d61218]*/
13121330
{
1313-
Py_HMAC_HACL_ONESHOT(md5, key, msg);
1331+
HACL_HMAC_COMPUTE_NAMED_DIGEST(md5, key, msg);
13141332
}
13151333

13161334
/*[clinic input]
@@ -1326,7 +1344,7 @@ static PyObject *
13261344
_hmac_compute_sha1_impl(PyObject *module, PyObject *key, PyObject *msg)
13271345
/*[clinic end generated code: output=79fd7689c83691d8 input=3b64dccc6bdbe4ba]*/
13281346
{
1329-
Py_HMAC_HACL_ONESHOT(sha1, key, msg);
1347+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha1, key, msg);
13301348
}
13311349

13321350
/*[clinic input]
@@ -1342,7 +1360,7 @@ static PyObject *
13421360
_hmac_compute_sha2_224_impl(PyObject *module, PyObject *key, PyObject *msg)
13431361
/*[clinic end generated code: output=7f21f1613e53979e input=a1a75f25f23449af]*/
13441362
{
1345-
Py_HMAC_HACL_ONESHOT(sha2_224, key, msg);
1363+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_224, key, msg);
13461364
}
13471365

13481366
/*[clinic input]
@@ -1358,7 +1376,7 @@ static PyObject *
13581376
_hmac_compute_sha2_256_impl(PyObject *module, PyObject *key, PyObject *msg)
13591377
/*[clinic end generated code: output=d4a291f7d9a82459 input=5c9ccf2df048ace3]*/
13601378
{
1361-
Py_HMAC_HACL_ONESHOT(sha2_256, key, msg);
1379+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_256, key, msg);
13621380
}
13631381

13641382
/*[clinic input]
@@ -1374,7 +1392,7 @@ static PyObject *
13741392
_hmac_compute_sha2_384_impl(PyObject *module, PyObject *key, PyObject *msg)
13751393
/*[clinic end generated code: output=f211fa26e3700c27 input=2fee2c14766af231]*/
13761394
{
1377-
Py_HMAC_HACL_ONESHOT(sha2_384, key, msg);
1395+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_384, key, msg);
13781396
}
13791397

13801398
/*[clinic input]
@@ -1390,7 +1408,7 @@ static PyObject *
13901408
_hmac_compute_sha2_512_impl(PyObject *module, PyObject *key, PyObject *msg)
13911409
/*[clinic end generated code: output=d5c20373762cecca input=3371eaac315c7864]*/
13921410
{
1393-
Py_HMAC_HACL_ONESHOT(sha2_512, key, msg);
1411+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha2_512, key, msg);
13941412
}
13951413

13961414
/*[clinic input]
@@ -1406,7 +1424,7 @@ static PyObject *
14061424
_hmac_compute_sha3_224_impl(PyObject *module, PyObject *key, PyObject *msg)
14071425
/*[clinic end generated code: output=a242ccac9ad9c22b input=d0ab0c7d189c3d87]*/
14081426
{
1409-
Py_HMAC_HACL_ONESHOT(sha3_224, key, msg);
1427+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_224, key, msg);
14101428
}
14111429

14121430
/*[clinic input]
@@ -1422,7 +1440,7 @@ static PyObject *
14221440
_hmac_compute_sha3_256_impl(PyObject *module, PyObject *key, PyObject *msg)
14231441
/*[clinic end generated code: output=b539dbb61af2fe0b input=f05d7b6364b35d02]*/
14241442
{
1425-
Py_HMAC_HACL_ONESHOT(sha3_256, key, msg);
1443+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_256, key, msg);
14261444
}
14271445

14281446
/*[clinic input]
@@ -1438,7 +1456,7 @@ static PyObject *
14381456
_hmac_compute_sha3_384_impl(PyObject *module, PyObject *key, PyObject *msg)
14391457
/*[clinic end generated code: output=5eb372fb5c4ffd3a input=d842d393e7aa05ae]*/
14401458
{
1441-
Py_HMAC_HACL_ONESHOT(sha3_384, key, msg);
1459+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_384, key, msg);
14421460
}
14431461

14441462
/*[clinic input]
@@ -1454,7 +1472,7 @@ static PyObject *
14541472
_hmac_compute_sha3_512_impl(PyObject *module, PyObject *key, PyObject *msg)
14551473
/*[clinic end generated code: output=154bcbf8c2eacac1 input=166fe5baaeaabfde]*/
14561474
{
1457-
Py_HMAC_HACL_ONESHOT(sha3_512, key, msg);
1475+
HACL_HMAC_COMPUTE_NAMED_DIGEST(sha3_512, key, msg);
14581476
}
14591477

14601478
/*[clinic input]
@@ -1470,7 +1488,7 @@ static PyObject *
14701488
_hmac_compute_blake2s_32_impl(PyObject *module, PyObject *key, PyObject *msg)
14711489
/*[clinic end generated code: output=cfc730791bc62361 input=d22c36e7fe31a985]*/
14721490
{
1473-
Py_HMAC_HACL_ONESHOT(blake2s_32, key, msg);
1491+
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2s_32, key, msg);
14741492
}
14751493

14761494
/*[clinic input]
@@ -1486,9 +1504,11 @@ static PyObject *
14861504
_hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
14871505
/*[clinic end generated code: output=765c5c4fb9124636 input=4a35ee058d172f4b]*/
14881506
{
1489-
Py_HMAC_HACL_ONESHOT(blake2b_32, key, msg);
1507+
HACL_HMAC_COMPUTE_NAMED_DIGEST(blake2b_32, key, msg);
14901508
}
14911509

1510+
#undef HACL_HMAC_COMPUTE_NAMED_DIGEST
1511+
14921512
// --- HMAC module methods ----------------------------------------------------
14931513

14941514
static PyMethodDef hmacmodule_methods[] = {

0 commit comments

Comments
 (0)