Branch data Line data Source code
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 : : #ifndef Py_BUILD_CORE_BUILTIN
17 : : # define Py_BUILD_CORE_MODULE 1
18 : : #endif
19 : :
20 : : #include "Python.h"
21 : : #include "pycore_strhex.h" // _Py_strhex()
22 : :
23 : : #include "../hashlib.h"
24 : : #include "blake2module.h"
25 : :
26 : : #ifndef HAVE_LIBB2
27 : : /* pure SSE2 implementation is very slow, so only use the more optimized SSSE3+
28 : : * https://bugs.python.org/issue31834 */
29 : : #if defined(__SSSE3__) || defined(__SSE4_1__) || defined(__AVX__) || defined(__XOP__)
30 : : #include "impl/blake2s.c"
31 : : #else
32 : : #include "impl/blake2s-ref.c"
33 : : #endif
34 : : #endif // !HAVE_LIBB2
35 : :
36 : : #define HAVE_BLAKE2S 1
37 : :
38 : : extern PyType_Spec blake2s_type_spec;
39 : :
40 : :
41 : : typedef struct {
42 : : PyObject_HEAD
43 : : blake2s_param param;
44 : : blake2s_state state;
45 : : PyThread_type_lock lock;
46 : : } BLAKE2sObject;
47 : :
48 : : #include "clinic/blake2s_impl.c.h"
49 : :
50 : : /*[clinic input]
51 : : module _blake2
52 : : class _blake2.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
53 : : [clinic start generated code]*/
54 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b79d7ffe07286ce]*/
55 : :
56 : :
57 : : static BLAKE2sObject *
58 : 1528 : new_BLAKE2sObject(PyTypeObject *type)
59 : : {
60 : : BLAKE2sObject *self;
61 : 1528 : self = (BLAKE2sObject *)type->tp_alloc(type, 0);
62 [ + - ]: 1528 : if (self != NULL) {
63 : 1528 : self->lock = NULL;
64 : : }
65 : 1528 : return self;
66 : : }
67 : :
68 : : /*[clinic input]
69 : : @classmethod
70 : : _blake2.blake2s.__new__ as py_blake2s_new
71 : : data: object(c_default="NULL") = b''
72 : : /
73 : : *
74 : : digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2.blake2s.MAX_DIGEST_SIZE
75 : : key: Py_buffer(c_default="NULL", py_default="b''") = None
76 : : salt: Py_buffer(c_default="NULL", py_default="b''") = None
77 : : person: Py_buffer(c_default="NULL", py_default="b''") = None
78 : : fanout: int = 1
79 : : depth: int = 1
80 : : leaf_size: unsigned_long = 0
81 : : node_offset: unsigned_long_long = 0
82 : : node_depth: int = 0
83 : : inner_size: int = 0
84 : : last_node: bool = False
85 : : usedforsecurity: bool = True
86 : :
87 : : Return a new BLAKE2s hash object.
88 : : [clinic start generated code]*/
89 : :
90 : : static PyObject *
91 : 1526 : py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
92 : : Py_buffer *key, Py_buffer *salt, Py_buffer *person,
93 : : int fanout, int depth, unsigned long leaf_size,
94 : : unsigned long long node_offset, int node_depth,
95 : : int inner_size, int last_node, int usedforsecurity)
96 : : /*[clinic end generated code: output=556181f73905c686 input=4dda87723f23abb0]*/
97 : : {
98 : 1526 : BLAKE2sObject *self = NULL;
99 : : Py_buffer buf;
100 : :
101 : 1526 : self = new_BLAKE2sObject(type);
102 [ - + ]: 1526 : if (self == NULL) {
103 : 0 : goto error;
104 : : }
105 : :
106 : : /* Zero parameter block. */
107 : 1526 : memset(&self->param, 0, sizeof(self->param));
108 : :
109 : : /* Set digest size. */
110 [ + + + + ]: 1526 : if (digest_size <= 0 || digest_size > BLAKE2S_OUTBYTES) {
111 : 3 : PyErr_Format(PyExc_ValueError,
112 : : "digest_size must be between 1 and %d bytes",
113 : : BLAKE2S_OUTBYTES);
114 : 3 : goto error;
115 : : }
116 : 1523 : self->param.digest_length = digest_size;
117 : :
118 : : /* Set salt parameter. */
119 [ + + + + ]: 1523 : if ((salt->obj != NULL) && salt->len) {
120 [ + + ]: 11 : if (salt->len > BLAKE2S_SALTBYTES) {
121 : 1 : PyErr_Format(PyExc_ValueError,
122 : : "maximum salt length is %d bytes",
123 : : BLAKE2S_SALTBYTES);
124 : 1 : goto error;
125 : : }
126 : 10 : memcpy(self->param.salt, salt->buf, salt->len);
127 : : }
128 : :
129 : : /* Set personalization parameter. */
130 [ + + + + ]: 1522 : if ((person->obj != NULL) && person->len) {
131 [ + + ]: 11 : if (person->len > BLAKE2S_PERSONALBYTES) {
132 : 1 : PyErr_Format(PyExc_ValueError,
133 : : "maximum person length is %d bytes",
134 : : BLAKE2S_PERSONALBYTES);
135 : 1 : goto error;
136 : : }
137 : 10 : memcpy(self->param.personal, person->buf, person->len);
138 : : }
139 : :
140 : : /* Set tree parameters. */
141 [ + + + + ]: 1521 : if (fanout < 0 || fanout > 255) {
142 : 2 : PyErr_SetString(PyExc_ValueError,
143 : : "fanout must be between 0 and 255");
144 : 2 : goto error;
145 : : }
146 : 1519 : self->param.fanout = (uint8_t)fanout;
147 : :
148 [ + + + + ]: 1519 : if (depth <= 0 || depth > 255) {
149 : 3 : PyErr_SetString(PyExc_ValueError,
150 : : "depth must be between 1 and 255");
151 : 3 : goto error;
152 : : }
153 : 1516 : self->param.depth = (uint8_t)depth;
154 : :
155 [ + + ]: 1516 : if (leaf_size > 0xFFFFFFFFU) {
156 : 1 : PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
157 : 1 : goto error;
158 : : }
159 : : // NB: Simple assignment here would be incorrect on big endian platforms.
160 : 1515 : store32(&(self->param.leaf_length), leaf_size);
161 : :
162 : : #ifdef HAVE_BLAKE2S
163 [ + + ]: 1515 : if (node_offset > 0xFFFFFFFFFFFFULL) {
164 : : /* maximum 2**48 - 1 */
165 : 1 : PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
166 : 1 : goto error;
167 : : }
168 : 1514 : store48(&(self->param.node_offset), node_offset);
169 : : #else
170 : : // NB: Simple assignment here would be incorrect on big endian platforms.
171 : : store64(&(self->param.node_offset), node_offset);
172 : : #endif
173 : :
174 [ + + + + ]: 1514 : if (node_depth < 0 || node_depth > 255) {
175 : 2 : PyErr_SetString(PyExc_ValueError,
176 : : "node_depth must be between 0 and 255");
177 : 2 : goto error;
178 : : }
179 : 1512 : self->param.node_depth = node_depth;
180 : :
181 [ + + + + ]: 1512 : if (inner_size < 0 || inner_size > BLAKE2S_OUTBYTES) {
182 : 2 : PyErr_Format(PyExc_ValueError,
183 : : "inner_size must be between 0 and is %d",
184 : : BLAKE2S_OUTBYTES);
185 : 2 : goto error;
186 : : }
187 : 1510 : self->param.inner_length = inner_size;
188 : :
189 : : /* Set key length. */
190 [ + + + + ]: 1510 : if ((key->obj != NULL) && key->len) {
191 [ + + ]: 571 : if (key->len > BLAKE2S_KEYBYTES) {
192 : 1 : PyErr_Format(PyExc_ValueError,
193 : : "maximum key length is %d bytes",
194 : : BLAKE2S_KEYBYTES);
195 : 1 : goto error;
196 : : }
197 : 570 : self->param.key_length = (uint8_t)key->len;
198 : : }
199 : :
200 : : /* Initialize hash state. */
201 [ - + ]: 1509 : if (blake2s_init_param(&self->state, &self->param) < 0) {
202 : 0 : PyErr_SetString(PyExc_RuntimeError,
203 : : "error initializing hash state");
204 : 0 : goto error;
205 : : }
206 : :
207 : : /* Set last node flag (must come after initialization). */
208 : 1509 : self->state.last_node = last_node;
209 : :
210 : : /* Process key block if any. */
211 [ + + ]: 1509 : if (self->param.key_length) {
212 : : uint8_t block[BLAKE2S_BLOCKBYTES];
213 : 570 : memset(block, 0, sizeof(block));
214 : 570 : memcpy(block, key->buf, key->len);
215 : 570 : blake2s_update(&self->state, block, sizeof(block));
216 : 570 : secure_zero_memory(block, sizeof(block));
217 : : }
218 : :
219 : : /* Process initial data if any. */
220 [ + + ]: 1509 : if (data != NULL) {
221 [ + + - + : 605 : GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
- + - + ]
222 : :
223 [ + + ]: 602 : if (buf.len >= HASHLIB_GIL_MINSIZE) {
224 : 4 : Py_BEGIN_ALLOW_THREADS
225 : 4 : blake2s_update(&self->state, buf.buf, buf.len);
226 : 4 : Py_END_ALLOW_THREADS
227 : : } else {
228 : 598 : blake2s_update(&self->state, buf.buf, buf.len);
229 : : }
230 : 602 : PyBuffer_Release(&buf);
231 : : }
232 : :
233 : 1506 : return (PyObject *)self;
234 : :
235 : 20 : error:
236 [ + - ]: 20 : if (self != NULL) {
237 : 20 : Py_DECREF(self);
238 : : }
239 : 20 : return NULL;
240 : : }
241 : :
242 : : /*[clinic input]
243 : : _blake2.blake2s.copy
244 : :
245 : : Return a copy of the hash object.
246 : : [clinic start generated code]*/
247 : :
248 : : static PyObject *
249 : 2 : _blake2_blake2s_copy_impl(BLAKE2sObject *self)
250 : : /*[clinic end generated code: output=5b90131c4eae275e input=0b9d44942f0fe4b2]*/
251 : : {
252 : : BLAKE2sObject *cpy;
253 : :
254 [ - + ]: 2 : if ((cpy = new_BLAKE2sObject(Py_TYPE(self))) == NULL)
255 : 0 : return NULL;
256 : :
257 [ - + - - ]: 2 : ENTER_HASHLIB(self);
258 : 2 : cpy->param = self->param;
259 : 2 : cpy->state = self->state;
260 [ - + ]: 2 : LEAVE_HASHLIB(self);
261 : 2 : return (PyObject *)cpy;
262 : : }
263 : :
264 : : /*[clinic input]
265 : : _blake2.blake2s.update
266 : :
267 : : data: object
268 : : /
269 : :
270 : : Update this hash object's state with the provided bytes-like object.
271 : : [clinic start generated code]*/
272 : :
273 : : static PyObject *
274 : 77 : _blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
275 : : /*[clinic end generated code: output=757dc087fec37815 input=97500db2f9de4aaa]*/
276 : : {
277 : : Py_buffer buf;
278 : :
279 [ - + - + : 77 : GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
- + - + ]
280 : :
281 [ + + + + ]: 77 : if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
282 : 8 : self->lock = PyThread_allocate_lock();
283 : :
284 [ + + ]: 77 : if (self->lock != NULL) {
285 : 10 : Py_BEGIN_ALLOW_THREADS
286 : 10 : PyThread_acquire_lock(self->lock, 1);
287 : 10 : blake2s_update(&self->state, buf.buf, buf.len);
288 : 10 : PyThread_release_lock(self->lock);
289 : 10 : Py_END_ALLOW_THREADS
290 : : } else {
291 : 67 : blake2s_update(&self->state, buf.buf, buf.len);
292 : : }
293 : 77 : PyBuffer_Release(&buf);
294 : :
295 : 77 : Py_RETURN_NONE;
296 : : }
297 : :
298 : : /*[clinic input]
299 : : _blake2.blake2s.digest
300 : :
301 : : Return the digest value as a bytes object.
302 : : [clinic start generated code]*/
303 : :
304 : : static PyObject *
305 : 588 : _blake2_blake2s_digest_impl(BLAKE2sObject *self)
306 : : /*[clinic end generated code: output=40c566ca4bc6bc51 input=f41e0b8d6d937454]*/
307 : : {
308 : : uint8_t digest[BLAKE2S_OUTBYTES];
309 : : blake2s_state state_cpy;
310 : :
311 [ + + - + ]: 588 : ENTER_HASHLIB(self);
312 : 588 : state_cpy = self->state;
313 : 588 : blake2s_final(&state_cpy, digest, self->param.digest_length);
314 [ + + ]: 588 : LEAVE_HASHLIB(self);
315 : 1176 : return PyBytes_FromStringAndSize((const char *)digest,
316 : 588 : self->param.digest_length);
317 : : }
318 : :
319 : : /*[clinic input]
320 : : _blake2.blake2s.hexdigest
321 : :
322 : : Return the digest value as a string of hexadecimal digits.
323 : : [clinic start generated code]*/
324 : :
325 : : static PyObject *
326 : 539 : _blake2_blake2s_hexdigest_impl(BLAKE2sObject *self)
327 : : /*[clinic end generated code: output=15153eb5e59c52eb input=c77a1321567e8952]*/
328 : : {
329 : : uint8_t digest[BLAKE2S_OUTBYTES];
330 : : blake2s_state state_cpy;
331 : :
332 [ - + - - ]: 539 : ENTER_HASHLIB(self);
333 : 539 : state_cpy = self->state;
334 : 539 : blake2s_final(&state_cpy, digest, self->param.digest_length);
335 [ - + ]: 539 : LEAVE_HASHLIB(self);
336 : 539 : return _Py_strhex((const char *)digest, self->param.digest_length);
337 : : }
338 : :
339 : :
340 : : static PyMethodDef py_blake2s_methods[] = {
341 : : _BLAKE2_BLAKE2S_COPY_METHODDEF
342 : : _BLAKE2_BLAKE2S_DIGEST_METHODDEF
343 : : _BLAKE2_BLAKE2S_HEXDIGEST_METHODDEF
344 : : _BLAKE2_BLAKE2S_UPDATE_METHODDEF
345 : : {NULL, NULL}
346 : : };
347 : :
348 : :
349 : :
350 : : static PyObject *
351 : 22 : py_blake2s_get_name(BLAKE2sObject *self, void *closure)
352 : : {
353 : 22 : return PyUnicode_FromString("blake2s");
354 : : }
355 : :
356 : :
357 : :
358 : : static PyObject *
359 : 2 : py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
360 : : {
361 : 2 : return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
362 : : }
363 : :
364 : :
365 : :
366 : : static PyObject *
367 : 520 : py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
368 : : {
369 : 520 : return PyLong_FromLong(self->param.digest_length);
370 : : }
371 : :
372 : :
373 : : static PyGetSetDef py_blake2s_getsetters[] = {
374 : : {"name", (getter)py_blake2s_get_name,
375 : : NULL, NULL, NULL},
376 : : {"block_size", (getter)py_blake2s_get_block_size,
377 : : NULL, NULL, NULL},
378 : : {"digest_size", (getter)py_blake2s_get_digest_size,
379 : : NULL, NULL, NULL},
380 : : {NULL}
381 : : };
382 : :
383 : :
384 : : static void
385 : 1528 : py_blake2s_dealloc(PyObject *self)
386 : : {
387 : 1528 : BLAKE2sObject *obj = (BLAKE2sObject *)self;
388 : :
389 : : /* Try not to leave state in memory. */
390 : 1528 : secure_zero_memory(&obj->param, sizeof(obj->param));
391 : 1528 : secure_zero_memory(&obj->state, sizeof(obj->state));
392 [ + + ]: 1528 : if (obj->lock) {
393 : 8 : PyThread_free_lock(obj->lock);
394 : 8 : obj->lock = NULL;
395 : : }
396 : :
397 : 1528 : PyTypeObject *type = Py_TYPE(self);
398 : 1528 : PyObject_Free(self);
399 : 1528 : Py_DECREF(type);
400 : 1528 : }
401 : :
402 : : static PyType_Slot blake2s_type_slots[] = {
403 : : {Py_tp_dealloc, py_blake2s_dealloc},
404 : : {Py_tp_doc, (char *)py_blake2s_new__doc__},
405 : : {Py_tp_methods, py_blake2s_methods},
406 : : {Py_tp_getset, py_blake2s_getsetters},
407 : : {Py_tp_new, py_blake2s_new},
408 : : {0,0}
409 : : };
410 : :
411 : : PyType_Spec blake2s_type_spec = {
412 : : .name = "_blake2.blake2s",
413 : : .basicsize = sizeof(BLAKE2sObject),
414 : : .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
415 : : .slots = blake2s_type_slots
416 : : };
|