Skip to content

Commit aa41a74

Browse files
committed
fortify macro usage in cryptographic modules
1 parent 149bddc commit aa41a74

File tree

3 files changed

+100
-65
lines changed

3 files changed

+100
-65
lines changed

Modules/_hashopenssl.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,14 +1252,7 @@ _hashlib_HASH(_hashlibstate *state, const char *digestname, PyObject *data_obj,
12521252
}
12531253

12541254
#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)
1255+
return _hashlib_HASH_new_impl(MODULE, NAME, DATA, USEDFORSECURITY, STRING)
12631256

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

@@ -1285,7 +1278,12 @@ _hashlib_HASH_new_impl(PyObject *module, const char *name, PyObject *data,
12851278
int usedforsecurity, PyObject *string)
12861279
/*[clinic end generated code: output=b905aaf9840c1bbd input=c34af6c6e696d44e]*/
12871280
{
1288-
CALL_HASHLIB_NEW(module, name, data, string, usedforsecurity);
1281+
PyObject *data_obj;
1282+
if (_Py_hashlib_data_argument(&data_obj, data, string) < 0) {
1283+
return NULL;
1284+
}
1285+
_hashlibstate *state = get_hashlib_state(module);
1286+
return _hashlib_HASH(state, name, data_obj, usedforsecurity);
12891287
}
12901288

12911289

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: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,43 +1098,61 @@ _hmac_compute_digest_impl(PyObject *module, PyObject *key, PyObject *msg,
10981098
return info->api.compute_py(module, key, msg);
10991099
}
11001100

1101+
/*
1102+
* Obtain a view from 'key' and 'msg', storing it in 'keyview' and 'msgview'.
1103+
*
1104+
* Return 0 on success; otherwise set an exception and return -1.
1105+
*/
1106+
static int
1107+
hmac_get_buffer_views(PyObject *key, Py_buffer *keyview,
1108+
PyObject *msg, Py_buffer *msgview)
1109+
{
1110+
if (_Py_hashlib_get_buffer_view(key, keyview) < 0) {
1111+
return -1;
1112+
}
1113+
if (!has_uint32_t_buffer_length(keyview)) {
1114+
PyBuffer_Release(keyview);
1115+
set_invalid_key_length_error();
1116+
return -1;
1117+
}
1118+
if (_Py_hashlib_get_buffer_view(msg, msgview) < 0) {
1119+
PyBuffer_Release(keyview);
1120+
return -1;
1121+
}
1122+
if (!has_uint32_t_buffer_length(msgview)) {
1123+
PyBuffer_Release(msgview);
1124+
PyBuffer_Release(keyview);
1125+
set_invalid_msg_length_error();
1126+
return -1;
1127+
}
1128+
return 0;
1129+
}
1130+
11011131
/*
11021132
* One-shot HMAC-HASH using the given HACL_HID.
11031133
*
11041134
* The length of the key and message buffers must not exceed UINT32_MAX,
11051135
* lest an OverflowError is raised. The Python implementation takes care
11061136
* of dispatching to the OpenSSL implementation in this case.
11071137
*/
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-
); \
1138+
#define Py_HMAC_HACL_ONESHOT(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]
@@ -1329,6 +1347,8 @@ _hmac_compute_blake2b_32_impl(PyObject *module, PyObject *key, PyObject *msg)
13291347
Py_HMAC_HACL_ONESHOT(blake2b_32, key, msg);
13301348
}
13311349

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

13341354
static PyMethodDef hmacmodule_methods[] = {

0 commit comments

Comments
 (0)