Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Modules/_blake2/blake2s_impl.c
12 views
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
#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
new_BLAKE2sObject(PyTypeObject *type)
59
{
60
BLAKE2sObject *self;
61
self = (BLAKE2sObject *)type->tp_alloc(type, 0);
62
if (self != NULL) {
63
self->lock = NULL;
64
}
65
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
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
BLAKE2sObject *self = NULL;
99
Py_buffer buf;
100
101
self = new_BLAKE2sObject(type);
102
if (self == NULL) {
103
goto error;
104
}
105
106
/* Zero parameter block. */
107
memset(&self->param, 0, sizeof(self->param));
108
109
/* Set digest size. */
110
if (digest_size <= 0 || digest_size > BLAKE2S_OUTBYTES) {
111
PyErr_Format(PyExc_ValueError,
112
"digest_size must be between 1 and %d bytes",
113
BLAKE2S_OUTBYTES);
114
goto error;
115
}
116
self->param.digest_length = digest_size;
117
118
/* Set salt parameter. */
119
if ((salt->obj != NULL) && salt->len) {
120
if (salt->len > BLAKE2S_SALTBYTES) {
121
PyErr_Format(PyExc_ValueError,
122
"maximum salt length is %d bytes",
123
BLAKE2S_SALTBYTES);
124
goto error;
125
}
126
memcpy(self->param.salt, salt->buf, salt->len);
127
}
128
129
/* Set personalization parameter. */
130
if ((person->obj != NULL) && person->len) {
131
if (person->len > BLAKE2S_PERSONALBYTES) {
132
PyErr_Format(PyExc_ValueError,
133
"maximum person length is %d bytes",
134
BLAKE2S_PERSONALBYTES);
135
goto error;
136
}
137
memcpy(self->param.personal, person->buf, person->len);
138
}
139
140
/* Set tree parameters. */
141
if (fanout < 0 || fanout > 255) {
142
PyErr_SetString(PyExc_ValueError,
143
"fanout must be between 0 and 255");
144
goto error;
145
}
146
self->param.fanout = (uint8_t)fanout;
147
148
if (depth <= 0 || depth > 255) {
149
PyErr_SetString(PyExc_ValueError,
150
"depth must be between 1 and 255");
151
goto error;
152
}
153
self->param.depth = (uint8_t)depth;
154
155
if (leaf_size > 0xFFFFFFFFU) {
156
PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
157
goto error;
158
}
159
// NB: Simple assignment here would be incorrect on big endian platforms.
160
store32(&(self->param.leaf_length), leaf_size);
161
162
#ifdef HAVE_BLAKE2S
163
if (node_offset > 0xFFFFFFFFFFFFULL) {
164
/* maximum 2**48 - 1 */
165
PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
166
goto error;
167
}
168
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
if (node_depth < 0 || node_depth > 255) {
175
PyErr_SetString(PyExc_ValueError,
176
"node_depth must be between 0 and 255");
177
goto error;
178
}
179
self->param.node_depth = node_depth;
180
181
if (inner_size < 0 || inner_size > BLAKE2S_OUTBYTES) {
182
PyErr_Format(PyExc_ValueError,
183
"inner_size must be between 0 and is %d",
184
BLAKE2S_OUTBYTES);
185
goto error;
186
}
187
self->param.inner_length = inner_size;
188
189
/* Set key length. */
190
if ((key->obj != NULL) && key->len) {
191
if (key->len > BLAKE2S_KEYBYTES) {
192
PyErr_Format(PyExc_ValueError,
193
"maximum key length is %d bytes",
194
BLAKE2S_KEYBYTES);
195
goto error;
196
}
197
self->param.key_length = (uint8_t)key->len;
198
}
199
200
/* Initialize hash state. */
201
if (blake2s_init_param(&self->state, &self->param) < 0) {
202
PyErr_SetString(PyExc_RuntimeError,
203
"error initializing hash state");
204
goto error;
205
}
206
207
/* Set last node flag (must come after initialization). */
208
self->state.last_node = last_node;
209
210
/* Process key block if any. */
211
if (self->param.key_length) {
212
uint8_t block[BLAKE2S_BLOCKBYTES];
213
memset(block, 0, sizeof(block));
214
memcpy(block, key->buf, key->len);
215
blake2s_update(&self->state, block, sizeof(block));
216
secure_zero_memory(block, sizeof(block));
217
}
218
219
/* Process initial data if any. */
220
if (data != NULL) {
221
GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
222
223
if (buf.len >= HASHLIB_GIL_MINSIZE) {
224
Py_BEGIN_ALLOW_THREADS
225
blake2s_update(&self->state, buf.buf, buf.len);
226
Py_END_ALLOW_THREADS
227
} else {
228
blake2s_update(&self->state, buf.buf, buf.len);
229
}
230
PyBuffer_Release(&buf);
231
}
232
233
return (PyObject *)self;
234
235
error:
236
if (self != NULL) {
237
Py_DECREF(self);
238
}
239
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
_blake2_blake2s_copy_impl(BLAKE2sObject *self)
250
/*[clinic end generated code: output=5b90131c4eae275e input=0b9d44942f0fe4b2]*/
251
{
252
BLAKE2sObject *cpy;
253
254
if ((cpy = new_BLAKE2sObject(Py_TYPE(self))) == NULL)
255
return NULL;
256
257
ENTER_HASHLIB(self);
258
cpy->param = self->param;
259
cpy->state = self->state;
260
LEAVE_HASHLIB(self);
261
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
_blake2_blake2s_update(BLAKE2sObject *self, PyObject *data)
275
/*[clinic end generated code: output=757dc087fec37815 input=97500db2f9de4aaa]*/
276
{
277
Py_buffer buf;
278
279
GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
280
281
if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
282
self->lock = PyThread_allocate_lock();
283
284
if (self->lock != NULL) {
285
Py_BEGIN_ALLOW_THREADS
286
PyThread_acquire_lock(self->lock, 1);
287
blake2s_update(&self->state, buf.buf, buf.len);
288
PyThread_release_lock(self->lock);
289
Py_END_ALLOW_THREADS
290
} else {
291
blake2s_update(&self->state, buf.buf, buf.len);
292
}
293
PyBuffer_Release(&buf);
294
295
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
_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
ENTER_HASHLIB(self);
312
state_cpy = self->state;
313
blake2s_final(&state_cpy, digest, self->param.digest_length);
314
LEAVE_HASHLIB(self);
315
return PyBytes_FromStringAndSize((const char *)digest,
316
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
_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
ENTER_HASHLIB(self);
333
state_cpy = self->state;
334
blake2s_final(&state_cpy, digest, self->param.digest_length);
335
LEAVE_HASHLIB(self);
336
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
py_blake2s_get_name(BLAKE2sObject *self, void *closure)
352
{
353
return PyUnicode_FromString("blake2s");
354
}
355
356
357
358
static PyObject *
359
py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
360
{
361
return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
362
}
363
364
365
366
static PyObject *
367
py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
368
{
369
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
py_blake2s_dealloc(PyObject *self)
386
{
387
BLAKE2sObject *obj = (BLAKE2sObject *)self;
388
389
/* Try not to leave state in memory. */
390
secure_zero_memory(&obj->param, sizeof(obj->param));
391
secure_zero_memory(&obj->state, sizeof(obj->state));
392
if (obj->lock) {
393
PyThread_free_lock(obj->lock);
394
obj->lock = NULL;
395
}
396
397
PyTypeObject *type = Py_TYPE(self);
398
PyObject_Free(self);
399
Py_DECREF(type);
400
}
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
};
417
418