Skip to content

Commit 90532c0

Browse files
committed
All hashlib tests pass
1 parent d8b6101 commit 90532c0

File tree

2 files changed

+311
-46
lines changed

2 files changed

+311
-46
lines changed

Modules/blake2module.c

+116-45
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,9 @@ PyInit__blake2(void)
183183
typedef enum { Blake2s, Blake2b } blake2_alg;
184184

185185
static inline blake2_alg type_to_alg(PyTypeObject *type) {
186-
if (type->tp_name == blake2b_type_spec.name)
186+
if (!strcmp(type->tp_name, blake2b_type_spec.name))
187187
return Blake2b;
188-
else if (type->tp_name == blake2s_type_spec.name)
188+
else if (!strcmp(type->tp_name, blake2s_type_spec.name))
189189
return Blake2s;
190190
else
191191
Py_UNREACHABLE();
@@ -207,8 +207,9 @@ typedef struct {
207207
/*[clinic input]
208208
module _blake2
209209
class _blake2.blake2b "Blake2Object *" "&PyBlake2_BLAKE2bType"
210+
class _blake2.blake2s "Blake2Object *" "&PyBlake2_BLAKE2sType"
210211
[clinic start generated code]*/
211-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0b180617d6a53dca]*/
212+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b7526666bd18af83]*/
212213

213214

214215
static Blake2Object *
@@ -270,35 +271,13 @@ static void update(Blake2Object *self, uint8_t *buf, Py_ssize_t len) {
270271
}
271272
}
272273

273-
/*[clinic input]
274-
@classmethod
275-
_blake2.blake2b.__new__ as py_blake2b_new
276-
data: object(c_default="NULL") = b''
277-
/
278-
*
279-
digest_size: int(c_default="HACL_HASH_BLAKE2B_OUT_BYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
280-
key: Py_buffer(c_default="NULL", py_default="b''") = None
281-
salt: Py_buffer(c_default="NULL", py_default="b''") = None
282-
person: Py_buffer(c_default="NULL", py_default="b''") = None
283-
fanout: int = 1
284-
depth: int = 1
285-
leaf_size: unsigned_long = 0
286-
node_offset: unsigned_long_long = 0
287-
node_depth: int = 0
288-
inner_size: int = 0
289-
last_node: bool = False
290-
usedforsecurity: bool = True
291-
292-
Return a new BLAKE2b hash object.
293-
[clinic start generated code]*/
294-
295274
static PyObject *
296-
py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
275+
py_blake2b_or_s_new(PyTypeObject *type, PyObject *data, int digest_size,
297276
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
298277
int fanout, int depth, unsigned long leaf_size,
299278
unsigned long long node_offset, int node_depth,
300279
int inner_size, int last_node, int usedforsecurity)
301-
/*[clinic end generated code: output=32bfd8f043c6896f input=8fee2b7b11428b2d]*/
280+
302281
{
303282
Blake2Object *self = NULL;
304283
Py_buffer buf;
@@ -310,34 +289,40 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
310289

311290
self->alg = type_to_alg(type);
312291

292+
// Using Blake2b because we statically know that these are greater than the
293+
// Blake2s sizes -- this avoids a VLA.
313294
uint8_t salt_[HACL_HASH_BLAKE2B_SALT_BYTES] = { 0 };
314295
uint8_t personal_[HACL_HASH_BLAKE2B_PERSONAL_BYTES] = { 0 };
315296

316297
/* Validate digest size. */
317-
if (digest_size <= 0 || (unsigned) digest_size > HACL_HASH_BLAKE2B_OUT_BYTES) {
298+
if (digest_size <= 0 ||
299+
(unsigned) digest_size > (self->alg == Blake2b ? HACL_HASH_BLAKE2B_OUT_BYTES : HACL_HASH_BLAKE2S_OUT_BYTES))
300+
{
318301
PyErr_Format(PyExc_ValueError,
319-
"digest_size must be between 1 and %d bytes",
320-
HACL_HASH_BLAKE2B_OUT_BYTES);
302+
"digest_size for %s must be between 1 and %d bytes, here it is %d",
303+
self->alg == Blake2b ? "Blake2b" : "Blake2s",
304+
self->alg == Blake2b ? HACL_HASH_BLAKE2B_OUT_BYTES : HACL_HASH_BLAKE2S_OUT_BYTES,
305+
digest_size);
321306
goto error;
322307
}
323308

324309
/* Validate salt parameter. */
325310
if ((salt->obj != NULL) && salt->len) {
326-
if (salt->len > HACL_HASH_BLAKE2B_SALT_BYTES) {
311+
if (salt->len > (self->alg == Blake2b ? HACL_HASH_BLAKE2B_SALT_BYTES : HACL_HASH_BLAKE2S_SALT_BYTES)) {
327312
PyErr_Format(PyExc_ValueError,
328313
"maximum salt length is %d bytes",
329-
HACL_HASH_BLAKE2B_SALT_BYTES);
314+
(self->alg == Blake2b ? HACL_HASH_BLAKE2B_SALT_BYTES : HACL_HASH_BLAKE2S_SALT_BYTES));
330315
goto error;
331316
}
332317
memcpy(salt_, salt->buf, salt->len);
333318
}
334319

335320
/* Validate personalization parameter. */
336321
if ((person->obj != NULL) && person->len) {
337-
if (person->len > HACL_HASH_BLAKE2B_PERSONAL_BYTES) {
322+
if (person->len > (self->alg == Blake2b ? HACL_HASH_BLAKE2B_PERSONAL_BYTES : HACL_HASH_BLAKE2S_PERSONAL_BYTES)) {
338323
PyErr_Format(PyExc_ValueError,
339324
"maximum person length is %d bytes",
340-
HACL_HASH_BLAKE2B_PERSONAL_BYTES);
325+
(self->alg == Blake2b ? HACL_HASH_BLAKE2B_PERSONAL_BYTES : HACL_HASH_BLAKE2S_PERSONAL_BYTES));
341326
goto error;
342327
}
343328
memcpy(personal_, person->buf, person->len);
@@ -373,19 +358,20 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
373358
goto error;
374359
}
375360

376-
if (inner_size < 0 || (unsigned) inner_size > HACL_HASH_BLAKE2B_OUT_BYTES) {
361+
if (inner_size < 0 ||
362+
(unsigned) inner_size > (self->alg == Blake2b ? HACL_HASH_BLAKE2B_OUT_BYTES : HACL_HASH_BLAKE2S_OUT_BYTES)) {
377363
PyErr_Format(PyExc_ValueError,
378364
"inner_size must be between 0 and is %d",
379-
HACL_HASH_BLAKE2B_OUT_BYTES);
365+
(self->alg == Blake2b ? HACL_HASH_BLAKE2B_OUT_BYTES : HACL_HASH_BLAKE2S_OUT_BYTES));
380366
goto error;
381367
}
382368

383369
/* Set key length. */
384370
if ((key->obj != NULL) && key->len) {
385-
if (key->len > HACL_HASH_BLAKE2B_KEY_BYTES) {
371+
if (key->len > (self->alg == Blake2b ? HACL_HASH_BLAKE2B_KEY_BYTES : HACL_HASH_BLAKE2S_KEY_BYTES)) {
386372
PyErr_Format(PyExc_ValueError,
387373
"maximum key length is %d bytes",
388-
HACL_HASH_BLAKE2B_KEY_BYTES);
374+
(self->alg == Blake2b ? HACL_HASH_BLAKE2B_KEY_BYTES : HACL_HASH_BLAKE2S_KEY_BYTES));
389375
goto error;
390376
}
391377
}
@@ -440,6 +426,72 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
440426
return NULL;
441427
}
442428

429+
/*[clinic input]
430+
@classmethod
431+
_blake2.blake2b.__new__ as py_blake2b_new
432+
data: object(c_default="NULL") = b''
433+
/
434+
*
435+
digest_size: int(c_default="HACL_HASH_BLAKE2B_OUT_BYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
436+
key: Py_buffer(c_default="NULL", py_default="b''") = None
437+
salt: Py_buffer(c_default="NULL", py_default="b''") = None
438+
person: Py_buffer(c_default="NULL", py_default="b''") = None
439+
fanout: int = 1
440+
depth: int = 1
441+
leaf_size: unsigned_long = 0
442+
node_offset: unsigned_long_long = 0
443+
node_depth: int = 0
444+
inner_size: int = 0
445+
last_node: bool = False
446+
usedforsecurity: bool = True
447+
448+
Return a new BLAKE2b hash object.
449+
[clinic start generated code]*/
450+
451+
static PyObject *
452+
py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
453+
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
454+
int fanout, int depth, unsigned long leaf_size,
455+
unsigned long long node_offset, int node_depth,
456+
int inner_size, int last_node, int usedforsecurity)
457+
/*[clinic end generated code: output=32bfd8f043c6896f input=8fee2b7b11428b2d]*/
458+
{
459+
return py_blake2b_or_s_new(type, data, digest_size, key, salt, person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
460+
}
461+
462+
/*[clinic input]
463+
@classmethod
464+
_blake2.blake2s.__new__ as py_blake2s_new
465+
data: object(c_default="NULL") = b''
466+
/
467+
*
468+
digest_size: int(c_default="HACL_HASH_BLAKE2S_OUT_BYTES") = _blake2.blake2s.MAX_DIGEST_SIZE
469+
key: Py_buffer(c_default="NULL", py_default="b''") = None
470+
salt: Py_buffer(c_default="NULL", py_default="b''") = None
471+
person: Py_buffer(c_default="NULL", py_default="b''") = None
472+
fanout: int = 1
473+
depth: int = 1
474+
leaf_size: unsigned_long = 0
475+
node_offset: unsigned_long_long = 0
476+
node_depth: int = 0
477+
inner_size: int = 0
478+
last_node: bool = False
479+
usedforsecurity: bool = True
480+
481+
Return a new BLAKE2s hash object.
482+
[clinic start generated code]*/
483+
484+
static PyObject *
485+
py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
486+
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
487+
int fanout, int depth, unsigned long leaf_size,
488+
unsigned long long node_offset, int node_depth,
489+
int inner_size, int last_node, int usedforsecurity)
490+
/*[clinic end generated code: output=556181f73905c686 input=8165a11980eac7f3]*/
491+
{
492+
return py_blake2b_or_s_new(type, data, digest_size, key, salt, person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
493+
}
494+
443495
/*[clinic input]
444496
_blake2.blake2b.copy
445497
@@ -575,15 +627,15 @@ static PyMethodDef py_blake2b_methods[] = {
575627
static PyObject *
576628
py_blake2b_get_name(Blake2Object *self, void *closure)
577629
{
578-
return PyUnicode_FromString("blake2b");
630+
return PyUnicode_FromString(self->alg == Blake2b ? "blake2b" : "blake2s");
579631
}
580632

581633

582634

583635
static PyObject *
584636
py_blake2b_get_block_size(Blake2Object *self, void *closure)
585637
{
586-
return PyLong_FromLong(HACL_HASH_BLAKE2B_BLOCK_BYTES);
638+
return PyLong_FromLong(self->alg == Blake2b ? HACL_HASH_BLAKE2B_BLOCK_BYTES : HACL_HASH_BLAKE2S_BLOCK_BYTES);
587639
}
588640

589641

@@ -618,9 +670,17 @@ py_blake2b_dealloc(Blake2Object *self)
618670
{
619671
switch (self->alg) {
620672
case Blake2b:
621-
Hacl_Hash_Blake2b_free(self->blake2b_state);
673+
// This happens if we hit "goto error" in the middle of the
674+
// initialization function. We leverage the fact that tp_alloc
675+
// guarantees that the contents of the object are NULL-initialized
676+
// (see documentation for PyType_GenericAlloc) to detect this case.
677+
if (self->blake2b_state != NULL)
678+
Hacl_Hash_Blake2b_free(self->blake2b_state);
679+
break;
622680
case Blake2s:
623-
Hacl_Hash_Blake2s_free(self->blake2s_state);
681+
if (self->blake2b_state != NULL)
682+
Hacl_Hash_Blake2s_free(self->blake2s_state);
683+
break;
624684
default:
625685
Py_UNREACHABLE();
626686
}
@@ -630,7 +690,7 @@ py_blake2b_dealloc(Blake2Object *self)
630690
Py_DECREF(type);
631691
}
632692

633-
static PyType_Slot blake2bs_type_slots[] = {
693+
static PyType_Slot blake2b_type_slots[] = {
634694
{Py_tp_dealloc, py_blake2b_dealloc},
635695
{Py_tp_doc, (char *)py_blake2b_new__doc__},
636696
{Py_tp_methods, py_blake2b_methods},
@@ -639,16 +699,27 @@ static PyType_Slot blake2bs_type_slots[] = {
639699
{0,0}
640700
};
641701

702+
static PyType_Slot blake2s_type_slots[] = {
703+
{Py_tp_dealloc, py_blake2b_dealloc},
704+
{Py_tp_doc, (char *)py_blake2s_new__doc__},
705+
{Py_tp_methods, py_blake2b_methods},
706+
{Py_tp_getset, py_blake2b_getsetters},
707+
// only the constructor differs, so that it can receive a clinic-generated
708+
// default digest length suitable for blake2s
709+
{Py_tp_new, py_blake2s_new},
710+
{0,0}
711+
};
712+
642713
static PyType_Spec blake2b_type_spec = {
643714
.name = "_blake2.blake2b",
644715
.basicsize = sizeof(Blake2Object),
645716
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
646-
.slots = blake2bs_type_slots
717+
.slots = blake2b_type_slots
647718
};
648719

649720
static PyType_Spec blake2s_type_spec = {
650721
.name = "_blake2.blake2s",
651722
.basicsize = sizeof(Blake2Object),
652723
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
653-
.slots = blake2bs_type_slots
724+
.slots = blake2s_type_slots
654725
};

0 commit comments

Comments
 (0)