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 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
36extern PyType_Spec blake2s_type_spec;
37
38typedef 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]
48module _blake2
49class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
50[clinic start generated code]*/
51/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/
52
53
54static BLAKE2sObject *
55new_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
84Return a new BLAKE2s hash object.
85[clinic start generated code]*/
86
87static PyObject *
88py_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
242Return a copy of the hash object.
243[clinic start generated code]*/
244
245static PyObject *
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
267Update this hash object's state with the provided bytes-like object.
268[clinic start generated code]*/
269
270static PyObject *
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
298Return the digest value as a bytes object.
299[clinic start generated code]*/
300
301static PyObject *
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
319Return the digest value as a string of hexadecimal digits.
320[clinic start generated code]*/
321
322static PyObject *
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
337static 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
347static PyObject *
348py_blake2s_get_name(BLAKE2sObject *self, void *closure)
349{
350 return PyUnicode_FromString("blake2s");
351}
352
353
354
355static PyObject *
356py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
357{
358 return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
359}
360
361
362
363static PyObject *
364py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
365{
366 return PyLong_FromLong(self->param.digest_length);
367}
368
369
370static 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
381static void
382py_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
399static 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
408PyType_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