Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:mod:`hashlib`: Fix data races when accessing
:attr:`~hashlib.hash.digest_size` and :attr:`~hashlib.hash.block_size` on
SHA-3 objects. Patch by Bénédikt Tran.
34 changes: 20 additions & 14 deletions Modules/sha3module.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ sha3_get_state(PyObject *module)
typedef struct {
HASHLIB_OBJECT_HEAD
Hacl_Hash_SHA3_state_t *hash_state;
// HACL* update functions entirely replace the state, which can lead
// to races on the free-threaded build. Since the kind of hash is static,
// we can store its corresponding metadata once.
uint32_t digest_size;
uint32_t block_size;
int is_shake;
} SHA3object;

#define _SHA3object_CAST(op) ((SHA3object *)(op))
Expand Down Expand Up @@ -96,7 +102,7 @@ newSHA3object(PyTypeObject *type)
return NULL;
}
HASHLIB_INIT_MUTEX(newobj);

newobj->digest_size = newobj->block_size = 0;
PyObject_GC_Track(newobj);
return newobj;
}
Expand Down Expand Up @@ -179,6 +185,11 @@ py_sha3_new_impl(PyTypeObject *type, PyObject *data_obj, int usedforsecurity,
goto error;
}

// set the metadata once we know that the state is valid
int is_shake = Hacl_Hash_SHA3_is_shake(self->hash_state);
self->digest_size = is_shake ? 0 : Hacl_Hash_SHA3_hash_len(self->hash_state);
self->block_size = Hacl_Hash_SHA3_block_len(self->hash_state);

if (data) {
GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
/* Do not use self->mutex here as this is the constructor
Expand Down Expand Up @@ -253,6 +264,8 @@ _sha3_sha3_224_copy_impl(SHA3object *self, PyTypeObject *cls)
Py_DECREF(newobj);
return PyErr_NoMemory();
}
newobj->digest_size = self->digest_size;
newobj->block_size = self->block_size;
return (PyObject *)newobj;
}

Expand All @@ -273,8 +286,7 @@ _sha3_sha3_224_digest_impl(SHA3object *self)
HASHLIB_ACQUIRE_LOCK(self);
(void)Hacl_Hash_SHA3_digest(self->hash_state, digest);
HASHLIB_RELEASE_LOCK(self);
return PyBytes_FromStringAndSize((const char *)digest,
Hacl_Hash_SHA3_hash_len(self->hash_state));
return PyBytes_FromStringAndSize((const char *)digest, self->digest_size);
}


Expand All @@ -292,8 +304,7 @@ _sha3_sha3_224_hexdigest_impl(SHA3object *self)
HASHLIB_ACQUIRE_LOCK(self);
(void)Hacl_Hash_SHA3_digest(self->hash_state, digest);
HASHLIB_RELEASE_LOCK(self);
return _Py_strhex((const char *)digest,
Hacl_Hash_SHA3_hash_len(self->hash_state));
return _Py_strhex((const char *)digest, self->digest_size);
}


Expand Down Expand Up @@ -334,8 +345,7 @@ static PyObject *
SHA3_get_block_size(PyObject *op, void *Py_UNUSED(closure))
{
SHA3object *self = _SHA3object_CAST(op);
uint32_t rate = Hacl_Hash_SHA3_block_len(self->hash_state);
return PyLong_FromLong(rate);
return PyLong_FromLong(self->block_size);
}


Expand Down Expand Up @@ -371,18 +381,15 @@ SHA3_get_digest_size(PyObject *op, void *Py_UNUSED(closure))
{
// Preserving previous behavior: variable-length algorithms return 0
SHA3object *self = _SHA3object_CAST(op);
if (Hacl_Hash_SHA3_is_shake(self->hash_state))
return PyLong_FromLong(0);
else
return PyLong_FromLong(Hacl_Hash_SHA3_hash_len(self->hash_state));
return PyLong_FromLong(self->digest_size);
}


static PyObject *
SHA3_get_capacity_bits(PyObject *op, void *Py_UNUSED(closure))
{
SHA3object *self = _SHA3object_CAST(op);
uint32_t rate = Hacl_Hash_SHA3_block_len(self->hash_state) * 8;
uint32_t rate = self->block_size * 8;
assert(rate <= 1600);
int capacity = 1600 - rate;
return PyLong_FromLong(capacity);
Expand All @@ -393,8 +400,7 @@ static PyObject *
SHA3_get_rate_bits(PyObject *op, void *Py_UNUSED(closure))
{
SHA3object *self = _SHA3object_CAST(op);
uint32_t rate = Hacl_Hash_SHA3_block_len(self->hash_state) * 8;
return PyLong_FromLong(rate);
return PyLong_FromLong(self->block_size * 8);
}

static PyObject *
Expand Down
Loading