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