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 | |
37 | extern PyType_Spec blake2b_type_spec; |
38 | |
39 | typedef 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] |
49 | module _blake2 |
50 | class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType" |
51 | [clinic start generated code]*/ |
52 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/ |
53 | |
54 | |
55 | static BLAKE2bObject * |
56 | new_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 | |
85 | Return a new BLAKE2b hash object. |
86 | [clinic start generated code]*/ |
87 | |
88 | static PyObject * |
89 | py_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 | |
243 | Return a copy of the hash object. |
244 | [clinic start generated code]*/ |
245 | |
246 | static 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 | |
268 | Update this hash object's state with the provided bytes-like object. |
269 | [clinic start generated code]*/ |
270 | |
271 | static 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 | |
299 | Return the digest value as a bytes object. |
300 | [clinic start generated code]*/ |
301 | |
302 | static 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 | |
320 | Return the digest value as a string of hexadecimal digits. |
321 | [clinic start generated code]*/ |
322 | |
323 | static 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 | |
338 | static 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 | |
348 | static PyObject * |
349 | py_blake2b_get_name(BLAKE2bObject *self, void *closure) |
350 | { |
351 | return PyUnicode_FromString("blake2b" ); |
352 | } |
353 | |
354 | |
355 | |
356 | static PyObject * |
357 | py_blake2b_get_block_size(BLAKE2bObject *self, void *closure) |
358 | { |
359 | return PyLong_FromLong(BLAKE2B_BLOCKBYTES); |
360 | } |
361 | |
362 | |
363 | |
364 | static PyObject * |
365 | py_blake2b_get_digest_size(BLAKE2bObject *self, void *closure) |
366 | { |
367 | return PyLong_FromLong(self->param.digest_length); |
368 | } |
369 | |
370 | |
371 | static 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 | |
382 | static void |
383 | py_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 | |
400 | static 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 | |
409 | PyType_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 | |