Skip to content

Commit b8eaad3

Browse files
gh-117233: Detect support for several hashes at hashlib build time (GH-117234)
Detect libcrypto BLAKE2, Shake, SHA3, and Truncated-SHA512 support at hashlib build time ## BLAKE2 While OpenSSL supports both "b" and "s" variants of the BLAKE2 hash function, other cryptographic libraries may lack support for one or both of the variants. This commit modifies `hashlib`'s C code to detect whether or not the linked libcrypto supports each BLAKE2 variant, and elides references to each variant's NID accordingly. In cases where the underlying libcrypto doesn't fully support BLAKE2, CPython's `./configure` script can be given the following flag to use CPython's interned BLAKE2 implementation: `--with-builtin-hashlib-hashes=blake2`. ## SHA3, Shake, & truncated SHA512. Detect BLAKE2, SHA3, Shake, & truncated SHA512 support in the OpenSSL-ish libcrypto library at build time. This helps allow hashlib's `_hashopenssl` to be used with libraries that do not to support every algorithm that upstream OpenSSL does. Such as AWS-LC & BoringSSL. Co-authored-by: Gregory P. Smith [Google LLC] <[email protected]>
1 parent 01a51f9 commit b8eaad3

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Detect BLAKE2, SHA3, Shake, & truncated SHA512 support in the OpenSSL-ish
2+
libcrypto library at build time. This allows :mod:`hashlib` to be used with
3+
libraries that do not to support every algorithm that upstream OpenSSL does.

Modules/_hashopenssl.c

+59-10
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,15 @@
4545
#define MUNCH_SIZE INT_MAX
4646

4747
#define PY_OPENSSL_HAS_SCRYPT 1
48+
#if defined(NID_sha3_224) && defined(NID_sha3_256) && defined(NID_sha3_384) && defined(NID_sha3_512)
4849
#define PY_OPENSSL_HAS_SHA3 1
50+
#endif
51+
#if defined(NID_shake128) || defined(NID_shake256)
4952
#define PY_OPENSSL_HAS_SHAKE 1
53+
#endif
54+
#if defined(NID_blake2s256) || defined(NID_blake2b512)
5055
#define PY_OPENSSL_HAS_BLAKE2 1
56+
#endif
5157

5258
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
5359
#define PY_EVP_MD EVP_MD
@@ -88,22 +94,45 @@ typedef struct {
8894
PY_EVP_MD *evp_nosecurity;
8995
} py_hashentry_t;
9096

97+
// Fundamental to TLS, assumed always present in any libcrypto:
9198
#define Py_hash_md5 "md5"
9299
#define Py_hash_sha1 "sha1"
93100
#define Py_hash_sha224 "sha224"
94101
#define Py_hash_sha256 "sha256"
95102
#define Py_hash_sha384 "sha384"
96103
#define Py_hash_sha512 "sha512"
97-
#define Py_hash_sha512_224 "sha512_224"
98-
#define Py_hash_sha512_256 "sha512_256"
99-
#define Py_hash_sha3_224 "sha3_224"
100-
#define Py_hash_sha3_256 "sha3_256"
101-
#define Py_hash_sha3_384 "sha3_384"
102-
#define Py_hash_sha3_512 "sha3_512"
103-
#define Py_hash_shake_128 "shake_128"
104-
#define Py_hash_shake_256 "shake_256"
105-
#define Py_hash_blake2s "blake2s"
106-
#define Py_hash_blake2b "blake2b"
104+
105+
// Not all OpenSSL-like libcrypto libraries provide these:
106+
#if defined(NID_sha512_224)
107+
# define Py_hash_sha512_224 "sha512_224"
108+
#endif
109+
#if defined(NID_sha512_256)
110+
# define Py_hash_sha512_256 "sha512_256"
111+
#endif
112+
#if defined(NID_sha3_224)
113+
# define Py_hash_sha3_224 "sha3_224"
114+
#endif
115+
#if defined(NID_sha3_256)
116+
# define Py_hash_sha3_256 "sha3_256"
117+
#endif
118+
#if defined(NID_sha3_384)
119+
# define Py_hash_sha3_384 "sha3_384"
120+
#endif
121+
#if defined(NID_sha3_512)
122+
# define Py_hash_sha3_512 "sha3_512"
123+
#endif
124+
#if defined(NID_shake128)
125+
# define Py_hash_shake_128 "shake_128"
126+
#endif
127+
#if defined(NID_shake256)
128+
# define Py_hash_shake_256 "shake_256"
129+
#endif
130+
#if defined(NID_blake2s256)
131+
# define Py_hash_blake2s "blake2s"
132+
#endif
133+
#if defined(NID_blake2b512)
134+
# define Py_hash_blake2b "blake2b"
135+
#endif
107136

108137
#define PY_HASH_ENTRY(py_name, py_alias, ossl_name, ossl_nid) \
109138
{py_name, py_alias, ossl_name, ossl_nid, 0, NULL, NULL}
@@ -119,19 +148,39 @@ static const py_hashentry_t py_hashes[] = {
119148
PY_HASH_ENTRY(Py_hash_sha384, "SHA384", SN_sha384, NID_sha384),
120149
PY_HASH_ENTRY(Py_hash_sha512, "SHA512", SN_sha512, NID_sha512),
121150
/* truncated sha2 */
151+
#ifdef Py_hash_sha512_224
122152
PY_HASH_ENTRY(Py_hash_sha512_224, "SHA512_224", SN_sha512_224, NID_sha512_224),
153+
#endif
154+
#ifdef Py_hash_sha512_256
123155
PY_HASH_ENTRY(Py_hash_sha512_256, "SHA512_256", SN_sha512_256, NID_sha512_256),
156+
#endif
124157
/* sha3 */
158+
#ifdef Py_hash_sha3_224
125159
PY_HASH_ENTRY(Py_hash_sha3_224, NULL, SN_sha3_224, NID_sha3_224),
160+
#endif
161+
#ifdef Py_hash_sha3_256
126162
PY_HASH_ENTRY(Py_hash_sha3_256, NULL, SN_sha3_256, NID_sha3_256),
163+
#endif
164+
#ifdef Py_hash_sha3_384
127165
PY_HASH_ENTRY(Py_hash_sha3_384, NULL, SN_sha3_384, NID_sha3_384),
166+
#endif
167+
#ifdef Py_hash_sha3_512
128168
PY_HASH_ENTRY(Py_hash_sha3_512, NULL, SN_sha3_512, NID_sha3_512),
169+
#endif
129170
/* sha3 shake */
171+
#ifdef Py_hash_shake_128
130172
PY_HASH_ENTRY(Py_hash_shake_128, NULL, SN_shake128, NID_shake128),
173+
#endif
174+
#ifdef Py_hash_shake_256
131175
PY_HASH_ENTRY(Py_hash_shake_256, NULL, SN_shake256, NID_shake256),
176+
#endif
132177
/* blake2 digest */
178+
#ifdef Py_hash_blake2s
133179
PY_HASH_ENTRY(Py_hash_blake2s, "blake2s256", SN_blake2s256, NID_blake2s256),
180+
#endif
181+
#ifdef Py_hash_blake2b
134182
PY_HASH_ENTRY(Py_hash_blake2b, "blake2b512", SN_blake2b512, NID_blake2b512),
183+
#endif
135184
PY_HASH_ENTRY(NULL, NULL, NULL, 0),
136185
};
137186

0 commit comments

Comments
 (0)