Files
oasis-linux-mirror/pkg/python/patch/0001-Add-BearSSL-implementation-of-_hashlib.patch
2021-10-05 18:54:21 -07:00

2267 lines
64 KiB
Diff

From 61ad7f5ec78d4c80a99ac71820d9bc8b62c3fbae Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Sat, 15 May 2021 22:48:13 -0700
Subject: [PATCH] Add BearSSL implementation of _hashlib
---
Modules/_hashbearssl.c | 1126 +++++++++++++++++++++++++++++++
Modules/clinic/_hashbearssl.c.h | 1113 ++++++++++++++++++++++++++++++
2 files changed, 2239 insertions(+)
create mode 100644 Modules/_hashbearssl.c
create mode 100644 Modules/clinic/_hashbearssl.c.h
diff --git a/Modules/_hashbearssl.c b/Modules/_hashbearssl.c
new file mode 100644
index 0000000000..2d1a76296d
--- /dev/null
+++ b/Modules/_hashbearssl.c
@@ -0,0 +1,1126 @@
+/* Module that wraps all BearSSL hash algorithms */
+#define PY_SSIZE_T_CLEAN
+#include "Python.h"
+#include "hashlib.h"
+#include "pystrhex.h"
+
+#include <bearssl.h>
+
+static PyModuleDef _hashlibmodule;
+static PyTypeObject Hash_Type;
+static PyTypeObject SHAKE_Type;
+static PyTypeObject HMAC_Type;
+
+typedef struct {
+ PyObject_HEAD
+ br_hash_compat_context ctx;
+ PyThread_type_lock lock;
+} Hash;
+
+typedef struct {
+ PyObject_HEAD
+ br_hmac_context ctx;
+ br_hmac_key_context key;
+ PyThread_type_lock lock;
+} HMAC;
+
+typedef struct {
+ PyObject_HEAD
+ br_shake_context ctx;
+ int bits;
+ PyThread_type_lock lock;
+} SHAKE;
+
+#include "clinic/_hashbearssl.c.h"
+/*[clinic input]
+module _hashlib
+class _hashlib.Hash "Hash *" "Hash_Type"
+class _hashlib.HMAC "HMAC *" "HMAC_Type"
+class _hashlib.SHAKE "SHAKE *" "SHAKE_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7a269412ec77c79a]*/
+
+static const br_hash_class *
+py_hash_by_name(const char *name)
+{
+ if (strcmp(name, "md5") == 0)
+ return &br_md5_vtable;
+ else if (strcmp(name, "sha1") == 0)
+ return &br_sha1_vtable;
+ else if (strcmp(name, "sha224") == 0)
+ return &br_sha224_vtable;
+ else if (strcmp(name, "sha256") == 0)
+ return &br_sha256_vtable;
+ else if (strcmp(name, "sha384") == 0)
+ return &br_sha384_vtable;
+ else if (strcmp(name, "sha512") == 0)
+ return &br_sha512_vtable;
+ return NULL;
+}
+
+PyDoc_STRVAR(Hash_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 void
+Hash_dealloc(Hash *self)
+{
+ if (self->lock)
+ PyThread_free_lock(self->lock);
+ PyObject_Free(self);
+}
+
+/*[clinic input]
+_hashlib.Hash.update as Hash_update
+
+ data: Py_buffer
+ /
+
+Update this hash object's state with the provided string.
+[clinic start generated code]*/
+
+static PyObject *
+Hash_update_impl(Hash *self, Py_buffer *data)
+/*[clinic end generated code: output=eed11f7503e289a3 input=0547d16ba3981abf]*/
+{
+ if (!self->lock && data->len >= HASHLIB_GIL_MINSIZE)
+ self->lock = PyThread_allocate_lock();
+ if (self->lock) {
+ Py_BEGIN_ALLOW_THREADS
+ PyThread_acquire_lock(self->lock, 1);
+ self->ctx.vtable->update(&self->ctx.vtable, data->buf, data->len);
+ PyThread_release_lock(self->lock);
+ Py_END_ALLOW_THREADS
+ } else {
+ self->ctx.vtable->update(&self->ctx.vtable, data->buf, data->len);
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_hashlib.Hash.digest as Hash_digest
+
+Return the digest value as a bytes object.
+[clinic start generated code]*/
+
+static PyObject *
+Hash_digest_impl(Hash *self)
+/*[clinic end generated code: output=b3eafdc9f37cf341 input=6d4afcd832edc55a]*/
+{
+ char digest[64];
+ Py_ssize_t digest_size;
+
+ ENTER_HASHLIB(self)
+ self->ctx.vtable->out(&self->ctx.vtable, digest);
+ LEAVE_HASHLIB(self)
+ digest_size = (self->ctx.vtable->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+
+ return PyBytes_FromStringAndSize(digest, digest_size);
+}
+
+/*[clinic input]
+_hashlib.Hash.hexdigest as Hash_hexdigest
+
+Return the digest value as a string of hexadecimal digits.
+[clinic start generated code]*/
+
+static PyObject *
+Hash_hexdigest_impl(Hash *self)
+/*[clinic end generated code: output=eff810494302910a input=6b224236fad6ff65]*/
+{
+ char digest[64];
+ Py_ssize_t digest_size;
+
+ ENTER_HASHLIB(self)
+ self->ctx.vtable->out(&self->ctx.vtable, digest);
+ LEAVE_HASHLIB(self)
+ digest_size = (self->ctx.vtable->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
+
+ return _Py_strhex(digest, digest_size);
+}
+
+/*[clinic input]
+_hashlib.Hash.copy as Hash_copy
+
+Return a copy of the hash object.
+[clinic start generated code]*/
+
+static PyObject *
+Hash_copy_impl(Hash *self)
+/*[clinic end generated code: output=e97863340f55061b input=b830c9d949d08256]*/
+{
+ Hash *newobj;
+
+ newobj = PyObject_New(Hash, &Hash_Type);
+ if (!newobj)
+ return NULL;
+ newobj->lock = NULL;
+ ENTER_HASHLIB(self)
+ newobj->ctx = self->ctx;
+ LEAVE_HASHLIB(self)
+
+ return (PyObject *)newobj;
+}
+
+static PyMethodDef Hash_methods[] = {
+ HASH_UPDATE_METHODDEF
+ HASH_DIGEST_METHODDEF
+ HASH_HEXDIGEST_METHODDEF
+ HASH_COPY_METHODDEF
+ {0}
+};
+
+static PyObject *
+Hash_get_digest_size(Hash *self, void *closure)
+{
+ long digest_size;
+
+ digest_size = self->ctx.vtable->desc >> BR_HASHDESC_OUT_OFF & BR_HASHDESC_OUT_MASK;
+ return PyLong_FromLong(digest_size);
+}
+
+static PyObject *
+Hash_get_block_size(Hash *self, void *closure)
+{
+ long block_size;
+
+ block_size = 1 << (self->ctx.vtable->desc >> BR_HASHDESC_LBLEN_OFF & BR_HASHDESC_LBLEN_MASK);
+ return PyLong_FromLong(block_size);
+}
+
+static PyObject *
+Hash_get_name(Hash *self, void *closure)
+{
+ const char *name = NULL;
+
+ switch (self->ctx.vtable->desc >> BR_HASHDESC_ID_OFF & BR_HASHDESC_ID_MASK) {
+ case br_md5_ID: name = "md5"; break;
+ case br_sha1_ID: name = "sha1"; break;
+ case br_sha224_ID: name = "sha224"; break;
+ case br_sha256_ID: name = "sha256"; break;
+ case br_sha384_ID: name = "sha384"; break;
+ case br_sha512_ID: name = "sha512"; break;
+ }
+
+ return PyUnicode_FromString(name);
+}
+
+static PyGetSetDef Hash_getset[] = {
+ {"digest_size", (getter)Hash_get_digest_size, NULL, NULL, NULL},
+ {"block_size", (getter)Hash_get_block_size, NULL, NULL, NULL},
+ {"name", (getter)Hash_get_name, NULL, NULL, NULL},
+ {0}
+};
+
+static PyTypeObject Hash_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "_hashlib.Hash",
+ .tp_dealloc = (destructor)Hash_dealloc,
+ .tp_doc = Hash_doc,
+ .tp_basicsize = sizeof(Hash),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
+ .tp_methods = Hash_methods,
+ .tp_getset = Hash_getset,
+};
+
+PyDoc_STRVAR(SHAKE_doc,
+"SHAKE(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(length) -- return the current digest value\n"
+"hexdigest(length) -- 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 void
+SHAKE_dealloc(SHAKE *self)
+{
+ if (self->lock)
+ PyThread_free_lock(self->lock);
+ PyObject_Free(self);
+}
+
+/*[clinic input]
+_hashlib.SHAKE.update as SHAKE_update
+
+ data: Py_buffer
+ /
+
+Update this hash object's state with the provided string.
+[clinic start generated code]*/
+
+static PyObject *
+SHAKE_update_impl(SHAKE *self, Py_buffer *data)
+/*[clinic end generated code: output=b7f5cd67459e2fb3 input=87a80642380b615f]*/
+{
+ if (!self->lock && data->len >= HASHLIB_GIL_MINSIZE)
+ self->lock = PyThread_allocate_lock();
+ if (self->lock) {
+ Py_BEGIN_ALLOW_THREADS
+ PyThread_acquire_lock(self->lock, 1);
+ br_shake_inject(&self->ctx, data->buf, data->len);
+ PyThread_release_lock(self->lock);
+ Py_END_ALLOW_THREADS
+ } else {
+ br_shake_inject(&self->ctx, data->buf, data->len);
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_hashlib.SHAKE.digest as SHAKE_digest
+
+ length: Py_ssize_t
+
+Return the digest value as a bytes object.
+[clinic start generated code]*/
+
+static PyObject *
+SHAKE_digest_impl(SHAKE *self, Py_ssize_t length)
+/*[clinic end generated code: output=4235ee593cba0b23 input=9e31587954f5e87a]*/
+{
+ br_shake_context ctx;
+ PyObject *bytes;
+
+ bytes = PyBytes_FromStringAndSize(NULL, length);
+ if (!bytes)
+ return NULL;
+
+ ENTER_HASHLIB(self)
+ ctx = self->ctx;
+ LEAVE_HASHLIB(self)
+ br_shake_flip(&ctx);
+ br_shake_produce(&ctx, PyBytes_AS_STRING(bytes), length);
+
+ return bytes;
+}
+
+/*[clinic input]
+_hashlib.SHAKE.hexdigest as SHAKE_hexdigest
+
+ length: Py_ssize_t
+
+Return the digest value as a string of hexadecimal digits.
+[clinic start generated code]*/
+
+static PyObject *
+SHAKE_hexdigest_impl(SHAKE *self, Py_ssize_t length)
+/*[clinic end generated code: output=fd9a7905a89a1509 input=2c43a9638ca1db5e]*/
+{
+ br_shake_context ctx;
+ char *bytes;
+ PyObject *str;
+
+ bytes = PyMem_Malloc(length);
+ if (!bytes) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ENTER_HASHLIB(self)
+ ctx = self->ctx;
+ LEAVE_HASHLIB(self)
+ br_shake_flip(&ctx);
+ br_shake_produce(&ctx, bytes, length);
+
+ str = _Py_strhex(bytes, length);
+ PyMem_Free(bytes);
+ return str;
+}
+
+/*[clinic input]
+_hashlib.SHAKE.copy as SHAKE_copy
+
+Return a copy of the SHAKE object.
+[clinic start generated code]*/
+
+static PyObject *
+SHAKE_copy_impl(SHAKE *self)
+/*[clinic end generated code: output=19cff23538f29dc6 input=34c8368c5c9e910c]*/
+{
+ SHAKE *newobj;
+
+ newobj = PyObject_New(SHAKE, &SHAKE_Type);
+ if (!newobj)
+ return NULL;
+ newobj->lock = NULL;
+ ENTER_HASHLIB(self)
+ newobj->ctx = self->ctx;
+ newobj->bits = self->bits;
+ LEAVE_HASHLIB(self)
+
+ return (PyObject *)newobj;
+}
+
+static PyMethodDef SHAKE_methods[] = {
+ SHAKE_UPDATE_METHODDEF
+ SHAKE_DIGEST_METHODDEF
+ SHAKE_HEXDIGEST_METHODDEF
+ SHAKE_COPY_METHODDEF
+ {0}
+};
+
+static PyObject *
+SHAKE_get_digest_size(SHAKE *self, void *closure)
+{
+ return PyLong_FromLong(0);
+}
+
+static PyObject *
+SHAKE_get_block_size(SHAKE *self, void *closure)
+{
+ return PyLong_FromLong(self->ctx.rate);
+}
+
+static PyObject *
+SHAKE_get_name(SHAKE *self, void *closure)
+{
+ const char *name = NULL;
+
+ switch (self->bits) {
+ case 128: name = "shake_128"; break;
+ case 256: name = "shake_256"; break;
+ }
+
+ return PyUnicode_FromString(name);
+}
+
+static PyGetSetDef SHAKE_getset[] = {
+ {"digest_size", (getter)SHAKE_get_digest_size, NULL, NULL, NULL},
+ {"block_size", (getter)SHAKE_get_block_size, NULL, NULL, NULL},
+ {"name", (getter)SHAKE_get_name, NULL, NULL, NULL},
+ {0}
+};
+
+static PyTypeObject SHAKE_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "_hashlib.SHAKE",
+ .tp_dealloc = (destructor)SHAKE_dealloc,
+ .tp_doc = SHAKE_doc,
+ .tp_basicsize = sizeof(SHAKE),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
+ .tp_methods = SHAKE_methods,
+ .tp_getset = SHAKE_getset,
+};
+
+PyDoc_STRVAR(HMAC_doc,
+"The object used to calculate HMAC of a message.\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 name, including the hash algorithm used by this object\n\
+digest_size -- number of bytes in digest() output\n");
+
+static void
+HMAC_dealloc(HMAC *self)
+{
+ if (self->lock)
+ PyThread_free_lock(self->lock);
+ PyObject_Free(self);
+}
+/*[clinic input]
+_hashlib.HMAC.copy as HMAC_copy
+
+Return a copy of the HMAC object.
+[clinic start generated code]*/
+
+static PyObject *
+HMAC_copy_impl(HMAC *self)
+/*[clinic end generated code: output=6a3595133ec708a5 input=c471e903458ee9a7]*/
+{
+ HMAC *newobj;
+
+ newobj = PyObject_New(HMAC, &HMAC_Type);
+ if (!newobj)
+ return NULL;
+ newobj->lock = NULL;
+ ENTER_HASHLIB(self)
+ newobj->ctx = self->ctx;
+ newobj->key = self->key;
+ LEAVE_HASHLIB(self)
+
+ return (PyObject *)newobj;
+}
+
+/*[clinic input]
+_hashlib.HMAC.update as HMAC_update
+
+ data: Py_buffer
+ /
+
+Update the HMAC object with data.
+[clinic start generated code]*/
+
+static PyObject *
+HMAC_update_impl(HMAC *self, Py_buffer *data)
+/*[clinic end generated code: output=d3520ecffa6cc3ab input=827e77e990887267]*/
+{
+ if (!self->lock && data->len >= HASHLIB_GIL_MINSIZE)
+ self->lock = PyThread_allocate_lock();
+ if (self->lock) {
+ Py_BEGIN_ALLOW_THREADS
+ PyThread_acquire_lock(self->lock, 1);
+ br_hmac_update(&self->ctx, data->buf, data->len);
+ PyThread_release_lock(self->lock);
+ Py_END_ALLOW_THREADS
+ } else {
+ br_hmac_update(&self->ctx, data->buf, data->len);
+ }
+ Py_RETURN_NONE;
+}
+
+/*[clinic input]
+_hashlib.HMAC.digest as HMAC_digest
+
+Return the digest of the bytes passed to the update() method so far.
+[clinic start generated code]*/
+
+static PyObject *
+HMAC_digest_impl(HMAC *self)
+/*[clinic end generated code: output=9853eeca2bdd96df input=d39cb2285b557318]*/
+{
+ char digest[64];
+ Py_ssize_t digest_size;
+
+ ENTER_HASHLIB(self)
+ digest_size = br_hmac_out(&self->ctx, digest);
+ LEAVE_HASHLIB(self)
+
+ return PyBytes_FromStringAndSize(digest, digest_size);
+}
+
+/*[clinic input]
+_hashlib.HMAC.hexdigest as HMAC_hexdigest
+
+Return hexadecimal digest of the bytes passed to the update() method so far.
+
+This may be used to exchange the value safely in email or other non-binary
+environments.
+[clinic start generated code]*/
+
+static PyObject *
+HMAC_hexdigest_impl(HMAC *self)
+/*[clinic end generated code: output=9bb0c7abb6940bab input=2471f22b8dba7433]*/
+{
+ char digest[64];
+ Py_ssize_t digest_size;
+
+ ENTER_HASHLIB(self)
+ digest_size = br_hmac_out(&self->ctx, digest);
+ LEAVE_HASHLIB(self)
+
+ return _Py_strhex(digest, digest_size);
+}
+
+static PyMethodDef HMAC_methods[] = {
+ HMAC_UPDATE_METHODDEF
+ HMAC_DIGEST_METHODDEF
+ HMAC_HEXDIGEST_METHODDEF
+ HMAC_COPY_METHODDEF
+ {0},
+};
+
+static PyObject *
+HMAC_get_digest_size(HMAC *self, void *closure)
+{
+ const br_hash_class *hc;
+ long digest_size;
+
+ hc = br_hmac_get_digest(&self->ctx);
+ digest_size = hc->desc >> BR_HASHDESC_OUT_OFF & BR_HASHDESC_OUT_MASK;
+ return PyLong_FromLong(digest_size);
+}
+
+static PyObject *
+HMAC_get_block_size(HMAC *self, void *closure)
+{
+ const br_hash_class *hc;
+ long block_size;
+
+ hc = br_hmac_get_digest(&self->ctx);
+ block_size = 1 << (hc->desc >> BR_HASHDESC_LBLEN_OFF & BR_HASHDESC_LBLEN_MASK);
+ return PyLong_FromLong(block_size);
+}
+
+static PyObject *
+HMAC_get_name(HMAC *self, void *closure)
+{
+ const br_hash_class *hc;
+ const char *name = NULL;
+
+ hc = br_hmac_get_digest(&self->ctx);
+ switch (hc->desc >> BR_HASHDESC_ID_OFF & BR_HASHDESC_ID_MASK) {
+ case br_md5_ID: name = "hmac-md5"; break;
+ case br_sha1_ID: name = "hmac-sha1"; break;
+ case br_sha224_ID: name = "hmac-sha224"; break;
+ case br_sha256_ID: name = "hmac-sha256"; break;
+ case br_sha384_ID: name = "hmac-sha384"; break;
+ case br_sha512_ID: name = "hmac-sha512"; break;
+ }
+
+ return PyUnicode_FromString(name);
+}
+
+static PyGetSetDef HMAC_getset[] = {
+ {"digest_size", (getter)HMAC_get_digest_size, NULL, NULL, NULL},
+ {"block_size", (getter)HMAC_get_block_size, NULL, NULL, NULL},
+ {"name", (getter)HMAC_get_name, NULL, NULL, NULL},
+ {0}
+};
+
+static PyTypeObject HMAC_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "_hashlib.HMAC",
+ .tp_dealloc = (destructor)HMAC_dealloc,
+ .tp_doc = HMAC_doc,
+ .tp_basicsize = sizeof(HMAC),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
+ .tp_methods = HMAC_methods,
+ .tp_getset = HMAC_getset,
+};
+
+static PyObject *
+Hash_new_vtable(PyObject *module, const br_hash_class *hc,
+ Py_buffer *string, int usedforsecurity)
+{
+ Hash *self;
+
+ self = PyObject_New(Hash, &Hash_Type);
+ if (!self)
+ return NULL;
+ self->lock = NULL;
+ hc->init(&self->ctx.vtable);
+
+ if (string->len >= HASHLIB_GIL_MINSIZE) {
+ Py_BEGIN_ALLOW_THREADS
+ hc->update(&self->ctx.vtable, string->buf, string->len);
+ Py_END_ALLOW_THREADS
+ } else {
+ hc->update(&self->ctx.vtable, string->buf, string->len);
+ }
+
+ return (PyObject *)self;
+}
+
+static PyObject *
+SHAKE_new(PyObject *module, int bits, Py_buffer *string, int usedforsecurity)
+{
+ SHAKE *self;
+
+ self = PyObject_New(SHAKE, &SHAKE_Type);
+ if (!self)
+ return NULL;
+ self->lock = NULL;
+ self->bits = bits;
+ br_shake_init(&self->ctx, bits);
+
+ if (string->len >= HASHLIB_GIL_MINSIZE) {
+ Py_BEGIN_ALLOW_THREADS
+ br_shake_inject(&self->ctx, string->buf, string->len);
+ Py_END_ALLOW_THREADS
+ } else {
+ br_shake_inject(&self->ctx, string->buf, string->len);
+ }
+
+ return (PyObject *)self;
+}
+
+/*[clinic input]
+_hashlib.new
+
+ name: str
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+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 *
+_hashlib_new_impl(PyObject *module, const char *name, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=5459beb11946eb8d input=c7e3a9928c6af923]*/
+{
+ const br_hash_class *hc = NULL;
+ int shake = 0;
+
+ hc = py_hash_by_name(name);
+ if (hc)
+ ;
+ else if (strcmp(name, "shake_128") == 0)
+ shake = 128;
+ else if (strcmp(name, "shake_256") == 0)
+ shake = 256;
+ else {
+ PyErr_SetString(PyExc_ValueError, "unsupported hash type");
+ return NULL;
+ }
+
+ if (hc)
+ return Hash_new_vtable(module, hc, string, usedforsecurity);
+ if (shake)
+ return SHAKE_new(module, shake, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_md5
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a md5 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_md5_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=bf0df21c3ecd9d85 input=75e59cc38a292e51]*/
+{
+ return Hash_new_vtable(module, &br_md5_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_sha1
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a sha1 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha1_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=9c468cf3cfdd2e57 input=0f8ad0fa5d988be8]*/
+{
+ return Hash_new_vtable(module, &br_sha1_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_sha224
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a sha224 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha224_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=9b3fea17aacc8dfe input=21aacab0e6949431]*/
+{
+ return Hash_new_vtable(module, &br_sha224_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_sha256
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a sha256 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha256_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=2c0585ccc6dfa22a input=81dd291675e0f6c9]*/
+{
+ return Hash_new_vtable(module, &br_sha256_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_sha384
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a sha384 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha384_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=196d8d7558cfd155 input=eed0b0128dd67969]*/
+{
+ return Hash_new_vtable(module, &br_sha384_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_sha512
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a sha512 hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_sha512_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=7349b37b20ff6f75 input=da1228b585897043]*/
+{
+ return Hash_new_vtable(module, &br_sha512_vtable, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_shake_128
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a shake-128 variable hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_shake_128_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=e51cc0e4bded887e input=fb6dce24fc91d53d]*/
+{
+ return SHAKE_new(module, 128, string, usedforsecurity);
+}
+
+/*[clinic input]
+_hashlib.openssl_shake_256
+
+ string: Py_buffer = None
+ *
+ usedforsecurity: bool = True
+
+Returns a shake-256 variable hash object; optionally initialized with a string.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_openssl_shake_256_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity)
+/*[clinic end generated code: output=983a76ff0796751b input=9eb2a133d11e34dc]*/
+{
+ return SHAKE_new(module, 256, string, usedforsecurity);
+}
+
+static int
+_tscmp(const unsigned char *a, const unsigned char *b,
+ Py_ssize_t len_a, Py_ssize_t len_b)
+{
+ /* loop count depends on length of b. Might leak very little timing
+ * information if sizes are different.
+ */
+ Py_ssize_t length = len_b;
+ unsigned result = 0;
+ size_t i;
+
+ if (len_a != length) {
+ a = b;
+ result = 1;
+ }
+
+ for (i = 0; i < length; i++)
+ result |= (unsigned)a[i] ^ (unsigned)b[i];
+
+ return ~(result | -result) >> CHAR_BIT * sizeof(result) - 1;
+}
+
+/*[clinic input]
+_hashlib.compare_digest
+
+ a: object
+ b: object
+ /
+
+Return 'a == b'.
+
+This function uses an approach designed to prevent
+timing analysis, making it appropriate for cryptography.
+
+a and b must both be of the same type: either str (ASCII only),
+or any bytes-like object.
+
+Note: If a and b are of different lengths, or if an error occurs,
+a timing attack could theoretically reveal information about the
+types and lengths of a and b--but not their values.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_compare_digest_impl(PyObject *module, PyObject *a, PyObject *b)
+/*[clinic end generated code: output=6f1c13927480aed9 input=f9cc6da970b1b1d5]*/
+{
+ int rc;
+
+ /* ASCII unicode string */
+ if(PyUnicode_Check(a) && PyUnicode_Check(b)) {
+ if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
+ return NULL;
+ }
+ if (!PyUnicode_IS_ASCII(a) || !PyUnicode_IS_ASCII(b)) {
+ PyErr_SetString(PyExc_TypeError,
+ "comparing strings with non-ASCII characters is "
+ "not supported");
+ return NULL;
+ }
+
+ rc = _tscmp(PyUnicode_DATA(a),
+ PyUnicode_DATA(b),
+ PyUnicode_GET_LENGTH(a),
+ PyUnicode_GET_LENGTH(b));
+ }
+ /* fallback to buffer interface for bytes, bytesarray and other */
+ else {
+ Py_buffer view_a;
+ Py_buffer view_b;
+
+ if (PyObject_CheckBuffer(a) == 0 && PyObject_CheckBuffer(b) == 0) {
+ PyErr_Format(PyExc_TypeError,
+ "unsupported operand types(s) or combination of types: "
+ "'%.100s' and '%.100s'",
+ Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
+ return NULL;
+ }
+
+ if (PyObject_GetBuffer(a, &view_a, PyBUF_SIMPLE) == -1) {
+ return NULL;
+ }
+ if (view_a.ndim > 1) {
+ PyErr_SetString(PyExc_BufferError,
+ "Buffer must be single dimension");
+ PyBuffer_Release(&view_a);
+ return NULL;
+ }
+
+ if (PyObject_GetBuffer(b, &view_b, PyBUF_SIMPLE) == -1) {
+ PyBuffer_Release(&view_a);
+ return NULL;
+ }
+ if (view_b.ndim > 1) {
+ PyErr_SetString(PyExc_BufferError,
+ "Buffer must be single dimension");
+ PyBuffer_Release(&view_a);
+ PyBuffer_Release(&view_b);
+ return NULL;
+ }
+
+ rc = _tscmp((const unsigned char*)view_a.buf,
+ (const unsigned char*)view_b.buf,
+ view_a.len,
+ view_b.len);
+
+ PyBuffer_Release(&view_a);
+ PyBuffer_Release(&view_b);
+ }
+
+ return PyBool_FromLong(rc);
+}
+
+static struct PyMethodDef hashlib_methods[] = {
+ _HASHLIB_NEW_METHODDEF
+ _HASHLIB_HMAC_SINGLESHOT_METHODDEF
+ _HASHLIB_HMAC_NEW_METHODDEF
+ _HASHLIB_OPENSSL_MD5_METHODDEF
+ _HASHLIB_OPENSSL_SHA1_METHODDEF
+ _HASHLIB_OPENSSL_SHA224_METHODDEF
+ _HASHLIB_OPENSSL_SHA256_METHODDEF
+ _HASHLIB_OPENSSL_SHA384_METHODDEF
+ _HASHLIB_OPENSSL_SHA512_METHODDEF
+ _HASHLIB_OPENSSL_SHAKE_128_METHODDEF
+ _HASHLIB_OPENSSL_SHAKE_256_METHODDEF
+ _HASHLIB_COMPARE_DIGEST_METHODDEF
+ {0}
+};
+
+/* Fast HMAC for hmac.digest() */
+
+/*[clinic input]
+_hashlib.hmac_digest as _hashlib_hmac_singleshot
+
+ key: Py_buffer
+ msg: Py_buffer
+ digest: str
+
+Single-shot HMAC.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key,
+ Py_buffer *msg, const char *digest)
+/*[clinic end generated code: output=15658ede5ab98185 input=019dffc571909a46]*/
+{
+ char buf[64];
+ Py_ssize_t buf_len;
+ br_hmac_context ctx;
+ br_hmac_key_context keyctx;
+ const br_hash_class *hc;
+
+ hc = py_hash_by_name(digest);
+ if (!hc) {
+ PyErr_SetString(PyExc_ValueError, "unsupported hash type");
+ return NULL;
+ }
+ if (msg->len >= HASHLIB_GIL_MINSIZE) {
+ Py_BEGIN_ALLOW_THREADS
+ br_hmac_key_init(&keyctx, hc, key->buf, key->len);
+ br_hmac_init(&ctx, &keyctx, 0);
+ br_hmac_update(&ctx, msg->buf, msg->len);
+ br_hmac_out(&ctx, buf);
+ Py_END_ALLOW_THREADS
+ } else {
+ br_hmac_key_init(&keyctx, hc, key->buf, key->len);
+ br_hmac_init(&ctx, &keyctx, 0);
+ br_hmac_update(&ctx, msg->buf, msg->len);
+ br_hmac_out(&ctx, buf);
+ }
+ buf_len = br_hmac_size(&ctx);
+
+ return PyBytes_FromStringAndSize(buf, buf_len);
+}
+
+/*[clinic input]
+_hashlib.hmac_new
+
+ key: Py_buffer
+ msg: Py_buffer = None
+ digestmod: str(c_default="NULL") = None
+
+Return a new hmac object.
+[clinic start generated code]*/
+
+static PyObject *
+_hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, Py_buffer *msg,
+ const char *digestmod)
+/*[clinic end generated code: output=5733a8600554bba2 input=b0125f4222a0d06d]*/
+{
+ HMAC *self;
+ const br_hash_class *hc;
+
+ printf("hmac new\n");
+
+ if (!digestmod || !digestmod[0]) {
+ PyErr_SetString(
+ PyExc_TypeError, "missing required parameter 'digestmod'");
+ return NULL;
+ }
+ hc = py_hash_by_name(digestmod);
+ if (!hc) {
+ PyErr_SetString(PyExc_ValueError, "unknown hash function");
+ return NULL;
+ }
+ self = PyObject_New(HMAC, &HMAC_Type);
+ if (!self)
+ return NULL;
+ self->lock = NULL;
+ br_hmac_key_init(&self->key, hc, key->buf, key->len);
+ br_hmac_init(&self->ctx, &self->key, 0);
+
+ if (msg->len >= HASHLIB_GIL_MINSIZE) {
+ Py_BEGIN_ALLOW_THREADS
+ br_hmac_update(&self->ctx, msg->buf, msg->len);
+ Py_END_ALLOW_THREADS
+ } else {
+ br_hmac_update(&self->ctx, msg->buf, msg->len);
+ }
+
+ return (PyObject *)self;
+}
+
+static struct PyModuleDef _hashlibmodule = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_hashlib",
+ .m_doc = "BearSSL interface for hashlib module",
+ .m_methods = hashlib_methods,
+};
+
+PyMODINIT_FUNC
+PyInit__hashlib(void)
+{
+ PyObject *m = NULL, *set = NULL, *name;
+ static const char *const names[] = {
+ "md5",
+ "sha1",
+ "sha224",
+ "sha256",
+ "sha384",
+ "sha512",
+ "shake_128",
+ "shake_256",
+ };
+ int r;
+
+ m = PyState_FindModule(&_hashlibmodule);
+ if (m) {
+ Py_INCREF(m);
+ return m;
+ }
+ m = PyModule_Create(&_hashlibmodule);
+ if (!m)
+ goto err;
+ if (PyModule_AddType(m, &Hash_Type) < 0)
+ goto err;
+ if (PyModule_AddType(m, &SHAKE_Type) < 0)
+ goto err;
+ if (PyModule_AddType(m, &HMAC_Type) < 0)
+ goto err;
+ set = PyFrozenSet_New(NULL);
+ if (!set)
+ goto err;
+ for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
+ name = PyUnicode_FromString(names[i]);
+ if (!name)
+ goto err;
+ r = PySet_Add(set, name);
+ Py_DECREF(name);
+ if (r != 0)
+ goto err;
+ }
+ if (PyModule_AddObject(m, "openssl_md_meth_names", set) < 0)
+ goto err;
+
+ return m;
+
+ err:
+ if (set)
+ Py_DECREF(set);
+ if (m)
+ Py_DECREF(m);
+ return NULL;
+}
diff --git a/Modules/clinic/_hashbearssl.c.h b/Modules/clinic/_hashbearssl.c.h
new file mode 100644
index 0000000000..49bf8f9287
--- /dev/null
+++ b/Modules/clinic/_hashbearssl.c.h
@@ -0,0 +1,1113 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+PyDoc_STRVAR(Hash_update__doc__,
+"update($self, data, /)\n"
+"--\n"
+"\n"
+"Update this hash object\'s state with the provided string.");
+
+#define HASH_UPDATE_METHODDEF \
+ {"update", (PyCFunction)Hash_update, METH_O, Hash_update__doc__},
+
+static PyObject *
+Hash_update_impl(Hash *self, Py_buffer *data);
+
+static PyObject *
+Hash_update(Hash *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer data = {NULL, NULL};
+
+ if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&data, 'C')) {
+ _PyArg_BadArgument("update", "argument", "contiguous buffer", arg);
+ goto exit;
+ }
+ return_value = Hash_update_impl(self, &data);
+
+exit:
+ /* Cleanup for data */
+ if (data.obj) {
+ PyBuffer_Release(&data);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(Hash_digest__doc__,
+"digest($self, /)\n"
+"--\n"
+"\n"
+"Return the digest value as a bytes object.");
+
+#define HASH_DIGEST_METHODDEF \
+ {"digest", (PyCFunction)Hash_digest, METH_NOARGS, Hash_digest__doc__},
+
+static PyObject *
+Hash_digest_impl(Hash *self);
+
+static PyObject *
+Hash_digest(Hash *self, PyObject *Py_UNUSED(ignored))
+{
+ return Hash_digest_impl(self);
+}
+
+PyDoc_STRVAR(Hash_hexdigest__doc__,
+"hexdigest($self, /)\n"
+"--\n"
+"\n"
+"Return the digest value as a string of hexadecimal digits.");
+
+#define HASH_HEXDIGEST_METHODDEF \
+ {"hexdigest", (PyCFunction)Hash_hexdigest, METH_NOARGS, Hash_hexdigest__doc__},
+
+static PyObject *
+Hash_hexdigest_impl(Hash *self);
+
+static PyObject *
+Hash_hexdigest(Hash *self, PyObject *Py_UNUSED(ignored))
+{
+ return Hash_hexdigest_impl(self);
+}
+
+PyDoc_STRVAR(Hash_copy__doc__,
+"copy($self, /)\n"
+"--\n"
+"\n"
+"Return a copy of the hash object.");
+
+#define HASH_COPY_METHODDEF \
+ {"copy", (PyCFunction)Hash_copy, METH_NOARGS, Hash_copy__doc__},
+
+static PyObject *
+Hash_copy_impl(Hash *self);
+
+static PyObject *
+Hash_copy(Hash *self, PyObject *Py_UNUSED(ignored))
+{
+ return Hash_copy_impl(self);
+}
+
+PyDoc_STRVAR(SHAKE_update__doc__,
+"update($self, data, /)\n"
+"--\n"
+"\n"
+"Update this hash object\'s state with the provided string.");
+
+#define SHAKE_UPDATE_METHODDEF \
+ {"update", (PyCFunction)SHAKE_update, METH_O, SHAKE_update__doc__},
+
+static PyObject *
+SHAKE_update_impl(SHAKE *self, Py_buffer *data);
+
+static PyObject *
+SHAKE_update(SHAKE *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer data = {NULL, NULL};
+
+ if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&data, 'C')) {
+ _PyArg_BadArgument("update", "argument", "contiguous buffer", arg);
+ goto exit;
+ }
+ return_value = SHAKE_update_impl(self, &data);
+
+exit:
+ /* Cleanup for data */
+ if (data.obj) {
+ PyBuffer_Release(&data);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(SHAKE_digest__doc__,
+"digest($self, /, length)\n"
+"--\n"
+"\n"
+"Return the digest value as a bytes object.");
+
+#define SHAKE_DIGEST_METHODDEF \
+ {"digest", (PyCFunction)(void(*)(void))SHAKE_digest, METH_FASTCALL|METH_KEYWORDS, SHAKE_digest__doc__},
+
+static PyObject *
+SHAKE_digest_impl(SHAKE *self, Py_ssize_t length);
+
+static PyObject *
+SHAKE_digest(SHAKE *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"length", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "digest", 0};
+ PyObject *argsbuf[1];
+ Py_ssize_t length;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyFloat_Check(args[0])) {
+ PyErr_SetString(PyExc_TypeError,
+ "integer argument expected, got float" );
+ goto exit;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = PyNumber_Index(args[0]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ length = ival;
+ }
+ return_value = SHAKE_digest_impl(self, length);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(SHAKE_hexdigest__doc__,
+"hexdigest($self, /, length)\n"
+"--\n"
+"\n"
+"Return the digest value as a string of hexadecimal digits.");
+
+#define SHAKE_HEXDIGEST_METHODDEF \
+ {"hexdigest", (PyCFunction)(void(*)(void))SHAKE_hexdigest, METH_FASTCALL|METH_KEYWORDS, SHAKE_hexdigest__doc__},
+
+static PyObject *
+SHAKE_hexdigest_impl(SHAKE *self, Py_ssize_t length);
+
+static PyObject *
+SHAKE_hexdigest(SHAKE *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"length", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hexdigest", 0};
+ PyObject *argsbuf[1];
+ Py_ssize_t length;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyFloat_Check(args[0])) {
+ PyErr_SetString(PyExc_TypeError,
+ "integer argument expected, got float" );
+ goto exit;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = PyNumber_Index(args[0]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ length = ival;
+ }
+ return_value = SHAKE_hexdigest_impl(self, length);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(SHAKE_copy__doc__,
+"copy($self, /)\n"
+"--\n"
+"\n"
+"Return a copy of the SHAKE object.");
+
+#define SHAKE_COPY_METHODDEF \
+ {"copy", (PyCFunction)SHAKE_copy, METH_NOARGS, SHAKE_copy__doc__},
+
+static PyObject *
+SHAKE_copy_impl(SHAKE *self);
+
+static PyObject *
+SHAKE_copy(SHAKE *self, PyObject *Py_UNUSED(ignored))
+{
+ return SHAKE_copy_impl(self);
+}
+
+PyDoc_STRVAR(HMAC_copy__doc__,
+"copy($self, /)\n"
+"--\n"
+"\n"
+"Return a copy of the HMAC object.");
+
+#define HMAC_COPY_METHODDEF \
+ {"copy", (PyCFunction)HMAC_copy, METH_NOARGS, HMAC_copy__doc__},
+
+static PyObject *
+HMAC_copy_impl(HMAC *self);
+
+static PyObject *
+HMAC_copy(HMAC *self, PyObject *Py_UNUSED(ignored))
+{
+ return HMAC_copy_impl(self);
+}
+
+PyDoc_STRVAR(HMAC_update__doc__,
+"update($self, data, /)\n"
+"--\n"
+"\n"
+"Update the HMAC object with data.");
+
+#define HMAC_UPDATE_METHODDEF \
+ {"update", (PyCFunction)HMAC_update, METH_O, HMAC_update__doc__},
+
+static PyObject *
+HMAC_update_impl(HMAC *self, Py_buffer *data);
+
+static PyObject *
+HMAC_update(HMAC *self, PyObject *arg)
+{
+ PyObject *return_value = NULL;
+ Py_buffer data = {NULL, NULL};
+
+ if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&data, 'C')) {
+ _PyArg_BadArgument("update", "argument", "contiguous buffer", arg);
+ goto exit;
+ }
+ return_value = HMAC_update_impl(self, &data);
+
+exit:
+ /* Cleanup for data */
+ if (data.obj) {
+ PyBuffer_Release(&data);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(HMAC_digest__doc__,
+"digest($self, /)\n"
+"--\n"
+"\n"
+"Return the digest of the bytes passed to the update() method so far.");
+
+#define HMAC_DIGEST_METHODDEF \
+ {"digest", (PyCFunction)HMAC_digest, METH_NOARGS, HMAC_digest__doc__},
+
+static PyObject *
+HMAC_digest_impl(HMAC *self);
+
+static PyObject *
+HMAC_digest(HMAC *self, PyObject *Py_UNUSED(ignored))
+{
+ return HMAC_digest_impl(self);
+}
+
+PyDoc_STRVAR(HMAC_hexdigest__doc__,
+"hexdigest($self, /)\n"
+"--\n"
+"\n"
+"Return hexadecimal digest of the bytes passed to the update() method so far.\n"
+"\n"
+"This may be used to exchange the value safely in email or other non-binary\n"
+"environments.");
+
+#define HMAC_HEXDIGEST_METHODDEF \
+ {"hexdigest", (PyCFunction)HMAC_hexdigest, METH_NOARGS, HMAC_hexdigest__doc__},
+
+static PyObject *
+HMAC_hexdigest_impl(HMAC *self);
+
+static PyObject *
+HMAC_hexdigest(HMAC *self, PyObject *Py_UNUSED(ignored))
+{
+ return HMAC_hexdigest_impl(self);
+}
+
+PyDoc_STRVAR(_hashlib_new__doc__,
+"new($module, /, name, string=None, *, usedforsecurity=True)\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 _HASHLIB_NEW_METHODDEF \
+ {"new", (PyCFunction)(void(*)(void))_hashlib_new, METH_FASTCALL|METH_KEYWORDS, _hashlib_new__doc__},
+
+static PyObject *
+_hashlib_new_impl(PyObject *module, const char *name, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"name", "string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "new", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+ const char *name;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("new", "argument 'name'", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ if (PyObject_GetBuffer(args[1], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("new", "argument 'string'", "contiguous buffer", args[1]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[2]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_new_impl(module, name, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_md5__doc__,
+"openssl_md5($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a md5 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_MD5_METHODDEF \
+ {"openssl_md5", (PyCFunction)(void(*)(void))_hashlib_openssl_md5, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_md5__doc__},
+
+static PyObject *
+_hashlib_openssl_md5_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_md5", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_md5", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_md5_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha1__doc__,
+"openssl_sha1($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a sha1 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHA1_METHODDEF \
+ {"openssl_sha1", (PyCFunction)(void(*)(void))_hashlib_openssl_sha1, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha1__doc__},
+
+static PyObject *
+_hashlib_openssl_sha1_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha1", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_sha1", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_sha1_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha224__doc__,
+"openssl_sha224($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a sha224 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHA224_METHODDEF \
+ {"openssl_sha224", (PyCFunction)(void(*)(void))_hashlib_openssl_sha224, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha224__doc__},
+
+static PyObject *
+_hashlib_openssl_sha224_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha224", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_sha224", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_sha224_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha256__doc__,
+"openssl_sha256($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a sha256 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHA256_METHODDEF \
+ {"openssl_sha256", (PyCFunction)(void(*)(void))_hashlib_openssl_sha256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha256__doc__},
+
+static PyObject *
+_hashlib_openssl_sha256_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha256", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_sha256", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_sha256_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha384__doc__,
+"openssl_sha384($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a sha384 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHA384_METHODDEF \
+ {"openssl_sha384", (PyCFunction)(void(*)(void))_hashlib_openssl_sha384, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha384__doc__},
+
+static PyObject *
+_hashlib_openssl_sha384_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha384", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_sha384", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_sha384_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_sha512__doc__,
+"openssl_sha512($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a sha512 hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHA512_METHODDEF \
+ {"openssl_sha512", (PyCFunction)(void(*)(void))_hashlib_openssl_sha512, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha512__doc__},
+
+static PyObject *
+_hashlib_openssl_sha512_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_sha512", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_sha512", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_sha512_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
+"openssl_shake_128($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a shake-128 variable hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHAKE_128_METHODDEF \
+ {"openssl_shake_128", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_128, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_128__doc__},
+
+static PyObject *
+_hashlib_openssl_shake_128_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_128", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_shake_128", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_shake_128_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
+"openssl_shake_256($module, /, string=None, *, usedforsecurity=True)\n"
+"--\n"
+"\n"
+"Returns a shake-256 variable hash object; optionally initialized with a string.");
+
+#define _HASHLIB_OPENSSL_SHAKE_256_METHODDEF \
+ {"openssl_shake_256", (PyCFunction)(void(*)(void))_hashlib_openssl_shake_256, METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_256__doc__},
+
+static PyObject *
+_hashlib_openssl_shake_256_impl(PyObject *module, Py_buffer *string,
+ int usedforsecurity);
+
+static PyObject *
+_hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "openssl_shake_256", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
+ Py_buffer string = {NULL, NULL};
+ int usedforsecurity = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ if (PyObject_GetBuffer(args[0], &string, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&string, 'C')) {
+ _PyArg_BadArgument("openssl_shake_256", "argument 'string'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _hashlib_openssl_shake_256_impl(module, &string, usedforsecurity);
+
+exit:
+ /* Cleanup for string */
+ if (string.obj) {
+ PyBuffer_Release(&string);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_compare_digest__doc__,
+"compare_digest($module, a, b, /)\n"
+"--\n"
+"\n"
+"Return \'a == b\'.\n"
+"\n"
+"This function uses an approach designed to prevent\n"
+"timing analysis, making it appropriate for cryptography.\n"
+"\n"
+"a and b must both be of the same type: either str (ASCII only),\n"
+"or any bytes-like object.\n"
+"\n"
+"Note: If a and b are of different lengths, or if an error occurs,\n"
+"a timing attack could theoretically reveal information about the\n"
+"types and lengths of a and b--but not their values.");
+
+#define _HASHLIB_COMPARE_DIGEST_METHODDEF \
+ {"compare_digest", (PyCFunction)(void(*)(void))_hashlib_compare_digest, METH_FASTCALL, _hashlib_compare_digest__doc__},
+
+static PyObject *
+_hashlib_compare_digest_impl(PyObject *module, PyObject *a, PyObject *b);
+
+static PyObject *
+_hashlib_compare_digest(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *a;
+ PyObject *b;
+
+ if (!_PyArg_CheckPositional("compare_digest", nargs, 2, 2)) {
+ goto exit;
+ }
+ a = args[0];
+ b = args[1];
+ return_value = _hashlib_compare_digest_impl(module, a, b);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_hmac_singleshot__doc__,
+"hmac_digest($module, /, key, msg, digest)\n"
+"--\n"
+"\n"
+"Single-shot HMAC.");
+
+#define _HASHLIB_HMAC_SINGLESHOT_METHODDEF \
+ {"hmac_digest", (PyCFunction)(void(*)(void))_hashlib_hmac_singleshot, METH_FASTCALL|METH_KEYWORDS, _hashlib_hmac_singleshot__doc__},
+
+static PyObject *
+_hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key,
+ Py_buffer *msg, const char *digest);
+
+static PyObject *
+_hashlib_hmac_singleshot(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"key", "msg", "digest", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hmac_digest", 0};
+ PyObject *argsbuf[3];
+ Py_buffer key = {NULL, NULL};
+ Py_buffer msg = {NULL, NULL};
+ const char *digest;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyObject_GetBuffer(args[0], &key, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&key, 'C')) {
+ _PyArg_BadArgument("hmac_digest", "argument 'key'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (PyObject_GetBuffer(args[1], &msg, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&msg, 'C')) {
+ _PyArg_BadArgument("hmac_digest", "argument 'msg'", "contiguous buffer", args[1]);
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[2])) {
+ _PyArg_BadArgument("hmac_digest", "argument 'digest'", "str", args[2]);
+ goto exit;
+ }
+ Py_ssize_t digest_length;
+ digest = PyUnicode_AsUTF8AndSize(args[2], &digest_length);
+ if (digest == NULL) {
+ goto exit;
+ }
+ if (strlen(digest) != (size_t)digest_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ return_value = _hashlib_hmac_singleshot_impl(module, &key, &msg, digest);
+
+exit:
+ /* Cleanup for key */
+ if (key.obj) {
+ PyBuffer_Release(&key);
+ }
+ /* Cleanup for msg */
+ if (msg.obj) {
+ PyBuffer_Release(&msg);
+ }
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_hashlib_hmac_new__doc__,
+"hmac_new($module, /, key, msg=None, digestmod=None)\n"
+"--\n"
+"\n"
+"Return a new hmac object.");
+
+#define _HASHLIB_HMAC_NEW_METHODDEF \
+ {"hmac_new", (PyCFunction)(void(*)(void))_hashlib_hmac_new, METH_FASTCALL|METH_KEYWORDS, _hashlib_hmac_new__doc__},
+
+static PyObject *
+_hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, Py_buffer *msg,
+ const char *digestmod);
+
+static PyObject *
+_hashlib_hmac_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"key", "msg", "digestmod", NULL};
+ static _PyArg_Parser _parser = {NULL, _keywords, "hmac_new", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
+ Py_buffer key = {NULL, NULL};
+ Py_buffer msg = {NULL, NULL};
+ const char *digestmod = NULL;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyObject_GetBuffer(args[0], &key, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&key, 'C')) {
+ _PyArg_BadArgument("hmac_new", "argument 'key'", "contiguous buffer", args[0]);
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ if (PyObject_GetBuffer(args[1], &msg, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&msg, 'C')) {
+ _PyArg_BadArgument("hmac_new", "argument 'msg'", "contiguous buffer", args[1]);
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ if (!PyUnicode_Check(args[2])) {
+ _PyArg_BadArgument("hmac_new", "argument 'digestmod'", "str", args[2]);
+ goto exit;
+ }
+ Py_ssize_t digestmod_length;
+ digestmod = PyUnicode_AsUTF8AndSize(args[2], &digestmod_length);
+ if (digestmod == NULL) {
+ goto exit;
+ }
+ if (strlen(digestmod) != (size_t)digestmod_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+skip_optional_pos:
+ return_value = _hashlib_hmac_new_impl(module, &key, &msg, digestmod);
+
+exit:
+ /* Cleanup for key */
+ if (key.obj) {
+ PyBuffer_Release(&key);
+ }
+ /* Cleanup for msg */
+ if (msg.obj) {
+ PyBuffer_Release(&msg);
+ }
+
+ return return_value;
+}
+/*[clinic end generated code: output=b4705bad5ece43e9 input=a9049054013a1b77]*/
--
2.32.0