1/*
2 * Written in 2013 by Dmitry Chestnykh <dmitry@codingrobots.com>
3 * Modified for CPython by Christian Heimes <christian@python.org>
4 *
5 * To the extent possible under law, the author have dedicated all
6 * copyright and related and neighboring rights to this software to
7 * the public domain worldwide. This software is distributed without
8 * any warranty. http://creativecommons.org/publicdomain/zero/1.0/
9 */
10
11/* WARNING: autogenerated file!
12 *
13 * The blake2s_impl.c is autogenerated from blake2s_impl.c.
14 */
15
16#ifndef Py_BUILD_CORE_BUILTIN
17#  define Py_BUILD_CORE_MODULE 1
18#endif
19
20#include "Python.h"
21#include "pycore_strhex.h"       // _Py_strhex()
22
23#include "../hashlib.h"
24#include "blake2module.h"
25
26#ifndef HAVE_LIBB2
27/* pure SSE2 implementation is very slow, so only use the more optimized SSSE3+
28 * https://bugs.python.org/issue31834 */
29#if defined(__SSSE3__) || defined(__SSE4_1__) || defined(__AVX__) || defined(__XOP__)
30#include "impl/blake2s.c"
31#else
32#include "impl/blake2s-ref.c"
33#endif
34#endif // !HAVE_LIBB2
35
36#define HAVE_BLAKE2S 1
37
38extern PyType_Spec blake2s_type_spec;
39
40
41typedef struct {
42    PyObject_HEAD
43    blake2s_param    param;
44    blake2s_state    state;
45    PyThread_type_lock lock;
46} BLAKE2sObject;
47
48#include "clinic/blake2s_impl.c.h"
49
50/*[clinic input]
51module _blake2
52class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
53[clinic start generated code]*/
54/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/
55
56
57static BLAKE2sObject *
58new_BLAKE2sObject(PyTypeObject *type)
59{
60    BLAKE2sObject *self;
61    self = (BLAKE2sObject *)type->tp_alloc(type, 0);
62    if (self != NULL) {
63        self->lock = NULL;
64    }
65    return self;
66}
67
68/*[clinic input]
69@classmethod
70_blake2.blake2s.__new__ as py_blake2s_new
71    data: object(c_default="NULL") = b''
72    /
73    *
74    digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2.blake2s.MAX_DIGEST_SIZE
75    key: Py_buffer(c_default="NULL", py_default="b''") = None
76    salt: Py_buffer(c_default="NULL", py_default="b''") = None
77    person: Py_buffer(c_default="NULL", py_default="b''") = None
78    fanout: int = 1
79    depth: int = 1
80    leaf_size: unsigned_long = 0
81    node_offset: unsigned_long_long = 0
82    node_depth: int = 0
83    inner_size: int = 0
84    last_node: bool = False
85    usedforsecurity: bool = True
86
87Return a new BLAKE2s hash object.
88[clinic start generated code]*/
89
90static PyObject *
91py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
92                    Py_buffer *key, Py_buffer *salt, Py_buffer *person,
93                    int fanout, int depth, unsigned long leaf_size,
94                    unsigned long long node_offset, int node_depth,
95                    int inner_size, int last_node, int usedforsecurity)
96/*[clinic end generated code: output=556181f73905c686 input=4dda87723f23abb0]*/
97{
98    BLAKE2sObject *self = NULL;
99    Py_buffer buf;
100
101    self = new_BLAKE2sObject(type);
102    if (self == NULL) {
103        goto error;
104    }
105
106    /* Zero parameter block. */
107    memset(&self->param, 0, sizeof(self->param));
108
109    /* Set digest size. */
110    if (digest_size <= 0 || digest_size > BLAKE2S_OUTBYTES) {
111        PyErr_Format(PyExc_ValueError,
112                "digest_size must be between 1 and %d bytes",
113                BLAKE2S_OUTBYTES);
114        goto error;
115    }
116    self->param.digest_length = digest_size;
117
118    /* Set salt parameter. */
119    if ((salt->obj != NULL) && salt->len) {
120        if (salt->len > BLAKE2S_SALTBYTES) {
121            PyErr_Format(PyExc_ValueError,
122                "maximum salt length is %d bytes",
123                BLAKE2S_SALTBYTES);
124            goto error;
125        }
126        memcpy(self->param.salt, salt->buf, salt->len);
127    }
128
129    /* Set personalization parameter. */
130    if ((person->obj != NULL) && person->len) {
131        if (person->len > BLAKE2S_PERSONALBYTES) {
132            PyErr_Format(PyExc_ValueError,
133                "maximum person length is %d bytes",
134                BLAKE2S_PERSONALBYTES);
135            goto error;
136        }
137        memcpy(self->param.personal, person->buf, person->len);
138    }
139
140    /* Set tree parameters. */
141    if (fanout < 0 || fanout > 255) {
142        PyErr_SetString(PyExc_ValueError,
143                "fanout must be between 0 and 255");
144        goto error;
145    }
146    self->param.fanout = (uint8_t)fanout;
147
148    if (depth <= 0 || depth > 255) {
149        PyErr_SetString(PyExc_ValueError,
150                "depth must be between 1 and 255");
151        goto error;
152    }
153    self->param.depth = (uint8_t)depth;
154
155    if (leaf_size > 0xFFFFFFFFU) {
156        PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
157        goto error;
158    }
159    // NB: Simple assignment here would be incorrect on big endian platforms.
160    store32(&(self->param.leaf_length), leaf_size);
161
162#ifdef HAVE_BLAKE2S
163    if (node_offset > 0xFFFFFFFFFFFFULL) {
164        /* maximum 2**48 - 1 */
165         PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
166         goto error;
167     }
168    store48(&(self->param.node_offset), node_offset);
169#else
170    // NB: Simple assignment here would be incorrect on big endian platforms.
171    store64(&(self->param.node_offset), node_offset);
172#endif
173
174    if (node_depth < 0 || node_depth > 255) {
175        PyErr_SetString(PyExc_ValueError,
176                "node_depth must be between 0 and 255");
177        goto error;
178    }
179    self->param.node_depth = node_depth;
180
181    if (inner_size < 0 || inner_size > BLAKE2S_OUTBYTES) {
182        PyErr_Format(PyExc_ValueError,
183                "inner_size must be between 0 and is %d",
184                BLAKE2S_OUTBYTES);
185        goto error;
186    }
187    self->param.inner_length = inner_size;
188
189    /* Set key length. */
190    if ((key->obj != NULL) && key->len) {
191        if (key->len > BLAKE2S_KEYBYTES) {
192            PyErr_Format(PyExc_ValueError,
193                "maximum key length is %d bytes",
194                BLAKE2S_KEYBYTES);
195            goto error;
196        }
197        self->param.key_length = (uint8_t)key->len;
198    }
199
200    /* Initialize hash state. */
201    if (blake2s_init_param(&self->state, &self->param) < 0) {
202        PyErr_SetString(PyExc_RuntimeError,
203                "error initializing hash state");
204        goto error;
205    }
206
207    /* Set last node flag (must come after initialization). */
208    self->state.last_node = last_node;
209
210    /* Process key block if any. */
211    if (self->param.key_length) {
212        uint8_t block[BLAKE2S_BLOCKBYTES];
213        memset(block, 0, sizeof(block));
214        memcpy(block, key->buf, key->len);
215        blake2s_update(&self->state, block, sizeof(block));
216        secure_zero_memory(block, sizeof(block));
217    }
218
219    /* Process initial data if any. */
220    if (data != NULL) {
221        GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
222
223        if (buf.len >= HASHLIB_GIL_MINSIZE) {
224            Py_BEGIN_ALLOW_THREADS
225            blake2s_update(&self->state, buf.buf, buf.len);
226            Py_END_ALLOW_THREADS
227        } else {
228            blake2s_update(&self->state, buf.buf, buf.len);
229        }
230        PyBuffer_Release(&buf);
231    }
232
233    return (PyObject *)self;
234
235  error:
236    if (self != NULL) {
237        Py_DECREF(self);
238    }
239    return NULL;
240}
241
242/*[clinic input]
243_blake2.blake2s.copy
244
245Return a copy of the hash object.
246[clinic start generated code]*/
247
248static PyObject *
249_blake2_blake2s_copy_impl(BLAKE2sObject *self)
250/*[clinic end generated code: output=5b90131c4eae275e input=0b9d44942f0fe4b2]*/
251{
252    BLAKE2sObject *cpy;
253
254    if ((cpy = new_BLAKE2sObject(Py_TYPE(self))) == NULL)
255        return NULL;
256
257    ENTER_HASHLIB(self);
258    cpy->param = self->param;
259    cpy->state = self->state;
260    LEAVE_HASHLIB(self);
261    return (PyObject *)cpy;
262}
263
264/*[clinic input]
265_blake2.blake2s.update
266
267    data: object
268    /
269
270Update this hash object's state with the provided bytes-like object.
271[clinic start generated code]*/
272
273static PyObject *
274_blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
275/*[clinic end generated code: output=757dc087fec37815 input=97500db2f9de4aaa]*/
276{
277    Py_buffer buf;
278
279    GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
280
281    if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
282        self->lock = PyThread_allocate_lock();
283
284    if (self->lock != NULL) {
285       Py_BEGIN_ALLOW_THREADS
286       PyThread_acquire_lock(self->lock, 1);
287       blake2s_update(&self->state, buf.buf, buf.len);
288       PyThread_release_lock(self->lock);
289       Py_END_ALLOW_THREADS
290    } else {
291        blake2s_update(&self->state, buf.buf, buf.len);
292    }
293    PyBuffer_Release(&buf);
294
295    Py_RETURN_NONE;
296}
297
298/*[clinic input]
299_blake2.blake2s.digest
300
301Return the digest value as a bytes object.
302[clinic start generated code]*/
303
304static PyObject *
305_blake2_blake2s_digest_impl(BLAKE2sObject *self)
306/*[clinic end generated code: output=40c566ca4bc6bc51 input=f41e0b8d6d937454]*/
307{
308    uint8_t digest[BLAKE2S_OUTBYTES];
309    blake2s_state state_cpy;
310
311    ENTER_HASHLIB(self);
312    state_cpy = self->state;
313    blake2s_final(&state_cpy, digest, self->param.digest_length);
314    LEAVE_HASHLIB(self);
315    return PyBytes_FromStringAndSize((const char *)digest,
316            self->param.digest_length);
317}
318
319/*[clinic input]
320_blake2.blake2s.hexdigest
321
322Return the digest value as a string of hexadecimal digits.
323[clinic start generated code]*/
324
325static PyObject *
326_blake2_blake2s_hexdigest_impl(BLAKE2sObject *self)
327/*[clinic end generated code: output=15153eb5e59c52eb input=c77a1321567e8952]*/
328{
329    uint8_t digest[BLAKE2S_OUTBYTES];
330    blake2s_state state_cpy;
331
332    ENTER_HASHLIB(self);
333    state_cpy = self->state;
334    blake2s_final(&state_cpy, digest, self->param.digest_length);
335    LEAVE_HASHLIB(self);
336    return _Py_strhex((const char *)digest, self->param.digest_length);
337}
338
339
340static PyMethodDef py_blake2s_methods[] = {
341    _BLAKE2_BLAKE2S_COPY_METHODDEF
342    _BLAKE2_BLAKE2S_DIGEST_METHODDEF
343    _BLAKE2_BLAKE2S_HEXDIGEST_METHODDEF
344    _BLAKE2_BLAKE2S_UPDATE_METHODDEF
345    {NULL, NULL}
346};
347
348
349
350static PyObject *
351py_blake2s_get_name(BLAKE2sObject *self, void *closure)
352{
353    return PyUnicode_FromString("blake2s");
354}
355
356
357
358static PyObject *
359py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
360{
361    return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
362}
363
364
365
366static PyObject *
367py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
368{
369    return PyLong_FromLong(self->param.digest_length);
370}
371
372
373static PyGetSetDef py_blake2s_getsetters[] = {
374    {"name", (getter)py_blake2s_get_name,
375        NULL, NULL, NULL},
376    {"block_size", (getter)py_blake2s_get_block_size,
377        NULL, NULL, NULL},
378    {"digest_size", (getter)py_blake2s_get_digest_size,
379        NULL, NULL, NULL},
380    {NULL}
381};
382
383
384static void
385py_blake2s_dealloc(PyObject *self)
386{
387    BLAKE2sObject *obj = (BLAKE2sObject *)self;
388
389    /* Try not to leave state in memory. */
390    secure_zero_memory(&obj->param, sizeof(obj->param));
391    secure_zero_memory(&obj->state, sizeof(obj->state));
392    if (obj->lock) {
393        PyThread_free_lock(obj->lock);
394        obj->lock = NULL;
395    }
396
397    PyTypeObject *type = Py_TYPE(self);
398    PyObject_Free(self);
399    Py_DECREF(type);
400}
401
402static PyType_Slot blake2s_type_slots[] = {
403    {Py_tp_dealloc, py_blake2s_dealloc},
404    {Py_tp_doc, (char *)py_blake2s_new__doc__},
405    {Py_tp_methods, py_blake2s_methods},
406    {Py_tp_getset, py_blake2s_getsetters},
407    {Py_tp_new, py_blake2s_new},
408    {0,0}
409};
410
411PyType_Spec blake2s_type_spec = {
412    .name = "_blake2.blake2s",
413    .basicsize =  sizeof(BLAKE2sObject),
414    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
415    .slots = blake2s_type_slots
416};
417