1 /*
2  * Written in 2013 by Dmitry Chestnykh <[email protected]>
3  * Modified for CPython by Christian Heimes <[email protected]>
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 
38 extern PyType_Spec blake2s_type_spec;
39 
40 
41 typedef 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]
51 module _blake2
52 class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
53 [clinic start generated code]*/
54 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/
55 
56 
57 static BLAKE2sObject *
new_BLAKE2sObject(PyTypeObject * type)58 new_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 
87 Return a new BLAKE2s hash object.
88 [clinic start generated code]*/
89 
90 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)91 py_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 
245 Return a copy of the hash object.
246 [clinic start generated code]*/
247 
248 static PyObject *
_blake2_blake2s_copy_impl(BLAKE2sObject * self)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 
270 Update this hash object's state with the provided bytes-like object.
271 [clinic start generated code]*/
272 
273 static PyObject *
_blake2_blake2s_update(BLAKE2sObject * self,PyObject * data)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 
301 Return the digest value as a bytes object.
302 [clinic start generated code]*/
303 
304 static PyObject *
_blake2_blake2s_digest_impl(BLAKE2sObject * self)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 
322 Return the digest value as a string of hexadecimal digits.
323 [clinic start generated code]*/
324 
325 static PyObject *
_blake2_blake2s_hexdigest_impl(BLAKE2sObject * self)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 
340 static 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 
350 static PyObject *
py_blake2s_get_name(BLAKE2sObject * self,void * closure)351 py_blake2s_get_name(BLAKE2sObject *self, void *closure)
352 {
353     return PyUnicode_FromString("blake2s");
354 }
355 
356 
357 
358 static PyObject *
py_blake2s_get_block_size(BLAKE2sObject * self,void * closure)359 py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
360 {
361     return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
362 }
363 
364 
365 
366 static PyObject *
py_blake2s_get_digest_size(BLAKE2sObject * self,void * closure)367 py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
368 {
369     return PyLong_FromLong(self->param.digest_length);
370 }
371 
372 
373 static 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 
384 static void
py_blake2s_dealloc(PyObject * self)385 py_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 
402 static 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 
411 PyType_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