| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + :mod:`hashlib`: Fix data races when accessing | ||
| 2 | + :attr:`~hashlib.hash.digest_size` and :attr:`~hashlib.hash.block_size` on | ||
| 3 | + SHA-3 objects. Patch by Bénédikt Tran. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -67,6 +67,12 @@ sha3_get_state(PyObject *module) | |||
| 67 | 67 | typedef struct { | |
| 68 | 68 | HASHLIB_OBJECT_HEAD | |
| 69 | 69 | 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; | ||
| 70 | 76 | } SHA3object; | |
| 71 | 77 | ||
| 72 | 78 | #define _SHA3object_CAST(op) ((SHA3object *)(op)) | |
@@ -96,7 +102,7 @@ newSHA3object(PyTypeObject *type) | |||
| 96 | 102 | return NULL; | |
| 97 | 103 | } | |
| 98 | 104 | HASHLIB_INIT_MUTEX(newobj); | |
| 99 | - | ||
| 105 | + newobj->digest_size = newobj->block_size = 0; | ||
| 100 | 106 | PyObject_GC_Track(newobj); | |
| 101 | 107 | return newobj; | |
| 102 | 108 | } | |
@@ -179,6 +185,11 @@ py_sha3_new_impl(PyTypeObject *type, PyObject *data_obj, int usedforsecurity, | |||
| 179 | 185 | goto error; | |
| 180 | 186 | } | |
| 181 | 187 | ||
| 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 | + | ||
| 182 | 193 | if (data) { | |
| 183 | 194 | GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error); | |
| 184 | 195 | /* Do not use self->mutex here as this is the constructor | |
@@ -248,6 +259,8 @@ _sha3_sha3_224_copy_impl(SHA3object *self, PyTypeObject *cls) | |||
| 248 | 259 | } | |
| 249 | 260 | HASHLIB_ACQUIRE_LOCK(self); | |
| 250 | 261 | newobj->hash_state = Hacl_Hash_SHA3_copy(self->hash_state); | |
| 262 | + newobj->digest_size = self->digest_size; | ||
| 263 | + newobj->block_size = self->block_size; | ||
| 251 | 264 | HASHLIB_RELEASE_LOCK(self); | |
| 252 | 265 | if (newobj->hash_state == NULL) { | |
| 253 | 266 | Py_DECREF(newobj); | |
@@ -273,8 +286,7 @@ _sha3_sha3_224_digest_impl(SHA3object *self) | |||
| 273 | 286 | HASHLIB_ACQUIRE_LOCK(self); | |
| 274 | 287 | (void)Hacl_Hash_SHA3_digest(self->hash_state, digest); | |
| 275 | 288 | 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); | ||
| 278 | 290 | } | |
| 279 | 291 | ||
| 280 | 292 | ||
@@ -292,8 +304,7 @@ _sha3_sha3_224_hexdigest_impl(SHA3object *self) | |||
| 292 | 304 | HASHLIB_ACQUIRE_LOCK(self); | |
| 293 | 305 | (void)Hacl_Hash_SHA3_digest(self->hash_state, digest); | |
| 294 | 306 | 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); | ||
| 297 | 308 | } | |
| 298 | 309 | ||
| 299 | 310 | ||
@@ -334,8 +345,7 @@ static PyObject * | |||
| 334 | 345 | SHA3_get_block_size(PyObject *op, void *Py_UNUSED(closure)) | |
| 335 | 346 | { | |
| 336 | 347 | 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); | ||
| 339 | 349 | } | |
| 340 | 350 | ||
| 341 | 351 | ||
@@ -371,18 +381,15 @@ SHA3_get_digest_size(PyObject *op, void *Py_UNUSED(closure)) | |||
| 371 | 381 | { | |
| 372 | 382 | // Preserving previous behavior: variable-length algorithms return 0 | |
| 373 | 383 | 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); | ||
| 378 | 385 | } | |
| 379 | 386 | ||
| 380 | 387 | ||
| 381 | 388 | static PyObject * | |
| 382 | 389 | SHA3_get_capacity_bits(PyObject *op, void *Py_UNUSED(closure)) | |
| 383 | 390 | { | |
| 384 | 391 | 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; | ||
| 386 | 393 | assert(rate <= 1600); | |
| 387 | 394 | int capacity = 1600 - rate; | |
| 388 | 395 | return PyLong_FromLong(capacity); | |
@@ -393,8 +400,7 @@ static PyObject * | |||
| 393 | 400 | SHA3_get_rate_bits(PyObject *op, void *Py_UNUSED(closure)) | |
| 394 | 401 | { | |
| 395 | 402 | 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); | ||
| 398 | 404 | } | |
| 399 | 405 | ||
| 400 | 406 | static PyObject * | |
| Back | FazBrowse Home | New Git URL |
0 commit comments