|
20 | 20 |
|
21 | 21 | /* EVP is the preferred interface to hashing in OpenSSL */ |
22 | 22 | #include <openssl/evp.h> |
| 23 | +#include <openssl/hmac.h> |
23 | 24 | /* We use the object interface to discover what hashes OpenSSL supports. */ |
24 | 25 | #include <openssl/objects.h> |
25 | 26 | #include "openssl/err.h" |
@@ -495,10 +496,97 @@ EVP_new(PyObject *self, PyObject *args, PyObject *kwdict) |
495 | 496 | return ret_obj; |
496 | 497 | } |
497 | 498 |
|
498 | | -#if (OPENSSL_VERSION_NUMBER >= 0x10000000 && !defined(OPENSSL_NO_HMAC) \ |
499 | | - && !defined(OPENSSL_NO_SHA)) |
| 499 | + |
| 500 | + |
| 501 | +#if (!defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA)) |
| 502 | + |
500 | 503 | #define PY_PBKDF2_HMAC 1 |
501 | 504 |
|
| 505 | +/* Improved implementation of PKCS5_PBKDF2_HMAC() |
| 506 | + * |
| 507 | + * PKCS5_PBKDF2_HMAC_fast() hashes the password exactly one time instead of |
| 508 | + * `iter` times. Today (2013) the iteration count is typically 100,000 or |
| 509 | + * more. The improved algorithm is not subject to a Denial-of-Service |
| 510 | + * vulnerability with overly large passwords. |
| 511 | + * |
| 512 | + * Also OpenSSL < 1.0 don't provide PKCS5_PBKDF2_HMAC(), only |
| 513 | + * PKCS5_PBKDF2_SHA1. |
| 514 | + */ |
| 515 | +int PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen, |
| 516 | + const unsigned char *salt, int saltlen, |
| 517 | + int iter, const EVP_MD *digest, |
| 518 | + int keylen, unsigned char *out) |
| 519 | +{ |
| 520 | + unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; |
| 521 | + int cplen, j, k, tkeylen, mdlen; |
| 522 | + unsigned long i = 1; |
| 523 | + HMAC_CTX hctx_tpl, hctx; |
| 524 | + |
| 525 | + mdlen = EVP_MD_size(digest); |
| 526 | + if (mdlen < 0) |
| 527 | + return 0; |
| 528 | + |
| 529 | + HMAC_CTX_init(&hctx_tpl); |
| 530 | + HMAC_CTX_init(&hctx); |
| 531 | + p = out; |
| 532 | + tkeylen = keylen; |
| 533 | + if (!pass) |
| 534 | + passlen = 0; |
| 535 | + else if(passlen == -1) |
| 536 | + passlen = strlen(pass); |
| 537 | + if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) { |
| 538 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 539 | + return 0; |
| 540 | + } |
| 541 | + while(tkeylen) { |
| 542 | + if(tkeylen > mdlen) |
| 543 | + cplen = mdlen; |
| 544 | + else |
| 545 | + cplen = tkeylen; |
| 546 | + /* We are unlikely to ever use more than 256 blocks (5120 bits!) |
| 547 | + * but just in case... |
| 548 | + */ |
| 549 | + itmp[0] = (unsigned char)((i >> 24) & 0xff); |
| 550 | + itmp[1] = (unsigned char)((i >> 16) & 0xff); |
| 551 | + itmp[2] = (unsigned char)((i >> 8) & 0xff); |
| 552 | + itmp[3] = (unsigned char)(i & 0xff); |
| 553 | + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { |
| 554 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 555 | + return 0; |
| 556 | + } |
| 557 | + if (!HMAC_Update(&hctx, salt, saltlen) |
| 558 | + || !HMAC_Update(&hctx, itmp, 4) |
| 559 | + || !HMAC_Final(&hctx, digtmp, NULL)) { |
| 560 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 561 | + HMAC_CTX_cleanup(&hctx); |
| 562 | + return 0; |
| 563 | + } |
| 564 | + memcpy(p, digtmp, cplen); |
| 565 | + for (j = 1; j < iter; j++) { |
| 566 | + if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) { |
| 567 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 568 | + return 0; |
| 569 | + } |
| 570 | + if (!HMAC_Update(&hctx, digtmp, mdlen) |
| 571 | + || !HMAC_Final(&hctx, digtmp, NULL)) { |
| 572 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 573 | + HMAC_CTX_cleanup(&hctx); |
| 574 | + return 0; |
| 575 | + } |
| 576 | + HMAC_CTX_cleanup(&hctx); |
| 577 | + for (k = 0; k < cplen; k++) { |
| 578 | + p[k] ^= digtmp[k]; |
| 579 | + } |
| 580 | + } |
| 581 | + tkeylen-= cplen; |
| 582 | + i++; |
| 583 | + p+= cplen; |
| 584 | + } |
| 585 | + HMAC_CTX_cleanup(&hctx_tpl); |
| 586 | + return 1; |
| 587 | +} |
| 588 | + |
| 589 | + |
502 | 590 | PyDoc_STRVAR(pbkdf2_hmac__doc__, |
503 | 591 | "pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\ |
504 | 592 | \n\ |
@@ -579,10 +667,10 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) |
579 | 667 | key = PyBytes_AS_STRING(key_obj); |
580 | 668 |
|
581 | 669 | Py_BEGIN_ALLOW_THREADS |
582 | | - retval = PKCS5_PBKDF2_HMAC((char*)password.buf, password.len, |
583 | | - (unsigned char *)salt.buf, salt.len, |
584 | | - iterations, digest, dklen, |
585 | | - (unsigned char *)key); |
| 670 | + retval = PKCS5_PBKDF2_HMAC_fast((char*)password.buf, password.len, |
| 671 | + (unsigned char *)salt.buf, salt.len, |
| 672 | + iterations, digest, dklen, |
| 673 | + (unsigned char *)key); |
586 | 674 | Py_END_ALLOW_THREADS |
587 | 675 |
|
588 | 676 | if (!retval) { |
|
0 commit comments