@@ -67,6 +67,12 @@ sha3_get_state(PyObject *module)
6767typedef struct {
6868 HASHLIB_OBJECT_HEAD
6969 Hacl_Hash_SHA3_state_t * hash_state ;
70+ // HACL* update functions entirely replace the state, which can lead
71+ // to races on the free-threaded build. Since the kind of hash is static,
72+ // we can store its corresponding metadata once.
73+ uint32_t digest_size ;
74+ uint32_t block_size ;
75+ int is_shake ;
7076} SHA3object ;
7177
7278#define _SHA3object_CAST (op ) ((SHA3object *)(op))
@@ -96,7 +102,7 @@ newSHA3object(PyTypeObject *type)
96102 return NULL ;
97103 }
98104 HASHLIB_INIT_MUTEX (newobj );
99-
105+ newobj -> digest_size = newobj -> block_size = 0 ;
100106 PyObject_GC_Track (newobj );
101107 return newobj ;
102108}
@@ -179,6 +185,11 @@ py_sha3_new_impl(PyTypeObject *type, PyObject *data_obj, int usedforsecurity,
179185 goto error ;
180186 }
181187
188+ // set the metadata once we know that the state is valid
189+ int is_shake = Hacl_Hash_SHA3_is_shake (self -> hash_state );
190+ self -> digest_size = is_shake ? 0 : Hacl_Hash_SHA3_hash_len (self -> hash_state );
191+ self -> block_size = Hacl_Hash_SHA3_block_len (self -> hash_state );
192+
182193 if (data ) {
183194 GET_BUFFER_VIEW_OR_ERROR (data , & buf , goto error );
184195 /* Do not use self->mutex here as this is the constructor
@@ -253,6 +264,8 @@ _sha3_sha3_224_copy_impl(SHA3object *self, PyTypeObject *cls)
253264 Py_DECREF (newobj );
254265 return PyErr_NoMemory ();
255266 }
267+ newobj -> digest_size = self -> digest_size ;
268+ newobj -> block_size = self -> block_size ;
256269 return (PyObject * )newobj ;
257270}
258271
@@ -273,8 +286,7 @@ _sha3_sha3_224_digest_impl(SHA3object *self)
273286 HASHLIB_ACQUIRE_LOCK (self );
274287 (void )Hacl_Hash_SHA3_digest (self -> hash_state , digest );
275288 HASHLIB_RELEASE_LOCK (self );
276- return PyBytes_FromStringAndSize ((const char * )digest ,
277- Hacl_Hash_SHA3_hash_len (self -> hash_state ));
289+ return PyBytes_FromStringAndSize ((const char * )digest , self -> digest_size );
278290}
279291
280292
@@ -292,8 +304,7 @@ _sha3_sha3_224_hexdigest_impl(SHA3object *self)
292304 HASHLIB_ACQUIRE_LOCK (self );
293305 (void )Hacl_Hash_SHA3_digest (self -> hash_state , digest );
294306 HASHLIB_RELEASE_LOCK (self );
295- return _Py_strhex ((const char * )digest ,
296- Hacl_Hash_SHA3_hash_len (self -> hash_state ));
307+ return _Py_strhex ((const char * )digest , self -> digest_size );
297308}
298309
299310
@@ -334,8 +345,7 @@ static PyObject *
334345SHA3_get_block_size (PyObject * op , void * Py_UNUSED (closure ))
335346{
336347 SHA3object * self = _SHA3object_CAST (op );
337- uint32_t rate = Hacl_Hash_SHA3_block_len (self -> hash_state );
338- return PyLong_FromLong (rate );
348+ return PyLong_FromLong (self -> block_size );
339349}
340350
341351
@@ -371,18 +381,15 @@ SHA3_get_digest_size(PyObject *op, void *Py_UNUSED(closure))
371381{
372382 // Preserving previous behavior: variable-length algorithms return 0
373383 SHA3object * self = _SHA3object_CAST (op );
374- if (Hacl_Hash_SHA3_is_shake (self -> hash_state ))
375- return PyLong_FromLong (0 );
376- else
377- return PyLong_FromLong (Hacl_Hash_SHA3_hash_len (self -> hash_state ));
384+ return PyLong_FromLong (self -> digest_size );
378385}
379386
380387
381388static PyObject *
382389SHA3_get_capacity_bits (PyObject * op , void * Py_UNUSED (closure ))
383390{
384391 SHA3object * self = _SHA3object_CAST (op );
385- uint32_t rate = Hacl_Hash_SHA3_block_len ( self -> hash_state ) * 8 ;
392+ uint32_t rate = self -> block_size * 8 ;
386393 assert (rate <= 1600 );
387394 int capacity = 1600 - rate ;
388395 return PyLong_FromLong (capacity );
@@ -393,8 +400,7 @@ static PyObject *
393400SHA3_get_rate_bits (PyObject * op , void * Py_UNUSED (closure ))
394401{
395402 SHA3object * self = _SHA3object_CAST (op );
396- uint32_t rate = Hacl_Hash_SHA3_block_len (self -> hash_state ) * 8 ;
397- return PyLong_FromLong (rate );
403+ return PyLong_FromLong (self -> block_size * 8 );
398404}
399405
400406static PyObject *
0 commit comments