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