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 #include "pythread.h"
19
20 #include "../hashlib.h"
21 #include "blake2ns.h"
22
23 #define HAVE_BLAKE2S 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/blake2s.c"
33 #else
34 #include "impl/blake2s-ref.c"
35 #endif
36
37
38 extern PyTypeObject PyBlake2_BLAKE2sType;
39
40 typedef struct {
41 PyObject_HEAD
42 blake2s_param param;
43 blake2s_state state;
44 PyThread_type_lock lock;
45 } BLAKE2sObject;
46
47 #include "clinic/blake2s_impl.c.h"
48
49 /*[clinic input]
50 module _blake2
51 class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
52 [clinic start generated code]*/
53 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/
54
55
56 static BLAKE2sObject *
new_BLAKE2sObject(PyTypeObject * type)57 new_BLAKE2sObject(PyTypeObject *type)
58 {
59 BLAKE2sObject *self;
60 self = (BLAKE2sObject *)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.blake2s.__new__ as py_blake2s_new
70 data: object(c_default="NULL") = b''
71 /
72 *
73 digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2.blake2s.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: unsigned_long = 0
80 node_offset: unsigned_long_long = 0
81 node_depth: int = 0
82 inner_size: int = 0
83 last_node: bool = False
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)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)
94 /*[clinic end generated code: output=b95806be0514dcf7 input=641c0509debf714d]*/
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