(root)/
Python-3.12.0/
Modules/
sha1module.c
       1  /* SHA1 module */
       2  
       3  /* This module provides an interface to the SHA1 algorithm */
       4  
       5  /* See below for information about the original code this module was
       6     based upon. Additional work performed by:
       7  
       8     Andrew Kuchling (amk@amk.ca)
       9     Greg Stein (gstein@lyra.org)
      10     Trevor Perrin (trevp@trevp.net)
      11  
      12     Copyright (C) 2005-2007   Gregory P. Smith (greg@krypto.org)
      13     Licensed to PSF under a Contributor Agreement.
      14  
      15  */
      16  
      17  /* SHA1 objects */
      18  #ifndef Py_BUILD_CORE_BUILTIN
      19  #  define Py_BUILD_CORE_MODULE 1
      20  #endif
      21  
      22  #include "Python.h"
      23  #include "hashlib.h"
      24  #include "pycore_strhex.h"        // _Py_strhex()
      25  #include "pycore_typeobject.h"    // _PyType_GetModuleState()
      26  
      27  /*[clinic input]
      28  module _sha1
      29  class SHA1Type "SHA1object *" "&PyType_Type"
      30  [clinic start generated code]*/
      31  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3dc9a20d1becb759]*/
      32  
      33  /* Some useful types */
      34  
      35  #if SIZEOF_INT == 4
      36  typedef unsigned int SHA1_INT32;        /* 32-bit integer */
      37  typedef long long SHA1_INT64;        /* 64-bit integer */
      38  #else
      39  /* not defined. compilation will die. */
      40  #endif
      41  
      42  /* The SHA1 block size and message digest sizes, in bytes */
      43  
      44  #define SHA1_BLOCKSIZE    64
      45  #define SHA1_DIGESTSIZE   20
      46  
      47  #include "_hacl/Hacl_Hash_SHA1.h"
      48  
      49  typedef struct {
      50      PyObject_HEAD
      51      // Prevents undefined behavior via multiple threads entering the C API.
      52      // The lock will be NULL before threaded access has been enabled.
      53      PyThread_type_lock lock;
      54      Hacl_Streaming_SHA1_state *hash_state;
      55  } SHA1object;
      56  
      57  #include "clinic/sha1module.c.h"
      58  
      59  
      60  typedef struct {
      61      PyTypeObject* sha1_type;
      62  } SHA1State;
      63  
      64  static inline SHA1State*
      65  sha1_get_state(PyObject *module)
      66  {
      67      void *state = PyModule_GetState(module);
      68      assert(state != NULL);
      69      return (SHA1State *)state;
      70  }
      71  
      72  static SHA1object *
      73  newSHA1object(SHA1State *st)
      74  {
      75      SHA1object *sha = (SHA1object *)PyObject_GC_New(SHA1object, st->sha1_type);
      76      sha->lock = NULL;
      77      PyObject_GC_Track(sha);
      78      return sha;
      79  }
      80  
      81  
      82  /* Internal methods for a hash object */
      83  static int
      84  SHA1_traverse(PyObject *ptr, visitproc visit, void *arg)
      85  {
      86      Py_VISIT(Py_TYPE(ptr));
      87      return 0;
      88  }
      89  
      90  static void
      91  SHA1_dealloc(SHA1object *ptr)
      92  {
      93      Hacl_Streaming_SHA1_legacy_free(ptr->hash_state);
      94      if (ptr->lock != NULL) {
      95          PyThread_free_lock(ptr->lock);
      96      }
      97      PyTypeObject *tp = Py_TYPE(ptr);
      98      PyObject_GC_UnTrack(ptr);
      99      PyObject_GC_Del(ptr);
     100      Py_DECREF(tp);
     101  }
     102  
     103  
     104  /* External methods for a hash object */
     105  
     106  /*[clinic input]
     107  SHA1Type.copy
     108  
     109      cls: defining_class
     110  
     111  Return a copy of the hash object.
     112  [clinic start generated code]*/
     113  
     114  static PyObject *
     115  SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls)
     116  /*[clinic end generated code: output=b32d4461ce8bc7a7 input=6c22e66fcc34c58e]*/
     117  {
     118      SHA1State *st = _PyType_GetModuleState(cls);
     119  
     120      SHA1object *newobj;
     121      if ((newobj = newSHA1object(st)) == NULL)
     122          return NULL;
     123  
     124      ENTER_HASHLIB(self);
     125      newobj->hash_state = Hacl_Streaming_SHA1_legacy_copy(self->hash_state);
     126      LEAVE_HASHLIB(self);
     127      return (PyObject *)newobj;
     128  }
     129  
     130  /*[clinic input]
     131  SHA1Type.digest
     132  
     133  Return the digest value as a bytes object.
     134  [clinic start generated code]*/
     135  
     136  static PyObject *
     137  SHA1Type_digest_impl(SHA1object *self)
     138  /*[clinic end generated code: output=2f05302a7aa2b5cb input=13824b35407444bd]*/
     139  {
     140      unsigned char digest[SHA1_DIGESTSIZE];
     141      ENTER_HASHLIB(self);
     142      Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest);
     143      LEAVE_HASHLIB(self);
     144      return PyBytes_FromStringAndSize((const char *)digest, SHA1_DIGESTSIZE);
     145  }
     146  
     147  /*[clinic input]
     148  SHA1Type.hexdigest
     149  
     150  Return the digest value as a string of hexadecimal digits.
     151  [clinic start generated code]*/
     152  
     153  static PyObject *
     154  SHA1Type_hexdigest_impl(SHA1object *self)
     155  /*[clinic end generated code: output=4161fd71e68c6659 input=97691055c0c74ab0]*/
     156  {
     157      unsigned char digest[SHA1_DIGESTSIZE];
     158      ENTER_HASHLIB(self);
     159      Hacl_Streaming_SHA1_legacy_finish(self->hash_state, digest);
     160      LEAVE_HASHLIB(self);
     161      return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE);
     162  }
     163  
     164  static void update(Hacl_Streaming_SHA1_state *state, uint8_t *buf, Py_ssize_t len) {
     165  #if PY_SSIZE_T_MAX > UINT32_MAX
     166    while (len > UINT32_MAX) {
     167      Hacl_Streaming_SHA1_legacy_update(state, buf, UINT32_MAX);
     168      len -= UINT32_MAX;
     169      buf += UINT32_MAX;
     170    }
     171  #endif
     172    Hacl_Streaming_SHA1_legacy_update(state, buf, (uint32_t) len);
     173  }
     174  
     175  /*[clinic input]
     176  SHA1Type.update
     177  
     178      obj: object
     179      /
     180  
     181  Update this hash object's state with the provided string.
     182  [clinic start generated code]*/
     183  
     184  static PyObject *
     185  SHA1Type_update(SHA1object *self, PyObject *obj)
     186  /*[clinic end generated code: output=d9902f0e5015e9ae input=aad8e07812edbba3]*/
     187  {
     188      Py_buffer buf;
     189  
     190      GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
     191  
     192      if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) {
     193          self->lock = PyThread_allocate_lock();
     194      }
     195      if (self->lock != NULL) {
     196          Py_BEGIN_ALLOW_THREADS
     197          PyThread_acquire_lock(self->lock, 1);
     198          update(self->hash_state, buf.buf, buf.len);
     199          PyThread_release_lock(self->lock);
     200          Py_END_ALLOW_THREADS
     201      } else {
     202          update(self->hash_state, buf.buf, buf.len);
     203      }
     204  
     205      PyBuffer_Release(&buf);
     206      Py_RETURN_NONE;
     207  }
     208  
     209  static PyMethodDef SHA1_methods[] = {
     210      SHA1TYPE_COPY_METHODDEF
     211      SHA1TYPE_DIGEST_METHODDEF
     212      SHA1TYPE_HEXDIGEST_METHODDEF
     213      SHA1TYPE_UPDATE_METHODDEF
     214      {NULL,        NULL}         /* sentinel */
     215  };
     216  
     217  static PyObject *
     218  SHA1_get_block_size(PyObject *self, void *closure)
     219  {
     220      return PyLong_FromLong(SHA1_BLOCKSIZE);
     221  }
     222  
     223  static PyObject *
     224  SHA1_get_name(PyObject *self, void *closure)
     225  {
     226      return PyUnicode_FromStringAndSize("sha1", 4);
     227  }
     228  
     229  static PyObject *
     230  sha1_get_digest_size(PyObject *self, void *closure)
     231  {
     232      return PyLong_FromLong(SHA1_DIGESTSIZE);
     233  }
     234  
     235  static PyGetSetDef SHA1_getseters[] = {
     236      {"block_size",
     237       (getter)SHA1_get_block_size, NULL,
     238       NULL,
     239       NULL},
     240      {"name",
     241       (getter)SHA1_get_name, NULL,
     242       NULL,
     243       NULL},
     244      {"digest_size",
     245       (getter)sha1_get_digest_size, NULL,
     246       NULL,
     247       NULL},
     248      {NULL}  /* Sentinel */
     249  };
     250  
     251  static PyType_Slot sha1_type_slots[] = {
     252      {Py_tp_dealloc, SHA1_dealloc},
     253      {Py_tp_methods, SHA1_methods},
     254      {Py_tp_getset, SHA1_getseters},
     255      {Py_tp_traverse, SHA1_traverse},
     256      {0,0}
     257  };
     258  
     259  static PyType_Spec sha1_type_spec = {
     260      .name = "_sha1.sha1",
     261      .basicsize =  sizeof(SHA1object),
     262      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
     263                Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC),
     264      .slots = sha1_type_slots
     265  };
     266  
     267  /* The single module-level function: new() */
     268  
     269  /*[clinic input]
     270  _sha1.sha1
     271  
     272      string: object(c_default="NULL") = b''
     273      *
     274      usedforsecurity: bool = True
     275  
     276  Return a new SHA1 hash object; optionally initialized with a string.
     277  [clinic start generated code]*/
     278  
     279  static PyObject *
     280  _sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
     281  /*[clinic end generated code: output=6f8b3af05126e18e input=bd54b68e2bf36a8a]*/
     282  {
     283      SHA1object *new;
     284      Py_buffer buf;
     285  
     286      if (string)
     287          GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
     288  
     289      SHA1State *st = sha1_get_state(module);
     290      if ((new = newSHA1object(st)) == NULL) {
     291          if (string)
     292              PyBuffer_Release(&buf);
     293          return NULL;
     294      }
     295  
     296      new->hash_state = Hacl_Streaming_SHA1_legacy_create_in();
     297  
     298      if (PyErr_Occurred()) {
     299          Py_DECREF(new);
     300          if (string)
     301              PyBuffer_Release(&buf);
     302          return NULL;
     303      }
     304      if (string) {
     305          if (buf.len >= HASHLIB_GIL_MINSIZE) {
     306              /* We do not initialize self->lock here as this is the constructor
     307               * where it is not yet possible to have concurrent access. */
     308              Py_BEGIN_ALLOW_THREADS
     309              update(new->hash_state, buf.buf, buf.len);
     310              Py_END_ALLOW_THREADS
     311          } else {
     312              update(new->hash_state, buf.buf, buf.len);
     313          }
     314          PyBuffer_Release(&buf);
     315      }
     316  
     317      return (PyObject *)new;
     318  }
     319  
     320  
     321  /* List of functions exported by this module */
     322  
     323  static struct PyMethodDef SHA1_functions[] = {
     324      _SHA1_SHA1_METHODDEF
     325      {NULL,      NULL}            /* Sentinel */
     326  };
     327  
     328  static int
     329  _sha1_traverse(PyObject *module, visitproc visit, void *arg)
     330  {
     331      SHA1State *state = sha1_get_state(module);
     332      Py_VISIT(state->sha1_type);
     333      return 0;
     334  }
     335  
     336  static int
     337  _sha1_clear(PyObject *module)
     338  {
     339      SHA1State *state = sha1_get_state(module);
     340      Py_CLEAR(state->sha1_type);
     341      return 0;
     342  }
     343  
     344  static void
     345  _sha1_free(void *module)
     346  {
     347      _sha1_clear((PyObject *)module);
     348  }
     349  
     350  static int
     351  _sha1_exec(PyObject *module)
     352  {
     353      SHA1State* st = sha1_get_state(module);
     354  
     355      st->sha1_type = (PyTypeObject *)PyType_FromModuleAndSpec(
     356          module, &sha1_type_spec, NULL);
     357  
     358      if (st->sha1_type == NULL) {
     359          return -1;
     360      }
     361  
     362      Py_INCREF(st->sha1_type);
     363      if (PyModule_AddObject(module,
     364                             "SHA1Type",
     365                             (PyObject *)st->sha1_type) < 0) {
     366          Py_DECREF(st->sha1_type);
     367          return -1;
     368      }
     369  
     370      return 0;
     371  }
     372  
     373  
     374  /* Initialize this module. */
     375  
     376  static PyModuleDef_Slot _sha1_slots[] = {
     377      {Py_mod_exec, _sha1_exec},
     378      {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
     379      {0, NULL}
     380  };
     381  
     382  static struct PyModuleDef _sha1module = {
     383          PyModuleDef_HEAD_INIT,
     384          .m_name = "_sha1",
     385          .m_size = sizeof(SHA1State),
     386          .m_methods = SHA1_functions,
     387          .m_slots = _sha1_slots,
     388          .m_traverse = _sha1_traverse,
     389          .m_clear = _sha1_clear,
     390          .m_free = _sha1_free
     391  };
     392  
     393  PyMODINIT_FUNC
     394  PyInit__sha1(void)
     395  {
     396      return PyModuleDef_Init(&_sha1module);
     397  }