• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 blake2b_impl.c.
14  */
15 
16 #ifndef Py_BUILD_CORE_BUILTIN
17 #  define Py_BUILD_CORE_MODULE 1
18 #endif
19 
20 #include <stdbool.h>
21 #include "Python.h"
22 #include "pycore_strhex.h"       // _Py_strhex()
23 
24 #include "../hashlib.h"
25 #include "blake2module.h"
26 
27 #ifndef HAVE_LIBB2
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/blake2b.c"
32 #else
33 #include "impl/blake2b-ref.c"
34 #endif
35 #endif // !HAVE_LIBB2
36 
37 #define HAVE_BLAKE2B 1
38 
39 extern PyType_Spec blake2b_type_spec;
40 
41 
42 typedef struct {
43     PyObject_HEAD
44     blake2b_param    param;
45     blake2b_state    state;
46     bool use_mutex;
47     PyMutex mutex;
48 } BLAKE2bObject;
49 
50 #include "clinic/blake2b_impl.c.h"
51 
52 /*[clinic input]
53 module _blake2
54 class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType"
55 [clinic start generated code]*/
56 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/
57 
58 
59 static BLAKE2bObject *
new_BLAKE2bObject(PyTypeObject * type)60 new_BLAKE2bObject(PyTypeObject *type)
61 {
62     BLAKE2bObject *self;
63     self = (BLAKE2bObject *)type->tp_alloc(type, 0);
64     if (self == NULL) {
65         return NULL;
66     }
67     HASHLIB_INIT_MUTEX(self);
68 
69     return self;
70 }
71 
72 /*[clinic input]
73 @classmethod
74 _blake2.blake2b.__new__ as py_blake2b_new
75     data: object(c_default="NULL") = b''
76     /
77     *
78     digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
79     key: Py_buffer(c_default="NULL", py_default="b''") = None
80     salt: Py_buffer(c_default="NULL", py_default="b''") = None
81     person: Py_buffer(c_default="NULL", py_default="b''") = None
82     fanout: int = 1
83     depth: int = 1
84     leaf_size: unsigned_long = 0
85     node_offset: unsigned_long_long = 0
86     node_depth: int = 0
87     inner_size: int = 0
88     last_node: bool = False
89     usedforsecurity: bool = True
90 
91 Return a new BLAKE2b hash object.
92 [clinic start generated code]*/
93 
94 static PyObject *
py_blake2b_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)95 py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
96                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
97                     int fanout, int depth, unsigned long leaf_size,
98                     unsigned long long node_offset, int node_depth,
99                     int inner_size, int last_node, int usedforsecurity)
100 /*[clinic end generated code: output=32bfd8f043c6896f input=b947312abff46977]*/
101 {
102     BLAKE2bObject *self = NULL;
103     Py_buffer buf;
104 
105     self = new_BLAKE2bObject(type);
106     if (self == NULL) {
107         goto error;
108     }
109 
110     /* Zero parameter block. */
111     memset(&self->param, 0, sizeof(self->param));
112 
113     /* Set digest size. */
114     if (digest_size <= 0 || digest_size > BLAKE2B_OUTBYTES) {
115         PyErr_Format(PyExc_ValueError,
116                 "digest_size must be between 1 and %d bytes",
117                 BLAKE2B_OUTBYTES);
118         goto error;
119     }
120     self->param.digest_length = digest_size;
121 
122     /* Set salt parameter. */
123     if ((salt->obj != NULL) && salt->len) {
124         if (salt->len > BLAKE2B_SALTBYTES) {
125             PyErr_Format(PyExc_ValueError,
126                 "maximum salt length is %d bytes",
127                 BLAKE2B_SALTBYTES);
128             goto error;
129         }
130         memcpy(self->param.salt, salt->buf, salt->len);
131     }
132 
133     /* Set personalization parameter. */
134     if ((person->obj != NULL) && person->len) {
135         if (person->len > BLAKE2B_PERSONALBYTES) {
136             PyErr_Format(PyExc_ValueError,
137                 "maximum person length is %d bytes",
138                 BLAKE2B_PERSONALBYTES);
139             goto error;
140         }
141         memcpy(self->param.personal, person->buf, person->len);
142     }
143 
144     /* Set tree parameters. */
145     if (fanout < 0 || fanout > 255) {
146         PyErr_SetString(PyExc_ValueError,
147                 "fanout must be between 0 and 255");
148         goto error;
149     }
150     self->param.fanout = (uint8_t)fanout;
151 
152     if (depth <= 0 || depth > 255) {
153         PyErr_SetString(PyExc_ValueError,
154                 "depth must be between 1 and 255");
155         goto error;
156     }
157     self->param.depth = (uint8_t)depth;
158 
159     if (leaf_size > 0xFFFFFFFFU) {
160         PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
161         goto error;
162     }
163     // NB: Simple assignment here would be incorrect on big endian platforms.
164     store32(&(self->param.leaf_length), leaf_size);
165 
166 #ifdef HAVE_BLAKE2S
167     if (node_offset > 0xFFFFFFFFFFFFULL) {
168         /* maximum 2**48 - 1 */
169          PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
170          goto error;
171      }
172     store48(&(self->param.node_offset), node_offset);
173 #else
174     // NB: Simple assignment here would be incorrect on big endian platforms.
175     store64(&(self->param.node_offset), node_offset);
176 #endif
177 
178     if (node_depth < 0 || node_depth > 255) {
179         PyErr_SetString(PyExc_ValueError,
180                 "node_depth must be between 0 and 255");
181         goto error;
182     }
183     self->param.node_depth = node_depth;
184 
185     if (inner_size < 0 || inner_size > BLAKE2B_OUTBYTES) {
186         PyErr_Format(PyExc_ValueError,
187                 "inner_size must be between 0 and is %d",
188                 BLAKE2B_OUTBYTES);
189         goto error;
190     }
191     self->param.inner_length = inner_size;
192 
193     /* Set key length. */
194     if ((key->obj != NULL) && key->len) {
195         if (key->len > BLAKE2B_KEYBYTES) {
196             PyErr_Format(PyExc_ValueError,
197                 "maximum key length is %d bytes",
198                 BLAKE2B_KEYBYTES);
199             goto error;
200         }
201         self->param.key_length = (uint8_t)key->len;
202     }
203 
204     /* Initialize hash state. */
205     if (blake2b_init_param(&self->state, &self->param) < 0) {
206         PyErr_SetString(PyExc_RuntimeError,
207                 "error initializing hash state");
208         goto error;
209     }
210 
211     /* Set last node flag (must come after initialization). */
212     self->state.last_node = last_node;
213 
214     /* Process key block if any. */
215     if (self->param.key_length) {
216         uint8_t block[BLAKE2B_BLOCKBYTES];
217         memset(block, 0, sizeof(block));
218         memcpy(block, key->buf, key->len);
219         blake2b_update(&self->state, block, sizeof(block));
220         secure_zero_memory(block, sizeof(block));
221     }
222 
223     /* Process initial data if any. */
224     if (data != NULL) {
225         GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
226 
227         if (buf.len >= HASHLIB_GIL_MINSIZE) {
228             Py_BEGIN_ALLOW_THREADS
229             blake2b_update(&self->state, buf.buf, buf.len);
230             Py_END_ALLOW_THREADS
231         } else {
232             blake2b_update(&self->state, buf.buf, buf.len);
233         }
234         PyBuffer_Release(&buf);
235     }
236 
237     return (PyObject *)self;
238 
239   error:
240     if (self != NULL) {
241         Py_DECREF(self);
242     }
243     return NULL;
244 }
245 
246 /*[clinic input]
247 _blake2.blake2b.copy
248 
249 Return a copy of the hash object.
250 [clinic start generated code]*/
251 
252 static PyObject *
_blake2_blake2b_copy_impl(BLAKE2bObject * self)253 _blake2_blake2b_copy_impl(BLAKE2bObject *self)
254 /*[clinic end generated code: output=ff6acee5f93656ae input=e383c2d199fd8a2e]*/
255 {
256     BLAKE2bObject *cpy;
257 
258     if ((cpy = new_BLAKE2bObject(Py_TYPE(self))) == NULL)
259         return NULL;
260 
261     ENTER_HASHLIB(self);
262     cpy->param = self->param;
263     cpy->state = self->state;
264     LEAVE_HASHLIB(self);
265     return (PyObject *)cpy;
266 }
267 
268 /*[clinic input]
269 _blake2.blake2b.update
270 
271     data: object
272     /
273 
274 Update this hash object's state with the provided bytes-like object.
275 [clinic start generated code]*/
276 
277 static PyObject *
_blake2_blake2b_update(BLAKE2bObject * self,PyObject * data)278 _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
279 /*[clinic end generated code: output=010dfcbe22654359 input=ffc4aa6a6a225d31]*/
280 {
281     Py_buffer buf;
282 
283     GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
284 
285     if (!self->use_mutex && buf.len >= HASHLIB_GIL_MINSIZE) {
286         self->use_mutex = true;
287     }
288     if (self->use_mutex) {
289         Py_BEGIN_ALLOW_THREADS
290         PyMutex_Lock(&self->mutex);
291         blake2b_update(&self->state, buf.buf, buf.len);
292         PyMutex_Unlock(&self->mutex);
293         Py_END_ALLOW_THREADS
294     } else {
295         blake2b_update(&self->state, buf.buf, buf.len);
296     }
297 
298     PyBuffer_Release(&buf);
299 
300     Py_RETURN_NONE;
301 }
302 
303 /*[clinic input]
304 _blake2.blake2b.digest
305 
306 Return the digest value as a bytes object.
307 [clinic start generated code]*/
308 
309 static PyObject *
_blake2_blake2b_digest_impl(BLAKE2bObject * self)310 _blake2_blake2b_digest_impl(BLAKE2bObject *self)
311 /*[clinic end generated code: output=a5864660f4bfc61a input=7d21659e9c5fff02]*/
312 {
313     uint8_t digest[BLAKE2B_OUTBYTES];
314     blake2b_state state_cpy;
315 
316     ENTER_HASHLIB(self);
317     state_cpy = self->state;
318     blake2b_final(&state_cpy, digest, self->param.digest_length);
319     LEAVE_HASHLIB(self);
320     return PyBytes_FromStringAndSize((const char *)digest,
321             self->param.digest_length);
322 }
323 
324 /*[clinic input]
325 _blake2.blake2b.hexdigest
326 
327 Return the digest value as a string of hexadecimal digits.
328 [clinic start generated code]*/
329 
330 static PyObject *
_blake2_blake2b_hexdigest_impl(BLAKE2bObject * self)331 _blake2_blake2b_hexdigest_impl(BLAKE2bObject *self)
332 /*[clinic end generated code: output=b5598a87d8794a60 input=76930f6946351f56]*/
333 {
334     uint8_t digest[BLAKE2B_OUTBYTES];
335     blake2b_state state_cpy;
336 
337     ENTER_HASHLIB(self);
338     state_cpy = self->state;
339     blake2b_final(&state_cpy, digest, self->param.digest_length);
340     LEAVE_HASHLIB(self);
341     return _Py_strhex((const char *)digest, self->param.digest_length);
342 }
343 
344 
345 static PyMethodDef py_blake2b_methods[] = {
346     _BLAKE2_BLAKE2B_COPY_METHODDEF
347     _BLAKE2_BLAKE2B_DIGEST_METHODDEF
348     _BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF
349     _BLAKE2_BLAKE2B_UPDATE_METHODDEF
350     {NULL, NULL}
351 };
352 
353 
354 
355 static PyObject *
py_blake2b_get_name(BLAKE2bObject * self,void * closure)356 py_blake2b_get_name(BLAKE2bObject *self, void *closure)
357 {
358     return PyUnicode_FromString("blake2b");
359 }
360 
361 
362 
363 static PyObject *
py_blake2b_get_block_size(BLAKE2bObject * self,void * closure)364 py_blake2b_get_block_size(BLAKE2bObject *self, void *closure)
365 {
366     return PyLong_FromLong(BLAKE2B_BLOCKBYTES);
367 }
368 
369 
370 
371 static PyObject *
py_blake2b_get_digest_size(BLAKE2bObject * self,void * closure)372 py_blake2b_get_digest_size(BLAKE2bObject *self, void *closure)
373 {
374     return PyLong_FromLong(self->param.digest_length);
375 }
376 
377 
378 static PyGetSetDef py_blake2b_getsetters[] = {
379     {"name", (getter)py_blake2b_get_name,
380         NULL, NULL, NULL},
381     {"block_size", (getter)py_blake2b_get_block_size,
382         NULL, NULL, NULL},
383     {"digest_size", (getter)py_blake2b_get_digest_size,
384         NULL, NULL, NULL},
385     {NULL}
386 };
387 
388 
389 static void
py_blake2b_dealloc(PyObject * self)390 py_blake2b_dealloc(PyObject *self)
391 {
392     BLAKE2bObject *obj = (BLAKE2bObject *)self;
393 
394     /* Try not to leave state in memory. */
395     secure_zero_memory(&obj->param, sizeof(obj->param));
396     secure_zero_memory(&obj->state, sizeof(obj->state));
397 
398     PyTypeObject *type = Py_TYPE(self);
399     PyObject_Free(self);
400     Py_DECREF(type);
401 }
402 
403 static PyType_Slot blake2b_type_slots[] = {
404     {Py_tp_dealloc, py_blake2b_dealloc},
405     {Py_tp_doc, (char *)py_blake2b_new__doc__},
406     {Py_tp_methods, py_blake2b_methods},
407     {Py_tp_getset, py_blake2b_getsetters},
408     {Py_tp_new, py_blake2b_new},
409     {0,0}
410 };
411 
412 PyType_Spec blake2b_type_spec = {
413     .name = "_blake2.blake2b",
414     .basicsize =  sizeof(BLAKE2bObject),
415     .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
416     .slots = blake2b_type_slots
417 };
418