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