diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index d7e613c886c..6da057acd21 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -26,12 +26,6 @@ #include #include "openssl/err.h" -#include "clinic/_hashopenssl.c.h" -/*[clinic input] -module _hashlib -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c2b4ff081bac4be1]*/ - #define MUNCH_SIZE INT_MAX #ifndef HASH_OBJ_CONSTRUCTOR @@ -72,6 +66,13 @@ DEFINE_CONSTS_FOR_NEW(sha256) DEFINE_CONSTS_FOR_NEW(sha384) DEFINE_CONSTS_FOR_NEW(sha512) +#include "clinic/_hashopenssl.c.h" +/*[clinic input] +module _hashlib +class _hashlib.HASH "EVPobject *" "&EVPtype" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a881a5092eecad28]*/ + /* LCOV_EXCL_START */ static PyObject * @@ -169,11 +170,15 @@ locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self) /* External methods for a hash object */ -PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object."); +/*[clinic input] +_hashlib.HASH.copy as EVP_copy +Return a copy of the hash object. +[clinic start generated code]*/ static PyObject * -EVP_copy(EVPobject *self, PyObject *unused) +EVP_copy_impl(EVPobject *self) +/*[clinic end generated code: output=b370c21cdb8ca0b4 input=31455b6a3e638069]*/ { EVPobject *newobj; @@ -186,11 +191,15 @@ EVP_copy(EVPobject *self, PyObject *unused) return (PyObject *)newobj; } -PyDoc_STRVAR(EVP_digest__doc__, -"Return the digest value as a bytes object."); +/*[clinic input] +_hashlib.HASH.digest as EVP_digest + +Return the digest value as a bytes object. +[clinic start generated code]*/ static PyObject * -EVP_digest(EVPobject *self, PyObject *unused) +EVP_digest_impl(EVPobject *self) +/*[clinic end generated code: output=0f6a3a0da46dc12d input=03561809a419bf00]*/ { unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX *temp_ctx; @@ -217,11 +226,15 @@ EVP_digest(EVPobject *self, PyObject *unused) return retval; } -PyDoc_STRVAR(EVP_hexdigest__doc__, -"Return the digest value as a string of hexadecimal digits."); +/*[clinic input] +_hashlib.HASH.hexdigest as EVP_hexdigest + +Return the digest value as a string of hexadecimal digits. +[clinic start generated code]*/ static PyObject * -EVP_hexdigest(EVPobject *self, PyObject *unused) +EVP_hexdigest_impl(EVPobject *self) +/*[clinic end generated code: output=18e6decbaf197296 input=aff9cf0e4c741a9a]*/ { unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX *temp_ctx; @@ -248,18 +261,21 @@ EVP_hexdigest(EVPobject *self, PyObject *unused) return _Py_strhex((const char *)digest, (Py_ssize_t)digest_size); } -PyDoc_STRVAR(EVP_update__doc__, -"Update this hash object's state with the provided string."); +/*[clinic input] +_hashlib.HASH.update as EVP_update + + obj: object + / + +Update this hash object's state with the provided string. +[clinic start generated code]*/ static PyObject * -EVP_update(EVPobject *self, PyObject *args) +EVP_update(EVPobject *self, PyObject *obj) +/*[clinic end generated code: output=ec1d55ed2432e966 input=9b30ec848f015501]*/ { - PyObject *obj; Py_buffer view; - if (!PyArg_ParseTuple(args, "O:update", &obj)) - return NULL; - GET_BUFFER_VIEW_OR_ERROUT(obj, &view); if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) { @@ -282,10 +298,10 @@ EVP_update(EVPobject *self, PyObject *args) } static PyMethodDef EVP_methods[] = { - {"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__}, - {"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__}, - {"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__}, - {"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__}, + EVP_UPDATE_METHODDEF + EVP_DIGEST_METHODDEF + EVP_HEXDIGEST_METHODDEF + EVP_COPY_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -329,24 +345,37 @@ EVP_repr(EVPobject *self) return PyUnicode_FromFormat("<%U HASH object @ %p>", self->name, self); } -#if HASH_OBJ_CONSTRUCTOR +/*[clinic input] +_hashlib.HASH.__init__ as EVP_tp_init + + name as name_obj: object + string as data_obj: object(py_default="b''") = NULL + +A hash is an object used to calculate a checksum of a string of information. + +Methods: + +update() -- updates the current digest with an additional string +digest() -- return the current digest value +hexdigest() -- return the current digest as a string of hexadecimal digits +copy() -- return a copy of the current hash object + +Attributes: + +name -- the hash algorithm being used by this object +digest_size -- number of bytes in this hashes output +[clinic start generated code]*/ + static int -EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) +EVP_tp_init_impl(EVPobject *self, PyObject *name_obj, PyObject *data_obj) +/*[clinic end generated code: output=44766d27757cf851 input=dac22658387f9b5d]*/ { - static char *kwlist[] = {"name", "string", NULL}; - PyObject *name_obj = NULL; - PyObject *data_obj = NULL; Py_buffer view; char *nameStr; const EVP_MD *digest; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:HASH", kwlist, - &name_obj, &data_obj)) { - return -1; - } - if (data_obj) - GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); + GET_BUFFER_VIEW_OR_ERROR(data_obj, &view, return -1); if (!PyArg_Parse(name_obj, "s", &nameStr)) { PyErr_SetString(PyExc_TypeError, "name must be a string"); @@ -385,25 +414,8 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) return 0; } -#endif -PyDoc_STRVAR(hashtype_doc, -"A hash represents the object used to calculate a checksum of a\n\ -string of information.\n\ -\n\ -Methods:\n\ -\n\ -update() -- updates the current digest with an additional string\n\ -digest() -- return the current digest value\n\ -hexdigest() -- return the current digest as a string of hexadecimal digits\n\ -copy() -- return a copy of the current hash object\n\ -\n\ -Attributes:\n\ -\n\ -name -- the hash algorithm being used by this object\n\ -digest_size -- number of bytes in this hashes output\n"); - static PyTypeObject EVPtype = { PyVarObject_HEAD_INIT(NULL, 0) "_hashlib.HASH", /*tp_name*/ @@ -426,7 +438,7 @@ static PyTypeObject EVPtype = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - hashtype_doc, /*tp_doc*/ + EVP_tp_init__doc__, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ @@ -489,29 +501,29 @@ EVPnew(PyObject *name_obj, /* The module-level function: new() */ -PyDoc_STRVAR(EVP_new__doc__, -"Return a new hash object using the named algorithm.\n\ -An optional string argument may be provided and will be\n\ -automatically hashed.\n\ -\n\ -The MD5 and SHA1 algorithms are always supported.\n"); +/*[clinic input] +_hashlib.new as EVP_new + + name as name_obj: object + string as data_obj: object(py_default="b''") = NULL + +Return a new hash object using the named algorithm. + +An optional string argument may be provided and will be +automatically hashed. + +The MD5 and SHA1 algorithms are always supported. +[clinic start generated code]*/ static PyObject * -EVP_new(PyObject *self, PyObject *args, PyObject *kwdict) +EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj) +/*[clinic end generated code: output=9e7cf664e04b0226 input=1c46e40e0fec91f3]*/ { - static char *kwlist[] = {"name", "string", NULL}; - PyObject *name_obj = NULL; - PyObject *data_obj = NULL; Py_buffer view = { 0 }; PyObject *ret_obj; char *name; const EVP_MD *digest; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|O:new", kwlist, - &name_obj, &data_obj)) { - return NULL; - } - if (!PyArg_Parse(name_obj, "s", &name)) { PyErr_SetString(PyExc_TypeError, "name must be a string"); return NULL; @@ -619,43 +631,44 @@ PKCS5_PBKDF2_HMAC_fast(const char *pass, int passlen, #endif -PyDoc_STRVAR(pbkdf2_hmac__doc__, -"pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) -> key\n\ -\n\ -Password based key derivation function 2 (PKCS #5 v2.0) with HMAC as\n\ -pseudorandom function."); + +/*[clinic input] +_hashlib.pbkdf2_hmac as pbkdf2_hmac + + hash_name: str + password: Py_buffer + salt: Py_buffer + iterations: long + dklen as dklen_obj: object = None + +Password based key derivation function 2 (PKCS #5 v2.0) with HMAC as pseudorandom function. +[clinic start generated code]*/ static PyObject * -pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) +pbkdf2_hmac_impl(PyObject *module, const char *hash_name, + Py_buffer *password, Py_buffer *salt, long iterations, + PyObject *dklen_obj) +/*[clinic end generated code: output=144b76005416599b input=ed3ab0d2d28b5d5c]*/ { - static char *kwlist[] = {"hash_name", "password", "salt", "iterations", - "dklen", NULL}; - PyObject *key_obj = NULL, *dklen_obj = Py_None; - char *name, *key; - Py_buffer password, salt; - long iterations, dklen; + PyObject *key_obj = NULL; + char *key; + long dklen; int retval; const EVP_MD *digest; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "sy*y*l|O:pbkdf2_hmac", - kwlist, &name, &password, &salt, - &iterations, &dklen_obj)) { - return NULL; - } - - digest = EVP_get_digestbyname(name); + digest = EVP_get_digestbyname(hash_name); if (digest == NULL) { PyErr_SetString(PyExc_ValueError, "unsupported hash type"); goto end; } - if (password.len > INT_MAX) { + if (password->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "password is too long."); goto end; } - if (salt.len > INT_MAX) { + if (salt->len > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "salt is too long."); goto end; @@ -700,13 +713,13 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) 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, + 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, + 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 @@ -719,8 +732,6 @@ pbkdf2_hmac(PyObject *self, PyObject *args, PyObject *kwdict) } end: - PyBuffer_Release(&password); - PyBuffer_Release(&salt); return key_obj; } @@ -1034,10 +1045,9 @@ GEN_CONSTRUCTOR(sha512) /* List of functions exported by this module */ static struct PyMethodDef EVP_functions[] = { - {"new", (PyCFunction)(void(*)(void))EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__}, + EVP_NEW_METHODDEF #ifdef PY_PBKDF2_HMAC - {"pbkdf2_hmac", (PyCFunction)(void(*)(void))pbkdf2_hmac, METH_VARARGS|METH_KEYWORDS, - pbkdf2_hmac__doc__}, + PBKDF2_HMAC_METHODDEF #endif _HASHLIB_SCRYPT_METHODDEF _HASHLIB_HMAC_DIGEST_METHODDEF diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h index 3dad45de671..5f2b23560ef 100644 --- a/Modules/clinic/_hashopenssl.c.h +++ b/Modules/clinic/_hashopenssl.c.h @@ -2,6 +2,195 @@ preserve [clinic start generated code]*/ +PyDoc_STRVAR(EVP_copy__doc__, +"copy($self, /)\n" +"--\n" +"\n" +"Return a copy of the hash object."); + +#define EVP_COPY_METHODDEF \ + {"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__}, + +static PyObject * +EVP_copy_impl(EVPobject *self); + +static PyObject * +EVP_copy(EVPobject *self, PyObject *Py_UNUSED(ignored)) +{ + return EVP_copy_impl(self); +} + +PyDoc_STRVAR(EVP_digest__doc__, +"digest($self, /)\n" +"--\n" +"\n" +"Return the digest value as a bytes object."); + +#define EVP_DIGEST_METHODDEF \ + {"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__}, + +static PyObject * +EVP_digest_impl(EVPobject *self); + +static PyObject * +EVP_digest(EVPobject *self, PyObject *Py_UNUSED(ignored)) +{ + return EVP_digest_impl(self); +} + +PyDoc_STRVAR(EVP_hexdigest__doc__, +"hexdigest($self, /)\n" +"--\n" +"\n" +"Return the digest value as a string of hexadecimal digits."); + +#define EVP_HEXDIGEST_METHODDEF \ + {"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__}, + +static PyObject * +EVP_hexdigest_impl(EVPobject *self); + +static PyObject * +EVP_hexdigest(EVPobject *self, PyObject *Py_UNUSED(ignored)) +{ + return EVP_hexdigest_impl(self); +} + +PyDoc_STRVAR(EVP_update__doc__, +"update($self, obj, /)\n" +"--\n" +"\n" +"Update this hash object\'s state with the provided string."); + +#define EVP_UPDATE_METHODDEF \ + {"update", (PyCFunction)EVP_update, METH_O, EVP_update__doc__}, + +PyDoc_STRVAR(EVP_tp_init__doc__, +"HASH(name, string=b\'\')\n" +"--\n" +"\n" +"A hash is an object used to calculate a checksum of a string of information.\n" +"\n" +"Methods:\n" +"\n" +"update() -- updates the current digest with an additional string\n" +"digest() -- return the current digest value\n" +"hexdigest() -- return the current digest as a string of hexadecimal digits\n" +"copy() -- return a copy of the current hash object\n" +"\n" +"Attributes:\n" +"\n" +"name -- the hash algorithm being used by this object\n" +"digest_size -- number of bytes in this hashes output"); + +static int +EVP_tp_init_impl(EVPobject *self, PyObject *name_obj, PyObject *data_obj); + +static int +EVP_tp_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + static const char * const _keywords[] = {"name", "string", NULL}; + static _PyArg_Parser _parser = {"O|O:HASH", _keywords, 0}; + PyObject *name_obj; + PyObject *data_obj = NULL; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &name_obj, &data_obj)) { + goto exit; + } + return_value = EVP_tp_init_impl((EVPobject *)self, name_obj, data_obj); + +exit: + return return_value; +} + +PyDoc_STRVAR(EVP_new__doc__, +"new($module, /, name, string=b\'\')\n" +"--\n" +"\n" +"Return a new hash object using the named algorithm.\n" +"\n" +"An optional string argument may be provided and will be\n" +"automatically hashed.\n" +"\n" +"The MD5 and SHA1 algorithms are always supported."); + +#define EVP_NEW_METHODDEF \ + {"new", (PyCFunction)(void(*)(void))EVP_new, METH_FASTCALL|METH_KEYWORDS, EVP_new__doc__}, + +static PyObject * +EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj); + +static PyObject * +EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"name", "string", NULL}; + static _PyArg_Parser _parser = {"O|O:new", _keywords, 0}; + PyObject *name_obj; + PyObject *data_obj = NULL; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &name_obj, &data_obj)) { + goto exit; + } + return_value = EVP_new_impl(module, name_obj, data_obj); + +exit: + return return_value; +} + +#if ((OPENSSL_VERSION_NUMBER >= 0x10000000 && !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA))) + +PyDoc_STRVAR(pbkdf2_hmac__doc__, +"pbkdf2_hmac($module, /, hash_name, password, salt, iterations,\n" +" dklen=None)\n" +"--\n" +"\n" +"Password based key derivation function 2 (PKCS #5 v2.0) with HMAC as pseudorandom function."); + +#define PBKDF2_HMAC_METHODDEF \ + {"pbkdf2_hmac", (PyCFunction)(void(*)(void))pbkdf2_hmac, METH_FASTCALL|METH_KEYWORDS, pbkdf2_hmac__doc__}, + +static PyObject * +pbkdf2_hmac_impl(PyObject *module, const char *hash_name, + Py_buffer *password, Py_buffer *salt, long iterations, + PyObject *dklen_obj); + +static PyObject * +pbkdf2_hmac(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"hash_name", "password", "salt", "iterations", "dklen", NULL}; + static _PyArg_Parser _parser = {"sy*y*l|O:pbkdf2_hmac", _keywords, 0}; + const char *hash_name; + Py_buffer password = {NULL, NULL}; + Py_buffer salt = {NULL, NULL}; + long iterations; + PyObject *dklen_obj = Py_None; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &hash_name, &password, &salt, &iterations, &dklen_obj)) { + goto exit; + } + return_value = pbkdf2_hmac_impl(module, hash_name, &password, &salt, iterations, dklen_obj); + +exit: + /* Cleanup for password */ + if (password.obj) { + PyBuffer_Release(&password); + } + /* Cleanup for salt */ + if (salt.obj) { + PyBuffer_Release(&salt); + } + + return return_value; +} + +#endif /* ((OPENSSL_VERSION_NUMBER >= 0x10000000 && !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA))) */ + #if (OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_SCRYPT) && !defined(LIBRESSL_VERSION_NUMBER)) PyDoc_STRVAR(_hashlib_scrypt__doc__, @@ -96,7 +285,11 @@ exit: return return_value; } +#ifndef PBKDF2_HMAC_METHODDEF + #define PBKDF2_HMAC_METHODDEF +#endif /* !defined(PBKDF2_HMAC_METHODDEF) */ + #ifndef _HASHLIB_SCRYPT_METHODDEF #define _HASHLIB_SCRYPT_METHODDEF #endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */ -/*[clinic end generated code: output=acf668396f59f2b6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cae09468e2cdbefe input=a9049054013a1b77]*/