123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- /* SHA1 module */
- /* This module provides an interface to the SHA1 algorithm */
- /* See below for information about the original code this module was
- based upon. Additional work performed by:
- Andrew Kuchling (amk@amk.ca)
- Greg Stein (gstein@lyra.org)
- Trevor Perrin (trevp@trevp.net)
- Copyright (C) 2005-2007 Gregory P. Smith (greg@krypto.org)
- Licensed to PSF under a Contributor Agreement.
- */
- /* SHA1 objects */
- #ifndef Py_BUILD_CORE_BUILTIN
- # define Py_BUILD_CORE_MODULE 1
- #endif
- #include "Python.h"
- #include "hashlib.h"
- #include "pycore_strhex.h" // _Py_strhex()
- #include "pycore_typeobject.h" // _PyType_GetModuleState()
- /*[clinic input]
- module _sha1
- class SHA1Type "SHA1object *" "&PyType_Type"
- [clinic start generated code]*/
- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3dc9a20d1becb759]*/
- /* Some useful types */
- #if SIZEOF_INT == 4
- typedef unsigned int SHA1_INT32; /* 32-bit integer */
- typedef long long SHA1_INT64; /* 64-bit integer */
- #else
- /* not defined. compilation will die. */
- #endif
- /* The SHA1 block size and message digest sizes, in bytes */
- #define SHA1_BLOCKSIZE 64
- #define SHA1_DIGESTSIZE 20
- #include "_hacl/Hacl_Hash_SHA1.h"
- typedef struct {
- PyObject_HEAD
- // Prevents undefined behavior via multiple threads entering the C API.
- // The lock will be NULL before threaded access has been enabled.
- PyThread_type_lock lock;
- Hacl_Streaming_SHA1_state *hash_state;
- } SHA1object;
- #include "clinic/sha1module.c.h"
- typedef struct {
- PyTypeObject* sha1_type;
- } SHA1State;
- static inline SHA1State*
- sha1_get_state(PyObject *module)
- {
- void *state = PyModule_GetState(module);
- assert(state != NULL);
- return (SHA1State *)state;
- }
- static SHA1object *
- newSHA1object(SHA1State *st)
- {
- SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type);
- sha->lock = NULL;
- PyObject_GC_Track(sha);
- return sha;
- }
- /* Internal methods for a hash object */
- static int
- SHA1_traverse(PyObject *ptr, visitproc visit, void *arg)
- {
- Py_VISIT(Py_TYPE(ptr));
- return 0;
- }
- static void
- SHA1_dealloc(SHA1object *ptr)
- {
- Hacl_Streaming_SHA1_legacy_free(ptr->hash_state);
- if (ptr->lock != NULL) {
- PyThread_free_lock(ptr->lock);
- }
- PyTypeObject *tp = Py_TYPE(ptr);
- PyObject_GC_UnTrack(ptr);
- PyObject_GC_Del(ptr);
- Py_DECREF(tp);
- }
- /* External methods for a hash object */
- /*[clinic input]
- SHA1Type.copy
- cls: defining_class
- Return a copy of the hash object.
- [clinic start generated code]*/
- static PyObject *
- SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls)
- /*[clinic end generated code: output=b32d4461ce8bc7a7 input=6c22e66fcc34c58e]*/
- {
- SHA1State *st = _PyType_GetModuleState(cls);
- SHA1object *newobj;
- if ((newobj = newSHA1object(st)) == NULL)
- return NULL;
- ENTER_HASHLIB(self);
- newobj->hash_state = Hacl_Streaming_SHA1_legacy_copy(self->hash_state);
- LEAVE_HASHLIB(self);
- return (PyObject *)newobj;
- }
- /*[clinic input]
- SHA1Type.digest
- Return the digest value as a bytes object.
- [clinic start generated code]*/
- static PyObject *
- SHA1Type_digest_impl(SHA1object *self)
- /*[clinic end generated code: output=2f05302a7aa2b5cb input=13824b35407444bd]*/
- {
- unsigned char digest[SHA1_DIGESTSIZE];
- ENTER_HASHLIB(self);
- Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest);
- LEAVE_HASHLIB(self);
- return PyBytes_FromStringAndSize((const char *)digest, SHA1_DIGESTSIZE);
- }
- /*[clinic input]
- SHA1Type.hexdigest
- Return the digest value as a string of hexadecimal digits.
- [clinic start generated code]*/
- static PyObject *
- SHA1Type_hexdigest_impl(SHA1object *self)
- /*[clinic end generated code: output=4161fd71e68c6659 input=97691055c0c74ab0]*/
- {
- unsigned char digest[SHA1_DIGESTSIZE];
- ENTER_HASHLIB(self);
- Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest);
- LEAVE_HASHLIB(self);
- return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE);
- }
- static void update(Hacl_Streaming_SHA1_state *state, uint8_t *buf, Py_ssize_t len) {
- #if PY_SSIZE_T_MAX > UINT32_MAX
- while (len > UINT32_MAX) {
- Hacl_Streaming_SHA1_legacy_update(state, buf, UINT32_MAX);
- len -= UINT32_MAX;
- buf += UINT32_MAX;
- }
- #endif
- Hacl_Streaming_SHA1_legacy_update(state, buf, (uint32_t) len);
- }
- /*[clinic input]
- SHA1Type.update
- obj: object
- /
- Update this hash object's state with the provided string.
- [clinic start generated code]*/
- static PyObject *
- SHA1Type_update(SHA1object *self, PyObject *obj)
- /*[clinic end generated code: output=d9902f0e5015e9ae input=aad8e07812edbba3]*/
- {
- Py_buffer buf;
- GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
- if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) {
- self->lock = PyThread_allocate_lock();
- }
- if (self->lock != NULL) {
- Py_BEGIN_ALLOW_THREADS
- PyThread_acquire_lock(self->lock, 1);
- update(self->hash_state, buf.buf, buf.len);
- PyThread_release_lock(self->lock);
- Py_END_ALLOW_THREADS
- } else {
- update(self->hash_state, buf.buf, buf.len);
- }
- PyBuffer_Release(&buf);
- Py_RETURN_NONE;
- }
- static PyMethodDef SHA1_methods[] = {
- SHA1TYPE_COPY_METHODDEF
- SHA1TYPE_DIGEST_METHODDEF
- SHA1TYPE_HEXDIGEST_METHODDEF
- SHA1TYPE_UPDATE_METHODDEF
- {NULL, NULL} /* sentinel */
- };
- static PyObject *
- SHA1_get_block_size(PyObject *self, void *closure)
- {
- return PyLong_FromLong(SHA1_BLOCKSIZE);
- }
- static PyObject *
- SHA1_get_name(PyObject *self, void *closure)
- {
- return PyUnicode_FromStringAndSize("sha1", 4);
- }
- static PyObject *
- sha1_get_digest_size(PyObject *self, void *closure)
- {
- return PyLong_FromLong(SHA1_DIGESTSIZE);
- }
- static PyGetSetDef SHA1_getseters[] = {
- {"block_size",
- (getter)SHA1_get_block_size, NULL,
- NULL,
- NULL},
- {"name",
- (getter)SHA1_get_name, NULL,
- NULL,
- NULL},
- {"digest_size",
- (getter)sha1_get_digest_size, NULL,
- NULL,
- NULL},
- {NULL} /* Sentinel */
- };
- static PyType_Slot sha1_type_slots[] = {
- {Py_tp_dealloc, SHA1_dealloc},
- {Py_tp_methods, SHA1_methods},
- {Py_tp_getset, SHA1_getseters},
- {Py_tp_traverse, SHA1_traverse},
- {0,0}
- };
- static PyType_Spec sha1_type_spec = {
- .name = "_sha1.sha1",
- .basicsize = sizeof(SHA1object),
- .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
- Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC),
- .slots = sha1_type_slots
- };
- /* The single module-level function: new() */
- /*[clinic input]
- _sha1.sha1
- string: object(c_default="NULL") = b''
- *
- usedforsecurity: bool = True
- Return a new SHA1 hash object; optionally initialized with a string.
- [clinic start generated code]*/
- static PyObject *
- _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
- /*[clinic end generated code: output=6f8b3af05126e18e input=bd54b68e2bf36a8a]*/
- {
- SHA1object *new;
- Py_buffer buf;
- if (string)
- GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
- SHA1State *st = sha1_get_state(module);
- if ((new = newSHA1object(st)) == NULL) {
- if (string)
- PyBuffer_Release(&buf);
- return NULL;
- }
- new->hash_state = Hacl_Streaming_SHA1_legacy_create_in();
- if (PyErr_Occurred()) {
- Py_DECREF(new);
- if (string)
- PyBuffer_Release(&buf);
- return NULL;
- }
- if (string) {
- if (buf.len >= HASHLIB_GIL_MINSIZE) {
- /* We do not initialize self->lock here as this is the constructor
- * where it is not yet possible to have concurrent access. */
- Py_BEGIN_ALLOW_THREADS
- update(new->hash_state, buf.buf, buf.len);
- Py_END_ALLOW_THREADS
- } else {
- update(new->hash_state, buf.buf, buf.len);
- }
- PyBuffer_Release(&buf);
- }
- return (PyObject *)new;
- }
- /* List of functions exported by this module */
- static struct PyMethodDef SHA1_functions[] = {
- _SHA1_SHA1_METHODDEF
- {NULL, NULL} /* Sentinel */
- };
- static int
- _sha1_traverse(PyObject *module, visitproc visit, void *arg)
- {
- SHA1State *state = sha1_get_state(module);
- Py_VISIT(state->sha1_type);
- return 0;
- }
- static int
- _sha1_clear(PyObject *module)
- {
- SHA1State *state = sha1_get_state(module);
- Py_CLEAR(state->sha1_type);
- return 0;
- }
- static void
- _sha1_free(void *module)
- {
- _sha1_clear((PyObject *)module);
- }
- static int
- _sha1_exec(PyObject *module)
- {
- SHA1State* st = sha1_get_state(module);
- st->sha1_type = (PyTypeObject *)PyType_FromModuleAndSpec(
- module, &sha1_type_spec, NULL);
- if (st->sha1_type == NULL) {
- return -1;
- }
- Py_INCREF(st->sha1_type);
- if (PyModule_AddObject(module,
- "SHA1Type",
- (PyObject *)st->sha1_type) < 0) {
- Py_DECREF(st->sha1_type);
- return -1;
- }
- return 0;
- }
- /* Initialize this module. */
- static PyModuleDef_Slot _sha1_slots[] = {
- {Py_mod_exec, _sha1_exec},
- {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
- {0, NULL}
- };
- static struct PyModuleDef _sha1module = {
- PyModuleDef_HEAD_INIT,
- .m_name = "_sha1",
- .m_size = sizeof(SHA1State),
- .m_methods = SHA1_functions,
- .m_slots = _sha1_slots,
- .m_traverse = _sha1_traverse,
- .m_clear = _sha1_clear,
- .m_free = _sha1_free
- };
- PyMODINIT_FUNC
- PyInit__sha1(void)
- {
- return PyModuleDef_Init(&_sha1module);
- }
|