summaryrefslogtreecommitdiff
path: root/Modules/_blake2/blake2s_impl.c
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
committerNick Coghlan <ncoghlan@gmail.com>2017-02-09 16:08:17 +0100
commitc6180bb73c8c7c7f9d8ea9816487b710597b6fc1 (patch)
treefb4a5c18886537b4b7df46ed3b2aa579747ff507 /Modules/_blake2/blake2s_impl.c
parent5e0114a832a903518c4af6983161c0c2a8942a24 (diff)
parent819a21a3a4aac38f32e1ba4f68bcef45591fa3f0 (diff)
downloadcpython-c6180bb73c8c7c7f9d8ea9816487b710597b6fc1.tar.gz
Merge issue #26355 fix from Python 3.5
Diffstat (limited to 'Modules/_blake2/blake2s_impl.c')
-rw-r--r--Modules/_blake2/blake2s_impl.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c
new file mode 100644
index 0000000000..11d2e02251
--- /dev/null
+++ b/Modules/_blake2/blake2s_impl.c
@@ -0,0 +1,460 @@
+/*
+ * Written in 2013 by Dmitry Chestnykh <dmitry@codingrobots.com>
+ * Modified for CPython by Christian Heimes <christian@python.org>
+ *
+ * To the extent possible under law, the author have dedicated all
+ * copyright and related and neighboring rights to this software to
+ * the public domain worldwide. This software is distributed without
+ * any warranty. http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* WARNING: autogenerated file!
+ *
+ * The blake2s_impl.c is autogenerated from blake2s_impl.c.
+ */
+
+#include "Python.h"
+#include "pystrhex.h"
+#ifdef WITH_THREAD
+#include "pythread.h"
+#endif
+
+#include "../hashlib.h"
+#include "blake2ns.h"
+
+#define HAVE_BLAKE2S 1
+#define BLAKE2_LOCAL_INLINE(type) Py_LOCAL_INLINE(type)
+
+#include "impl/blake2.h"
+#include "impl/blake2-impl.h" /* for secure_zero_memory() and store48() */
+
+#ifdef BLAKE2_USE_SSE
+#include "impl/blake2s.c"
+#else
+#include "impl/blake2s-ref.c"
+#endif
+
+
+extern PyTypeObject PyBlake2_BLAKE2sType;
+
+typedef struct {
+ PyObject_HEAD
+ blake2s_param param;
+ blake2s_state state;
+#ifdef WITH_THREAD
+ PyThread_type_lock lock;
+#endif
+} BLAKE2sObject;
+
+#include "clinic/blake2s_impl.c.h"
+
+/*[clinic input]
+module _blake2s
+class _blake2s.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=edbfcf7557a685a7]*/
+
+
+static BLAKE2sObject *
+new_BLAKE2sObject(PyTypeObject *type)
+{
+ BLAKE2sObject *self;
+ self = (BLAKE2sObject *)type->tp_alloc(type, 0);
+#ifdef WITH_THREAD
+ if (self != NULL) {
+ self->lock = NULL;
+ }
+#endif
+ return self;
+}
+
+/*[clinic input]
+@classmethod
+_blake2s.blake2s.__new__ as py_blake2s_new
+ string as data: object = NULL
+ *
+ digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2s.blake2s.MAX_DIGEST_SIZE
+ key: Py_buffer = None
+ salt: Py_buffer = None
+ person: Py_buffer = None
+ fanout: int = 1
+ depth: int = 1
+ leaf_size as leaf_size_obj: object = NULL
+ node_offset as node_offset_obj: object = NULL
+ node_depth: int = 0
+ inner_size: int = 0
+ last_node: bool = False
+
+Return a new BLAKE2s hash object.
+[clinic start generated code]*/
+
+static PyObject *
+py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
+ Py_buffer *key, Py_buffer *salt, Py_buffer *person,
+ int fanout, int depth, PyObject *leaf_size_obj,
+ PyObject *node_offset_obj, int node_depth,
+ int inner_size, int last_node)
+/*[clinic end generated code: output=fe060b258a8cbfc6 input=458cfdcb3d0d47ff]*/
+{
+ BLAKE2sObject *self = NULL;
+ Py_buffer buf;
+
+ unsigned long leaf_size = 0;
+ unsigned long long node_offset = 0;
+
+ self = new_BLAKE2sObject(type);
+ if (self == NULL) {
+ goto error;
+ }
+
+ /* Zero parameter block. */
+ memset(&self->param, 0, sizeof(self->param));
+
+ /* Set digest size. */
+ if (digest_size <= 0 || digest_size > BLAKE2S_OUTBYTES) {
+ PyErr_Format(PyExc_ValueError,
+ "digest_size must be between 1 and %d bytes",
+ BLAKE2S_OUTBYTES);
+ goto error;
+ }
+ self->param.digest_length = digest_size;
+
+ /* Set salt parameter. */
+ if ((salt->obj != NULL) && salt->len) {
+ if (salt->len > BLAKE2S_SALTBYTES) {
+ PyErr_Format(PyExc_ValueError,
+ "maximum salt length is %d bytes",
+ BLAKE2S_SALTBYTES);
+ goto error;
+ }
+ memcpy(self->param.salt, salt->buf, salt->len);
+ }
+
+ /* Set personalization parameter. */
+ if ((person->obj != NULL) && person->len) {
+ if (person->len > BLAKE2S_PERSONALBYTES) {
+ PyErr_Format(PyExc_ValueError,
+ "maximum person length is %d bytes",
+ BLAKE2S_PERSONALBYTES);
+ goto error;
+ }
+ memcpy(self->param.personal, person->buf, person->len);
+ }
+
+ /* Set tree parameters. */
+ if (fanout < 0 || fanout > 255) {
+ PyErr_SetString(PyExc_ValueError,
+ "fanout must be between 0 and 255");
+ goto error;
+ }
+ self->param.fanout = (uint8_t)fanout;
+
+ if (depth <= 0 || depth > 255) {
+ PyErr_SetString(PyExc_ValueError,
+ "depth must be between 1 and 255");
+ goto error;
+ }
+ self->param.depth = (uint8_t)depth;
+
+ if (leaf_size_obj != NULL) {
+ leaf_size = PyLong_AsUnsignedLong(leaf_size_obj);
+ if (leaf_size == (unsigned long) -1 && PyErr_Occurred()) {
+ goto error;
+ }
+ if (leaf_size > 0xFFFFFFFFU) {
+ PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
+ goto error;
+ }
+ }
+ self->param.leaf_length = (unsigned int)leaf_size;
+
+ if (node_offset_obj != NULL) {
+ node_offset = PyLong_AsUnsignedLongLong(node_offset_obj);
+ if (node_offset == (unsigned long long) -1 && PyErr_Occurred()) {
+ goto error;
+ }
+ }
+#ifdef HAVE_BLAKE2S
+ if (node_offset > 0xFFFFFFFFFFFFULL) {
+ /* maximum 2**48 - 1 */
+ PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
+ goto error;
+ }
+ store48(&(self->param.node_offset), node_offset);
+#else
+ self->param.node_offset = node_offset;
+#endif
+
+ if (node_depth < 0 || node_depth > 255) {
+ PyErr_SetString(PyExc_ValueError,
+ "node_depth must be between 0 and 255");
+ goto error;
+ }
+ self->param.node_depth = node_depth;
+
+ if (inner_size < 0 || inner_size > BLAKE2S_OUTBYTES) {
+ PyErr_Format(PyExc_ValueError,
+ "inner_size must be between 0 and is %d",
+ BLAKE2S_OUTBYTES);
+ goto error;
+ }
+ self->param.inner_length = inner_size;
+
+ /* Set key length. */
+ if ((key->obj != NULL) && key->len) {
+ if (key->len > BLAKE2S_KEYBYTES) {
+ PyErr_Format(PyExc_ValueError,
+ "maximum key length is %d bytes",
+ BLAKE2S_KEYBYTES);
+ goto error;
+ }
+ self->param.key_length = (uint8_t)key->len;
+ }
+
+ /* Initialize hash state. */
+ if (blake2s_init_param(&self->state, &self->param) < 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "error initializing hash state");
+ goto error;
+ }
+
+ /* Set last node flag (must come after initialization). */
+ self->state.last_node = last_node;
+
+ /* Process key block if any. */
+ if (self->param.key_length) {
+ uint8_t block[BLAKE2S_BLOCKBYTES];
+ memset(block, 0, sizeof(block));
+ memcpy(block, key->buf, key->len);
+ blake2s_update(&self->state, block, sizeof(block));
+ secure_zero_memory(block, sizeof(block));
+ }
+
+ /* Process initial data if any. */
+ if (data != NULL) {
+ GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
+
+ if (buf.len >= HASHLIB_GIL_MINSIZE) {
+ Py_BEGIN_ALLOW_THREADS
+ blake2s_update(&self->state, buf.buf, buf.len);
+ Py_END_ALLOW_THREADS
+ } else {
+ blake2s_update(&self->state, buf.buf, buf.len);
+ }
+ PyBuffer_Release(&buf);
+ }
+
+ return (PyObject *)self;
+
+ error:
+ if (self != NULL) {
+ Py_DECREF(self);
+ }
+ return NULL;
+}
+
+/*[clinic input]
+_blake2s.blake2s.copy
+
+Return a copy of the hash object.
+[clinic start generated code]*/
+
+static PyObject *
+_blake2s_blake2s_copy_impl(BLAKE2sObject *self)
+/*[clinic end generated code: output=6c5bada404b7aed7 input=c8858e887ae4a07a]*/
+{
+ BLAKE2sObject *cpy;
+
+ if ((cpy = new_BLAKE2sObject(Py_TYPE(self))) == NULL)
+ return NULL;
+
+ ENTER_HASHLIB(self);
+ cpy->param = self->param;
+ cpy->state = self->state;
+ LEAVE_HASHLIB(self);
+ return (PyObject *)cpy;
+}
+
+/*[clinic input]
+_blake2s.blake2s.update
+
+ obj: object
+ /
+
+Update this hash object's state with the provided string.
+[clinic start generated code]*/
+
+static PyObject *
+_blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj)
+/*[clinic end generated code: output=fe8438a1d3cede87 input=47a408b9a3cc05c5]*/
+{
+ Py_buffer buf;
+
+ GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
+
+#ifdef WITH_THREAD
+ if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
+ self->lock = PyThread_allocate_lock();
+
+ if (self->lock != NULL) {
+ Py_BEGIN_ALLOW_THREADS
+ PyThread_acquire_lock(self->lock, 1);
+ blake2s_update(&self->state, buf.buf, buf.len);
+ PyThread_release_lock(self->lock);
+ Py_END_ALLOW_THREADS
+ } else {
+ blake2s_update(&self->state, buf.buf, buf.len);
+ }
+#else
+ blake2s_update(&self->state, buf.buf, buf.len);
+#endif /* !WITH_THREAD */
+ PyBuffer_Release(&buf);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+/*[clinic input]
+_blake2s.blake2s.digest
+
+Return the digest value as a string of binary data.
+[clinic start generated code]*/
+
+static PyObject *
+_blake2s_blake2s_digest_impl(BLAKE2sObject *self)
+/*[clinic end generated code: output=80e81a48c6f79cf9 input=feb9a220135bdeba]*/
+{
+ uint8_t digest[BLAKE2S_OUTBYTES];
+ blake2s_state state_cpy;
+
+ ENTER_HASHLIB(self);
+ state_cpy = self->state;
+ blake2s_final(&state_cpy, digest, self->param.digest_length);
+ LEAVE_HASHLIB(self);
+ return PyBytes_FromStringAndSize((const char *)digest,
+ self->param.digest_length);
+}
+
+/*[clinic input]
+_blake2s.blake2s.hexdigest
+
+Return the digest value as a string of hexadecimal digits.
+[clinic start generated code]*/
+
+static PyObject *
+_blake2s_blake2s_hexdigest_impl(BLAKE2sObject *self)
+/*[clinic end generated code: output=db6c5028c0a3c2e5 input=4e4877b8bd7aea91]*/
+{
+ uint8_t digest[BLAKE2S_OUTBYTES];
+ blake2s_state state_cpy;
+
+ ENTER_HASHLIB(self);
+ state_cpy = self->state;
+ blake2s_final(&state_cpy, digest, self->param.digest_length);
+ LEAVE_HASHLIB(self);
+ return _Py_strhex((const char *)digest, self->param.digest_length);
+}
+
+
+static PyMethodDef py_blake2s_methods[] = {
+ _BLAKE2S_BLAKE2S_COPY_METHODDEF
+ _BLAKE2S_BLAKE2S_DIGEST_METHODDEF
+ _BLAKE2S_BLAKE2S_HEXDIGEST_METHODDEF
+ _BLAKE2S_BLAKE2S_UPDATE_METHODDEF
+ {NULL, NULL}
+};
+
+
+
+static PyObject *
+py_blake2s_get_name(BLAKE2sObject *self, void *closure)
+{
+ return PyUnicode_FromString("blake2s");
+}
+
+
+
+static PyObject *
+py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
+{
+ return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
+}
+
+
+
+static PyObject *
+py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
+{
+ return PyLong_FromLong(self->param.digest_length);
+}
+
+
+static PyGetSetDef py_blake2s_getsetters[] = {
+ {"name", (getter)py_blake2s_get_name,
+ NULL, NULL, NULL},
+ {"block_size", (getter)py_blake2s_get_block_size,
+ NULL, NULL, NULL},
+ {"digest_size", (getter)py_blake2s_get_digest_size,
+ NULL, NULL, NULL},
+ {NULL}
+};
+
+
+static void
+py_blake2s_dealloc(PyObject *self)
+{
+ BLAKE2sObject *obj = (BLAKE2sObject *)self;
+
+ /* Try not to leave state in memory. */
+ secure_zero_memory(&obj->param, sizeof(obj->param));
+ secure_zero_memory(&obj->state, sizeof(obj->state));
+#ifdef WITH_THREAD
+ if (obj->lock) {
+ PyThread_free_lock(obj->lock);
+ obj->lock = NULL;
+ }
+#endif
+ PyObject_Del(self);
+}
+
+
+PyTypeObject PyBlake2_BLAKE2sType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "_blake2.blake2s", /* tp_name */
+ sizeof(BLAKE2sObject), /* tp_size */
+ 0, /* tp_itemsize */
+ py_blake2s_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ py_blake2s_new__doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ py_blake2s_methods, /* tp_methods */
+ 0, /* tp_members */
+ py_blake2s_getsetters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ py_blake2s_new, /* tp_new */
+};