Skip to content

Commit ad5b0d0

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

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 to '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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy