[Python-checkins] bpo-20182: AC convert remaining functions/methods in _hashopenssl.c (GH-9213)

Tal Einat webhook-mailer at python.org
Thu Dec 27 08:43:48 EST 2018


https://github.com/python/cpython/commit/c6c7237272499b2c528acb5f62601421f329e92a
commit: c6c7237272499b2c528acb5f62601421f329e92a
branch: master
author: Tal Einat <taleinat+github at gmail.com>
committer: GitHub <noreply at github.com>
date: 2018-12-27T15:43:43+02:00
summary:

bpo-20182: AC convert remaining functions/methods in _hashopenssl.c (GH-9213)

files:
M Modules/_hashopenssl.c
M Modules/clinic/_hashopenssl.c.h

diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index d7e613c886c3..6da057acd21f 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -26,12 +26,6 @@
 #include <openssl/objects.h>
 #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,24 +414,7 @@ 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)
@@ -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 3dad45de6712..5f2b23560ef1 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 @@ _hashlib_hmac_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
     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]*/



More information about the Python-checkins mailing list