Skip to content

Commit ec3589f

Browse files
bpo-47101: list only activated algorithms in hashlib.algorithms_available (pythonGH-32076)
(cherry picked from commit 48e2010) Co-authored-by: Christian Heimes <christian@python.org>
1 parent e513b81 commit ec3589f

3 files changed

Lines changed: 20 additions & 1 deletion

File tree

Lib/test/test_hashlib.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ def test_algorithms_guaranteed(self):
223223
def test_algorithms_available(self):
224224
self.assertTrue(set(hashlib.algorithms_guaranteed).
225225
issubset(hashlib.algorithms_available))
226+
# all available algorithms must be loadable, bpo-47101
227+
self.assertNotIn("undefined", hashlib.algorithms_available)
228+
for name in hashlib.algorithms_available:
229+
digest = hashlib.new(name, usedforsecurity=False)
226230

227231
def test_usedforsecurity_true(self):
228232
hashlib.new("sha256", usedforsecurity=True)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:const:`hashlib.algorithms_available` now lists only algorithms that are
2+
provided by activated crypto providers on OpenSSL 3.0. Legacy algorithms are
3+
not listed unless the legacy provider has been loaded into the default
4+
OSSL context.

Modules/_hashopenssl.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1860,15 +1860,21 @@ typedef struct _internal_name_mapper_state {
18601860

18611861
/* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */
18621862
static void
1863+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1864+
_openssl_hash_name_mapper(EVP_MD *md, void *arg)
1865+
#else
18631866
_openssl_hash_name_mapper(const EVP_MD *md, const char *from,
18641867
const char *to, void *arg)
1868+
#endif
18651869
{
18661870
_InternalNameMapperState *state = (_InternalNameMapperState *)arg;
18671871
PyObject *py_name;
18681872

18691873
assert(state != NULL);
1870-
if (md == NULL)
1874+
// ignore all undefined providers
1875+
if ((md == NULL) || (EVP_MD_nid(md) == NID_undef)) {
18711876
return;
1877+
}
18721878

18731879
py_name = py_digest_name(md);
18741880
if (py_name == NULL) {
@@ -1894,7 +1900,12 @@ hashlib_md_meth_names(PyObject *module)
18941900
return -1;
18951901
}
18961902

1903+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1904+
// get algorithms from all activated providers in default context
1905+
EVP_MD_do_all_provided(NULL, &_openssl_hash_name_mapper, &state);
1906+
#else
18971907
EVP_MD_do_all(&_openssl_hash_name_mapper, &state);
1908+
#endif
18981909

18991910
if (state.error) {
19001911
Py_DECREF(state.set);

0 commit comments

Comments
 (0)