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