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