bpo-1635741: Port _sha3 module to multi-phase init (GH-21855)
Port the _sha3 extension module to multi-phase init (PEP 489). Convert static types to heap types.
This commit is contained in:
parent
a7f026870d
commit
93d50a6a8d
|
@ -0,0 +1 @@
|
|||
Port :mod:`_sha3` to multi-phase init. Convert static types to heap types.
|
|
@ -122,6 +122,28 @@
|
|||
#define SHA3_squeeze Keccak_HashSqueeze
|
||||
#define SHA3_copystate(dest, src) memcpy(&(dest), &(src), sizeof(SHA3_state))
|
||||
|
||||
typedef struct {
|
||||
PyTypeObject *sha3_224_type;
|
||||
PyTypeObject *sha3_256_type;
|
||||
PyTypeObject *sha3_384_type;
|
||||
PyTypeObject *sha3_512_type;
|
||||
#ifdef PY_WITH_KECCAK
|
||||
PyTypeObject *keccak_224_type;
|
||||
PyTypeObject *keccak_256_type;
|
||||
PyTypeObject *keccak_384_type;
|
||||
PyTypeObject *keccak_512_type;
|
||||
#endif
|
||||
PyTypeObject *shake_128_type;
|
||||
PyTypeObject *shake_256_type;
|
||||
} SHA3State;
|
||||
|
||||
static inline SHA3State*
|
||||
sha3_get_state(PyObject *module)
|
||||
{
|
||||
void *state = PyModule_GetState(module);
|
||||
assert(state != NULL);
|
||||
return (SHA3State *)state;
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
module _sha3
|
||||
|
@ -142,19 +164,6 @@ typedef struct {
|
|||
PyThread_type_lock lock;
|
||||
} SHA3object;
|
||||
|
||||
static PyTypeObject SHA3_224type;
|
||||
static PyTypeObject SHA3_256type;
|
||||
static PyTypeObject SHA3_384type;
|
||||
static PyTypeObject SHA3_512type;
|
||||
#ifdef PY_WITH_KECCAK
|
||||
static PyTypeObject Keccak_224type;
|
||||
static PyTypeObject Keccak_256type;
|
||||
static PyTypeObject Keccak_384type;
|
||||
static PyTypeObject Keccak_512type;
|
||||
#endif
|
||||
static PyTypeObject SHAKE128type;
|
||||
static PyTypeObject SHAKE256type;
|
||||
|
||||
#include "clinic/sha3module.c.h"
|
||||
|
||||
static SHA3object *
|
||||
|
@ -184,42 +193,43 @@ static PyObject *
|
|||
py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity)
|
||||
/*[clinic end generated code: output=90409addc5d5e8b0 input=bcfcdf2e4368347a]*/
|
||||
{
|
||||
SHA3object *self = NULL;
|
||||
Py_buffer buf = {NULL, NULL};
|
||||
HashReturn res;
|
||||
|
||||
self = newSHA3object(type);
|
||||
SHA3object *self = newSHA3object(type);
|
||||
if (self == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (type == &SHA3_224type) {
|
||||
SHA3State *state = PyType_GetModuleState(type);
|
||||
assert(state != NULL);
|
||||
|
||||
HashReturn res;
|
||||
if (type == state->sha3_224_type) {
|
||||
res = Keccak_HashInitialize_SHA3_224(&self->hash_state);
|
||||
} else if (type == &SHA3_256type) {
|
||||
} else if (type == state->sha3_256_type) {
|
||||
res = Keccak_HashInitialize_SHA3_256(&self->hash_state);
|
||||
} else if (type == &SHA3_384type) {
|
||||
} else if (type == state->sha3_384_type) {
|
||||
res = Keccak_HashInitialize_SHA3_384(&self->hash_state);
|
||||
} else if (type == &SHA3_512type) {
|
||||
} else if (type == state->sha3_512_type) {
|
||||
res = Keccak_HashInitialize_SHA3_512(&self->hash_state);
|
||||
#ifdef PY_WITH_KECCAK
|
||||
} else if (type == &Keccak_224type) {
|
||||
} else if (type == state->keccak_224_type) {
|
||||
res = Keccak_HashInitialize(&self->hash_state, 1152, 448, 224, 0x01);
|
||||
} else if (type == &Keccak_256type) {
|
||||
} else if (type == state->keccak_256_type) {
|
||||
res = Keccak_HashInitialize(&self->hash_state, 1088, 512, 256, 0x01);
|
||||
} else if (type == &Keccak_384type) {
|
||||
} else if (type == state->keccak_384_type) {
|
||||
res = Keccak_HashInitialize(&self->hash_state, 832, 768, 384, 0x01);
|
||||
} else if (type == &Keccak_512type) {
|
||||
} else if (type == state->keccak_512_type) {
|
||||
res = Keccak_HashInitialize(&self->hash_state, 576, 1024, 512, 0x01);
|
||||
#endif
|
||||
} else if (type == &SHAKE128type) {
|
||||
} else if (type == state->shake_128_type) {
|
||||
res = Keccak_HashInitialize_SHAKE128(&self->hash_state);
|
||||
} else if (type == &SHAKE256type) {
|
||||
} else if (type == state->shake_256_type) {
|
||||
res = Keccak_HashInitialize_SHAKE256(&self->hash_state);
|
||||
} else {
|
||||
PyErr_BadInternalCall();
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_buffer buf = {NULL, NULL};
|
||||
if (data) {
|
||||
GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
|
||||
if (buf.len >= HASHLIB_GIL_MINSIZE) {
|
||||
|
@ -262,7 +272,10 @@ SHA3_dealloc(SHA3object *self)
|
|||
if (self->lock) {
|
||||
PyThread_free_lock(self->lock);
|
||||
}
|
||||
|
||||
PyTypeObject *tp = Py_TYPE(self);
|
||||
PyObject_Del(self);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,27 +429,31 @@ static PyObject *
|
|||
SHA3_get_name(SHA3object *self, void *closure)
|
||||
{
|
||||
PyTypeObject *type = Py_TYPE(self);
|
||||
if (type == &SHA3_224type) {
|
||||
|
||||
SHA3State *state = PyType_GetModuleState(type);
|
||||
assert(state != NULL);
|
||||
|
||||
if (type == state->sha3_224_type) {
|
||||
return PyUnicode_FromString("sha3_224");
|
||||
} else if (type == &SHA3_256type) {
|
||||
} else if (type == state->sha3_256_type) {
|
||||
return PyUnicode_FromString("sha3_256");
|
||||
} else if (type == &SHA3_384type) {
|
||||
} else if (type == state->sha3_384_type) {
|
||||
return PyUnicode_FromString("sha3_384");
|
||||
} else if (type == &SHA3_512type) {
|
||||
} else if (type == state->sha3_512_type) {
|
||||
return PyUnicode_FromString("sha3_512");
|
||||
#ifdef PY_WITH_KECCAK
|
||||
} else if (type == &Keccak_224type) {
|
||||
} else if (type == state->keccak_224_type) {
|
||||
return PyUnicode_FromString("keccak_224");
|
||||
} else if (type == &Keccak_256type) {
|
||||
} else if (type == state->keccak_256_type) {
|
||||
return PyUnicode_FromString("keccak_256");
|
||||
} else if (type == &Keccak_384type) {
|
||||
} else if (type == state->keccak_384_type) {
|
||||
return PyUnicode_FromString("keccak_384");
|
||||
} else if (type == &Keccak_512type) {
|
||||
} else if (type == state->keccak_512_type) {
|
||||
return PyUnicode_FromString("keccak_512");
|
||||
#endif
|
||||
} else if (type == &SHAKE128type) {
|
||||
} else if (type == state->shake_128_type) {
|
||||
return PyUnicode_FromString("shake_128");
|
||||
} else if (type == &SHAKE256type) {
|
||||
} else if (type == state->shake_256_type) {
|
||||
return PyUnicode_FromString("shake_256");
|
||||
} else {
|
||||
PyErr_BadInternalCall();
|
||||
|
@ -476,7 +493,6 @@ SHA3_get_suffix(SHA3object *self, void *closure)
|
|||
return PyBytes_FromStringAndSize((const char *)suffix, 1);
|
||||
}
|
||||
|
||||
|
||||
static PyGetSetDef SHA3_getseters[] = {
|
||||
{"block_size", (getter)SHA3_get_block_size, NULL, NULL, NULL},
|
||||
{"name", (getter)SHA3_get_name, NULL, NULL, NULL},
|
||||
|
@ -487,48 +503,24 @@ static PyGetSetDef SHA3_getseters[] = {
|
|||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#define SHA3_TYPE_SLOTS(type_slots_obj, type_doc, type_methods) \
|
||||
static PyType_Slot type_slots_obj[] = { \
|
||||
{Py_tp_dealloc, SHA3_dealloc}, \
|
||||
{Py_tp_doc, (char*)type_doc}, \
|
||||
{Py_tp_methods, type_methods}, \
|
||||
{Py_tp_getset, SHA3_getseters}, \
|
||||
{Py_tp_new, py_sha3_new}, \
|
||||
{0,0} \
|
||||
}
|
||||
|
||||
#define SHA3_TYPE(type_obj, type_name, type_doc, type_methods) \
|
||||
static PyTypeObject type_obj = { \
|
||||
PyVarObject_HEAD_INIT(NULL, 0) \
|
||||
type_name, /* tp_name */ \
|
||||
sizeof(SHA3object), /* tp_basicsize */ \
|
||||
0, /* tp_itemsize */ \
|
||||
/* methods */ \
|
||||
(destructor)SHA3_dealloc, /* tp_dealloc */ \
|
||||
0, /* tp_vectorcall_offset */ \
|
||||
0, /* tp_getattr */ \
|
||||
0, /* tp_setattr */ \
|
||||
0, /* tp_as_async */ \
|
||||
0, /* tp_repr */ \
|
||||
0, /* tp_as_number */ \
|
||||
0, /* tp_as_sequence */ \
|
||||
0, /* tp_as_mapping */ \
|
||||
0, /* tp_hash */ \
|
||||
0, /* tp_call */ \
|
||||
0, /* tp_str */ \
|
||||
0, /* tp_getattro */ \
|
||||
0, /* tp_setattro */ \
|
||||
0, /* tp_as_buffer */ \
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */ \
|
||||
type_doc, /* tp_doc */ \
|
||||
0, /* tp_traverse */ \
|
||||
0, /* tp_clear */ \
|
||||
0, /* tp_richcompare */ \
|
||||
0, /* tp_weaklistoffset */ \
|
||||
0, /* tp_iter */ \
|
||||
0, /* tp_iternext */ \
|
||||
type_methods, /* tp_methods */ \
|
||||
NULL, /* tp_members */ \
|
||||
SHA3_getseters, /* tp_getset */ \
|
||||
0, /* tp_base */ \
|
||||
0, /* tp_dict */ \
|
||||
0, /* tp_descr_get */ \
|
||||
0, /* tp_descr_set */ \
|
||||
0, /* tp_dictoffset */ \
|
||||
0, /* tp_init */ \
|
||||
0, /* tp_alloc */ \
|
||||
py_sha3_new, /* tp_new */ \
|
||||
// Using PyType_GetModuleState() on these types is safe since they
|
||||
// cannot be subclassed: it does not have the Py_TPFLAGS_BASETYPE flag.
|
||||
#define SHA3_TYPE_SPEC(type_spec_obj, type_name, type_slots) \
|
||||
static PyType_Spec type_spec_obj = { \
|
||||
.name = "_sha3." type_name, \
|
||||
.basicsize = sizeof(SHA3object), \
|
||||
.flags = Py_TPFLAGS_DEFAULT, \
|
||||
.slots = type_slots \
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(sha3_224__doc__,
|
||||
|
@ -551,11 +543,6 @@ PyDoc_STRVAR(sha3_512__doc__,
|
|||
\n\
|
||||
Return a new SHA3 hash object with a hashbit length of 64 bytes.");
|
||||
|
||||
SHA3_TYPE(SHA3_224type, "_sha3.sha3_224", sha3_224__doc__, SHA3_methods);
|
||||
SHA3_TYPE(SHA3_256type, "_sha3.sha3_256", sha3_256__doc__, SHA3_methods);
|
||||
SHA3_TYPE(SHA3_384type, "_sha3.sha3_384", sha3_384__doc__, SHA3_methods);
|
||||
SHA3_TYPE(SHA3_512type, "_sha3.sha3_512", sha3_512__doc__, SHA3_methods);
|
||||
|
||||
#ifdef PY_WITH_KECCAK
|
||||
PyDoc_STRVAR(keccak_224__doc__,
|
||||
"keccak_224([data], *, usedforsecurity=True) -> Keccak object\n\
|
||||
|
@ -577,10 +564,32 @@ PyDoc_STRVAR(keccak_512__doc__,
|
|||
\n\
|
||||
Return a new Keccak hash object with a hashbit length of 64 bytes.");
|
||||
|
||||
SHA3_TYPE(Keccak_224type, "_sha3.keccak_224", keccak_224__doc__, SHA3_methods);
|
||||
SHA3_TYPE(Keccak_256type, "_sha3.keccak_256", keccak_256__doc__, SHA3_methods);
|
||||
SHA3_TYPE(Keccak_384type, "_sha3.keccak_384", keccak_384__doc__, SHA3_methods);
|
||||
SHA3_TYPE(Keccak_512type, "_sha3.keccak_512", keccak_512__doc__, SHA3_methods);
|
||||
#endif
|
||||
|
||||
SHA3_TYPE_SLOTS(sha3_224_slots, sha3_224__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(sha3_224_spec, "sha3_224", sha3_224_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(sha3_256_slots, sha3_256__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(sha3_256_spec, "sha3_256", sha3_256_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(sha3_384_slots, sha3_384__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(sha3_384_spec, "sha3_384", sha3_384_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(sha3_512_slots, sha3_512__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(sha3_512_spec, "sha3_512", sha3_512_slots);
|
||||
|
||||
#ifdef PY_WITH_KECCAK
|
||||
SHA3_TYPE_SLOTS(Keccak_224_slots, keccak_224__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(Keccak_224_spec, "keccak_224", Keccak_224_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(Keccak_256_slots, keccak_256__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(Keccak_256_spec, "keccak_256", Keccak_256_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(Keccak_384_slots, keccak_384__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(Keccak_384_spec, "keccak_384", Keccak_384_slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(Keccak_512_slots, keccak_512__doc__, SHA3_methods);
|
||||
SHA3_TYPE_SPEC(Keccak_512_spec, "keccak_512", Keccak_512_slots);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -684,70 +693,118 @@ PyDoc_STRVAR(shake_256__doc__,
|
|||
\n\
|
||||
Return a new SHAKE hash object.");
|
||||
|
||||
SHA3_TYPE(SHAKE128type, "_sha3.shake_128", shake_128__doc__, SHAKE_methods);
|
||||
SHA3_TYPE(SHAKE256type, "_sha3.shake_256", shake_256__doc__, SHAKE_methods);
|
||||
SHA3_TYPE_SLOTS(SHAKE128slots, shake_128__doc__, SHAKE_methods);
|
||||
SHA3_TYPE_SPEC(SHAKE128_spec, "shake_128", SHAKE128slots);
|
||||
|
||||
SHA3_TYPE_SLOTS(SHAKE256slots, shake_256__doc__, SHAKE_methods);
|
||||
SHA3_TYPE_SPEC(SHAKE256_spec, "shake_256", SHAKE256slots);
|
||||
|
||||
|
||||
static int
|
||||
_sha3_traverse(PyObject *module, visitproc visit, void *arg)
|
||||
{
|
||||
SHA3State *state = sha3_get_state(module);
|
||||
Py_VISIT(state->sha3_224_type);
|
||||
Py_VISIT(state->sha3_256_type);
|
||||
Py_VISIT(state->sha3_384_type);
|
||||
Py_VISIT(state->sha3_512_type);
|
||||
#ifdef PY_WITH_KECCAK
|
||||
Py_VISIT(state->keccak_224_type);
|
||||
Py_VISIT(state->keccak_256_type);
|
||||
Py_VISIT(state->keccak_384_type);
|
||||
Py_VISIT(state->keccak_512_type);
|
||||
#endif
|
||||
Py_VISIT(state->shake_128_type);
|
||||
Py_VISIT(state->shake_256_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_sha3_clear(PyObject *module)
|
||||
{
|
||||
SHA3State *state = sha3_get_state(module);
|
||||
Py_CLEAR(state->sha3_224_type);
|
||||
Py_CLEAR(state->sha3_256_type);
|
||||
Py_CLEAR(state->sha3_384_type);
|
||||
Py_CLEAR(state->sha3_512_type);
|
||||
#ifdef PY_WITH_KECCAK
|
||||
Py_CLEAR(state->keccak_224_type);
|
||||
Py_CLEAR(state->keccak_256_type);
|
||||
Py_CLEAR(state->keccak_384_type);
|
||||
Py_CLEAR(state->keccak_512_type);
|
||||
#endif
|
||||
Py_CLEAR(state->shake_128_type);
|
||||
Py_CLEAR(state->shake_256_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_sha3_free(void *module)
|
||||
{
|
||||
_sha3_clear((PyObject *)module);
|
||||
}
|
||||
|
||||
static int
|
||||
_sha3_exec(PyObject *m)
|
||||
{
|
||||
SHA3State *st = sha3_get_state(m);
|
||||
|
||||
#define init_sha3type(type, typespec) \
|
||||
do { \
|
||||
st->type = (PyTypeObject *)PyType_FromModuleAndSpec( \
|
||||
m, &typespec, NULL); \
|
||||
if (st->type == NULL) { \
|
||||
return -1; \
|
||||
} \
|
||||
if (PyModule_AddType(m, st->type) < 0) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
init_sha3type(sha3_224_type, sha3_224_spec);
|
||||
init_sha3type(sha3_256_type, sha3_256_spec);
|
||||
init_sha3type(sha3_384_type, sha3_384_spec);
|
||||
init_sha3type(sha3_512_type, sha3_512_spec);
|
||||
#ifdef PY_WITH_KECCAK
|
||||
init_sha3type(keccak_224_type, Keccak_224_spec);
|
||||
init_sha3type(keccak_256_type, Keccak_256_spec);
|
||||
init_sha3type(keccak_384_type, Keccak_384_spec);
|
||||
init_sha3type(keccak_512_type, Keccak_512_spec);
|
||||
#endif
|
||||
init_sha3type(shake_128_type, SHAKE128_spec);
|
||||
init_sha3type(shake_256_type, SHAKE256_spec);
|
||||
#undef init_sha3type
|
||||
|
||||
if (PyModule_AddIntConstant(m, "keccakopt", KeccakOpt) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (PyModule_AddStringConstant(m, "implementation",
|
||||
KeccakP1600_implementation) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyModuleDef_Slot _sha3_slots[] = {
|
||||
{Py_mod_exec, _sha3_exec},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
/* Initialize this module. */
|
||||
static struct PyModuleDef _SHA3module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_sha3",
|
||||
NULL,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
static struct PyModuleDef _sha3module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
.m_name = "_sha3",
|
||||
.m_size = sizeof(SHA3State),
|
||||
.m_slots = _sha3_slots,
|
||||
.m_traverse = _sha3_traverse,
|
||||
.m_clear = _sha3_clear,
|
||||
.m_free = _sha3_free,
|
||||
};
|
||||
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit__sha3(void)
|
||||
{
|
||||
PyObject *m = NULL;
|
||||
|
||||
if ((m = PyModule_Create(&_SHA3module)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define init_sha3type(name, type) \
|
||||
do { \
|
||||
Py_SET_TYPE(type, &PyType_Type); \
|
||||
if (PyType_Ready(type) < 0) { \
|
||||
goto error; \
|
||||
} \
|
||||
Py_INCREF((PyObject *)type); \
|
||||
if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \
|
||||
goto error; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
init_sha3type("sha3_224", &SHA3_224type);
|
||||
init_sha3type("sha3_256", &SHA3_256type);
|
||||
init_sha3type("sha3_384", &SHA3_384type);
|
||||
init_sha3type("sha3_512", &SHA3_512type);
|
||||
#ifdef PY_WITH_KECCAK
|
||||
init_sha3type("keccak_224", &Keccak_224type);
|
||||
init_sha3type("keccak_256", &Keccak_256type);
|
||||
init_sha3type("keccak_384", &Keccak_384type);
|
||||
init_sha3type("keccak_512", &Keccak_512type);
|
||||
#endif
|
||||
init_sha3type("shake_128", &SHAKE128type);
|
||||
init_sha3type("shake_256", &SHAKE256type);
|
||||
|
||||
#undef init_sha3type
|
||||
|
||||
if (PyModule_AddIntConstant(m, "keccakopt", KeccakOpt) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (PyModule_AddStringConstant(m, "implementation",
|
||||
KeccakP1600_implementation) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return m;
|
||||
error:
|
||||
Py_DECREF(m);
|
||||
return NULL;
|
||||
return PyModuleDef_Init(&_sha3module);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue