Skip to content

Commit 3c140fa

Browse files
committed
implement hash information lookup
This commit implements the bits needed for finding static hash information data from an algorithm name. Search is case-insensitive and only algorithm names given as strings are supported.
1 parent b9bbb3e commit 3c140fa

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

Modules/hmacmodule.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "_hacl/Hacl_Streaming_HMAC.h" // Hacl_Agile_Hash_* identifiers
2424

25+
#include <stdbool.h>
26+
2527
// --- HMAC underlying hash function static information -----------------------
2628

2729
#define Py_hmac_hash_max_block_size 128
@@ -199,6 +201,96 @@ static const py_hmac_hinfo py_hmac_static_hinfo[] = {
199201
},
200202
};
201203

204+
static inline bool
205+
find_hash_info_by_utf8name(hmacmodule_state *state,
206+
const char *name,
207+
const py_hmac_hinfo **info)
208+
{
209+
assert(name != NULL);
210+
*info = _Py_hashtable_get(state->hinfo_table, name);
211+
return *info != NULL;
212+
}
213+
214+
static int
215+
find_hash_info_by_name(hmacmodule_state *state,
216+
PyObject *name,
217+
const py_hmac_hinfo **info)
218+
{
219+
const char *utf8name = PyUnicode_AsUTF8(name);
220+
if (utf8name == NULL) {
221+
goto error;
222+
}
223+
if (find_hash_info_by_utf8name(state, utf8name, info)) {
224+
return 1;
225+
}
226+
227+
// try to find an alternative using the lowercase name
228+
PyObject *lower = PyObject_CallMethodNoArgs(name, state->str_lower);
229+
if (lower == NULL) {
230+
goto error;
231+
}
232+
const char *utf8lower = PyUnicode_AsUTF8(lower);
233+
if (utf8lower == NULL) {
234+
Py_DECREF(lower);
235+
goto error;
236+
}
237+
int found = find_hash_info_by_utf8name(state, utf8lower, info);
238+
Py_DECREF(lower);
239+
return found;
240+
241+
error:
242+
*info = NULL;
243+
return -1;
244+
}
245+
246+
/*
247+
* Find the corresponding HMAC hash function static information.
248+
*
249+
* If an error occurs or if nothing can be found, this
250+
* returns -1 or 0 respectively, and sets 'info' to NULL.
251+
* Otherwise, this returns 1 and stores the result in 'info'.
252+
*
253+
* Parameters
254+
*
255+
* state The HMAC module state.
256+
* hash_info_ref An input to hashlib.new().
257+
* info The deduced information, if any.
258+
*/
259+
static int
260+
find_hash_info_impl(hmacmodule_state *state,
261+
PyObject *hash_info_ref,
262+
const py_hmac_hinfo **info)
263+
{
264+
if (PyUnicode_Check(hash_info_ref)) {
265+
return find_hash_info_by_name(state, hash_info_ref, info);
266+
}
267+
// NOTE(picnixz): For now, we only support named algorithms.
268+
// In the future, we need to decide whether 'hashlib.openssl_md5'
269+
// would make sense as an alias to 'md5' and how to remove OpenSSL.
270+
*info = NULL;
271+
return 0;
272+
}
273+
274+
static const py_hmac_hinfo *
275+
find_hash_info(hmacmodule_state *state, PyObject *hash_info_ref)
276+
{
277+
const py_hmac_hinfo *info = NULL;
278+
int rc = find_hash_info_impl(state, hash_info_ref, &info);
279+
if (rc < 0) {
280+
assert(info == NULL);
281+
assert(PyErr_Occurred());
282+
return NULL;
283+
}
284+
if (rc == 0) {
285+
assert(info == NULL);
286+
assert(!PyErr_Occurred());
287+
PyErr_Format(state->unknown_hash_error,
288+
"unsupported hash type: %R", hash_info_ref);
289+
return NULL;
290+
}
291+
return info;
292+
}
293+
202294
// --- HMAC module methods ----------------------------------------------------
203295

204296
static PyMethodDef hmacmodule_methods[] = {

0 commit comments

Comments
 (0)