1/*
2 * Written in 2013 by Dmitry Chestnykh <[email protected]>
3 * Modified for CPython by Christian Heimes <[email protected]>
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
19#include "../hashlib.h"
20#include "blake2ns.h"
21
22#define HAVE_BLAKE2B 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/blake2b.c"
32#else
33#include "impl/blake2b-ref.c"
34#endif
35
36
37extern PyType_Spec blake2b_type_spec;
38
39typedef struct {
40 PyObject_HEAD
41 blake2b_param param;
42 blake2b_state state;
43 PyThread_type_lock lock;
44} BLAKE2bObject;
45
46#include "clinic/blake2b_impl.c.h"
47
48/*[clinic input]
49module _blake2
50class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType"
51[clinic start generated code]*/
52/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/
53
54
55static BLAKE2bObject *
56new_BLAKE2bObject(PyTypeObject *type)
57{
58 BLAKE2bObject *self;
59 self = (BLAKE2bObject *)type->tp_alloc(type, 0);
60 if (self != NULL) {
61 self->lock = NULL;
62 }
63 return self;
64}
65
66/*[clinic input]
67@classmethod
68_blake2.blake2b.__new__ as py_blake2b_new
69 data: object(c_default="NULL") = b''
70 /
71 *
72 digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
73 key: Py_buffer(c_default="NULL", py_default="b''") = None
74 salt: Py_buffer(c_default="NULL", py_default="b''") = None
75 person: Py_buffer(c_default="NULL", py_default="b''") = None
76 fanout: int = 1
77 depth: int = 1
78 leaf_size: unsigned_long = 0
79 node_offset: unsigned_long_long = 0
80 node_depth: int = 0
81 inner_size: int = 0
82 last_node: bool = False
83 usedforsecurity: bool = True
84
85Return a new BLAKE2b hash object.
86[clinic start generated code]*/
87
88static PyObject *
89py_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, unsigned long leaf_size,
92 unsigned long long node_offset, int node_depth,
93 int inner_size, int last_node, int usedforsecurity)
94/*[clinic end generated code: output=32bfd8f043c6896f input=b947312abff46977]*/
95{
96 BLAKE2bObject *self = NULL;
97 Py_buffer buf;
98
99 self = new_BLAKE2bObject(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 > BLAKE2B_OUTBYTES) {
109 PyErr_Format(PyExc_ValueError,
110 "digest_size must be between 1 and %d bytes",
111 BLAKE2B_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 > BLAKE2B_SALTBYTES) {
119 PyErr_Format(PyExc_ValueError,
120 "maximum salt length is %d bytes",
121 BLAKE2B_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 > BLAKE2B_PERSONALBYTES) {
130 PyErr_Format(PyExc_ValueError,
131 "maximum person length is %d bytes",
132 BLAKE2B_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 > BLAKE2B_OUTBYTES) {
180 PyErr_Format(PyExc_ValueError,
181 "inner_size must be between 0 and is %d",
182 BLAKE2B_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 > BLAKE2B_KEYBYTES) {
190 PyErr_Format(PyExc_ValueError,
191 "maximum key length is %d bytes",
192 BLAKE2B_KEYBYTES);
193 goto error;
194 }
195 self->param.key_length = (uint8_t)key->len;
196 }
197
198 /* Initialize hash state. */
199 if (blake2b_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[BLAKE2B_BLOCKBYTES];
211 memset(block, 0, sizeof(block));
212 memcpy(block, key->buf, key->len);
213 blake2b_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 blake2b_update(&self->state, buf.buf, buf.len);
224 Py_END_ALLOW_THREADS
225 } else {
226 blake2b_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.blake2b.copy
242
243Return a copy of the hash object.
244[clinic start generated code]*/
245
246static PyObject *
247_blake2_blake2b_copy_impl(BLAKE2bObject *self)
248/*[clinic end generated code: output=ff6acee5f93656ae input=e383c2d199fd8a2e]*/
249{
250 BLAKE2bObject *cpy;
251
252 if ((cpy = new_BLAKE2bObject(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.blake2b.update
264
265 data: object
266 /
267
268Update this hash object's state with the provided bytes-like object.
269[clinic start generated code]*/
270
271static PyObject *
272_blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
273/*[clinic end generated code: output=010dfcbe22654359 input=ffc4aa6a6a225d31]*/
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 blake2b_update(&self->state, buf.buf, buf.len);
286 PyThread_release_lock(self->lock);
287 Py_END_ALLOW_THREADS
288 } else {
289 blake2b_update(&self->state, buf.buf, buf.len);
290 }
291 PyBuffer_Release(&buf);
292
293 Py_RETURN_NONE;
294}
295
296/*[clinic input]
297_blake2.blake2b.digest
298
299Return the digest value as a bytes object.
300[clinic start generated code]*/
301
302static PyObject *
303_blake2_blake2b_digest_impl(BLAKE2bObject *self)
304/*[clinic end generated code: output=a5864660f4bfc61a input=7d21659e9c5fff02]*/
305{
306 uint8_t digest[BLAKE2B_OUTBYTES];
307 blake2b_state state_cpy;
308
309 ENTER_HASHLIB(self);
310 state_cpy = self->state;
311 blake2b_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.blake2b.hexdigest
319
320Return the digest value as a string of hexadecimal digits.
321[clinic start generated code]*/
322
323static PyObject *
324_blake2_blake2b_hexdigest_impl(BLAKE2bObject *self)
325/*[clinic end generated code: output=b5598a87d8794a60 input=76930f6946351f56]*/
326{
327 uint8_t digest[BLAKE2B_OUTBYTES];
328 blake2b_state state_cpy;
329
330 ENTER_HASHLIB(self);
331 state_cpy = self->state;
332 blake2b_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
338static PyMethodDef py_blake2b_methods[] = {
339 _BLAKE2_BLAKE2B_COPY_METHODDEF
340 _BLAKE2_BLAKE2B_DIGEST_METHODDEF
341 _BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF
342 _BLAKE2_BLAKE2B_UPDATE_METHODDEF
343 {NULL, NULL}
344};
345
346
347
348static PyObject *
349py_blake2b_get_name(BLAKE2bObject *self, void *closure)
350{
351 return PyUnicode_FromString("blake2b");
352}
353
354
355
356static PyObject *
357py_blake2b_get_block_size(BLAKE2bObject *self, void *closure)
358{
359 return PyLong_FromLong(BLAKE2B_BLOCKBYTES);
360}
361
362
363
364static PyObject *
365py_blake2b_get_digest_size(BLAKE2bObject *self, void *closure)
366{
367 return PyLong_FromLong(self->param.digest_length);
368}
369
370
371static PyGetSetDef py_blake2b_getsetters[] = {
372 {"name", (getter)py_blake2b_get_name,
373 NULL, NULL, NULL},
374 {"block_size", (getter)py_blake2b_get_block_size,
375 NULL, NULL, NULL},
376 {"digest_size", (getter)py_blake2b_get_digest_size,
377 NULL, NULL, NULL},
378 {NULL}
379};
380
381
382static void
383py_blake2b_dealloc(PyObject *self)
384{
385 BLAKE2bObject *obj = (BLAKE2bObject *)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
395 PyTypeObject *type = Py_TYPE(self);
396 PyObject_Free(self);
397 Py_DECREF(type);
398}
399
400static PyType_Slot blake2b_type_slots[] = {
401 {Py_tp_dealloc, py_blake2b_dealloc},
402 {Py_tp_doc, (char *)py_blake2b_new__doc__},
403 {Py_tp_methods, py_blake2b_methods},
404 {Py_tp_getset, py_blake2b_getsetters},
405 {Py_tp_new, py_blake2b_new},
406 {0,0}
407};
408
409PyType_Spec blake2b_type_spec = {
410 .name = "_blake2.blake2b",
411 .basicsize = sizeof(BLAKE2bObject),
412 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
413 .slots = blake2b_type_slots
414};
415