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