diff -r e408e821d6c8 Modules/_hashopenssl.c --- a/Modules/_hashopenssl.c Sat Jul 27 02:41:48 2013 +0200 +++ b/Modules/_hashopenssl.c Sun Jul 28 16:38:28 2013 +0200 @@ -466,6 +466,88 @@ return ret_obj; } +PyDoc_STRVAR(PBKDF2__doc__, +"PBKDF2(hash_name, password, salt, iterations, keylen)\n\ +\n\ +Password based key derivation function 2 (PKCS #5 v2.0)."); + +static PyObject * +PBKDF2(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"hash_name", "password", "salt", "iterations", + "keylen", NULL}; + PyObject *key_obj; + char *name, *password, *salt, *key; + Py_ssize_t password_len, salt_len; + long iterations, key_len; + int retval; + const EVP_MD *digest; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "sy#y#ll:pbkdf2", kwlist, + &name, &password, &password_len, + &salt, &salt_len, &iterations, + &key_len)) { + return NULL; + } + + if (password_len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "password is too long."); + return NULL; + } + if (salt_len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "salt is too long."); + return NULL; + } + if (iterations < 1) { + PyErr_SetString(PyExc_ValueError, + "iteration value must be greater than 0."); + return NULL; + } + if (iterations > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "iteration value is too great."); + return NULL; + } + if (key_len < 1) { + PyErr_SetString(PyExc_ValueError, + "key length must be greater than 0."); + return NULL; + } + if (key_len > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "key length is too great."); + return NULL; + } + + digest = EVP_get_digestbyname(name); + if (digest == NULL) { + PyErr_SetString(PyExc_ValueError, "unsupported hash type"); + } + + key_obj = PyBytes_FromStringAndSize(NULL, key_len); + if (key_obj == NULL) { + return NULL; + } + key = PyBytes_AS_STRING(key_obj); + + Py_BEGIN_ALLOW_THREADS + retval = PKCS5_PBKDF2_HMAC(password, password_len, + (unsigned char *)salt, salt_len, + iterations, digest, key_len, + (unsigned char *)key); + Py_END_ALLOW_THREADS + + if (!retval) { + Py_DECREF(key_obj); + PyErr_SetString(PyExc_ValueError, "something went wrong..."); + return NULL; + } + + return key_obj; +} + /* State for our callback function so that it can accumulate a result. */ typedef struct _internal_name_mapper_state { @@ -588,6 +670,7 @@ static struct PyMethodDef EVP_functions[] = { {"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__}, + {"PBKDF2", (PyCFunction)PBKDF2, METH_VARARGS|METH_KEYWORDS, PBKDF2__doc__}, CONSTRUCTOR_METH_DEF(md5), CONSTRUCTOR_METH_DEF(sha1), #ifdef _OPENSSL_SUPPORTS_SHA2