/* * Written in 2013 by Dmitry Chestnykh * Modified for CPython by Christian Heimes * * 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; } } // NB: Simple assignment here would be incorrect on big endian platforms. store32(&(self->param.leaf_length), 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 // NB: Simple assignment here would be incorrect on big endian platforms. store64(&(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 */ };