Skip to content

Commit

Permalink
bpo-38134: Remove PKBDF2_HMAC_fast from _hashopenssl (pythonGH-16028)
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Heimes <[email protected]>
  • Loading branch information
tiran authored and gpshead committed Sep 12, 2019
1 parent 31a82e2 commit 64117e0
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 123 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Remove obsolete copy of PBKDF2_HMAC_fast. All supported OpenSSL versions
contain a fast implementation.
114 changes: 0 additions & 114 deletions Modules/_hashopenssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,6 @@

#define MUNCH_SIZE INT_MAX

#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
/* OpenSSL < 1.1.0 */
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#define HAS_FAST_PKCS5_PBKDF2_HMAC 0
#include <openssl/hmac.h>
#else
/* OpenSSL >= 1.1.0 */
#define HAS_FAST_PKCS5_PBKDF2_HMAC 1
#endif


typedef struct {
PyObject_HEAD
PyObject *name; /* name of this hash algorithm */
Expand Down Expand Up @@ -481,97 +469,6 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj)
return ret_obj;
}

#if (OPENSSL_VERSION_NUMBER >= 0x10000000 && !defined(OPENSSL_NO_HMAC) \
&& !defined(OPENSSL_NO_SHA))

#define PY_PBKDF2_HMAC 1

#if !HAS_FAST_PKCS5_PBKDF2_HMAC
/* Improved implementation of PKCS5_PBKDF2_HMAC()
*
* PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of
* `iter` times. Today (2013) the iteration count is typically 100,000 or
* more. The improved algorithm is not subject to a Denial-of-Service
* vulnerability with overly large passwords.
*
* Also OpenSSL < 1.0 don't provide PKCS5_PBKDF2_HMAC(), only
* PKCS5_PBKDF2_SHA1.
*/
static int
PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen,
const unsigned char *salt, int saltlen,
int iter, const EVP_MD *digest,
int keylen, unsigned char *out)
{
unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
int cplen, j, k, tkeylen, mdlen;
unsigned long i = 1;
HMAC_CTX hctx_tpl, hctx;

mdlen = EVP_MD_size(digest);
if (mdlen < 0)
return 0;

HMAC_CTX_init(&hctx_tpl);
HMAC_CTX_init(&hctx);
p = out;
tkeylen = keylen;
if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
while (tkeylen) {
if (tkeylen > mdlen)
cplen = mdlen;
else
cplen = tkeylen;
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case...
*/
itmp[0] = (unsigned char)((i >> 24) & 0xff);
itmp[1] = (unsigned char)((i >> 16) & 0xff);
itmp[2] = (unsigned char)((i >> 8) & 0xff);
itmp[3] = (unsigned char)(i & 0xff);
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, salt, saltlen)
|| !HMAC_Update(&hctx, itmp, 4)
|| !HMAC_Final(&hctx, digtmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
memcpy(p, digtmp, cplen);
for (j = 1; j < iter; j++) {
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, digtmp, mdlen)
|| !HMAC_Final(&hctx, digtmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
for (k = 0; k < cplen; k++) {
p[k] ^= digtmp[k];
}
}
tkeylen-= cplen;
i++;
p+= cplen;
}
HMAC_CTX_cleanup(&hctx_tpl);
return 1;
}
#endif



/*[clinic input]
_hashlib.pbkdf2_hmac as pbkdf2_hmac
Expand Down Expand Up @@ -652,17 +549,10 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
key = PyBytes_AS_STRING(key_obj);

Py_BEGIN_ALLOW_THREADS
#if HAS_FAST_PKCS5_PBKDF2_HMAC
retval = PKCS5_PBKDF2_HMAC((char*)password->buf, (int)password->len,
(unsigned char *)salt->buf, (int)salt->len,
iterations, digest, dklen,
(unsigned char *)key);
#else
retval = PKCS5_PBKDF2_HMAC_fast((char*)password->buf, (int)password->len,
(unsigned char *)salt->buf, (int)salt->len,
iterations, digest, dklen,
(unsigned char *)key);
#endif
Py_END_ALLOW_THREADS

if (!retval) {
Expand All @@ -675,8 +565,6 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
return key_obj;
}

#endif

#if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)
#define PY_SCRYPT 1

Expand Down Expand Up @@ -986,9 +874,7 @@ GEN_CONSTRUCTOR(sha512)

static struct PyMethodDef EVP_functions[] = {
EVP_NEW_METHODDEF
#ifdef PY_PBKDF2_HMAC
PBKDF2_HMAC_METHODDEF
#endif
_HASHLIB_SCRYPT_METHODDEF
_HASHLIB_HMAC_DIGEST_METHODDEF
CONSTRUCTOR_METH_DEF(md5),
Expand Down
10 changes: 1 addition & 9 deletions Modules/clinic/_hashopenssl.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 64117e0

Please sign in to comment.