(root)/
Python-3.12.0/
Modules/
_blake2/
blake2b_impl.c
       1  /*
       2   * Written in 2013 by Dmitry Chestnykh <dmitry@codingrobots.com>
       3   * Modified for CPython by Christian Heimes <christian@python.org>
       4   *
       5   * To the extent possible under law, the author have dedicated all
       6   * copyright and related and neighboring rights to this software to
       7   * the public domain worldwide. This software is distributed without
       8   * any warranty. http://creativecommons.org/publicdomain/zero/1.0/
       9   */
      10  
      11  /* WARNING: autogenerated file!
      12   *
      13   * The blake2s_impl.c is autogenerated from blake2b_impl.c.
      14   */
      15  
      16  #ifndef Py_BUILD_CORE_BUILTIN
      17  #  define Py_BUILD_CORE_MODULE 1
      18  #endif
      19  
      20  #include "Python.h"
      21  #include "pycore_strhex.h"       // _Py_strhex()
      22  
      23  #include "../hashlib.h"
      24  #include "blake2module.h"
      25  
      26  #ifndef HAVE_LIBB2
      27  /* pure SSE2 implementation is very slow, so only use the more optimized SSSE3+
      28   * https://bugs.python.org/issue31834 */
      29  #if defined(__SSSE3__) || defined(__SSE4_1__) || defined(__AVX__) || defined(__XOP__)
      30  #include "impl/blake2b.c"
      31  #else
      32  #include "impl/blake2b-ref.c"
      33  #endif
      34  #endif // !HAVE_LIBB2
      35  
      36  #define HAVE_BLAKE2B 1
      37  
      38  extern PyType_Spec blake2b_type_spec;
      39  
      40  
      41  typedef struct {
      42      PyObject_HEAD
      43      blake2b_param    param;
      44      blake2b_state    state;
      45      PyThread_type_lock lock;
      46  } BLAKE2bObject;
      47  
      48  #include "clinic/blake2b_impl.c.h"
      49  
      50  /*[clinic input]
      51  module _blake2
      52  class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType"
      53  [clinic start generated code]*/
      54  /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/
      55  
      56  
      57  static BLAKE2bObject *
      58  new_BLAKE2bObject(PyTypeObject *type)
      59  {
      60      BLAKE2bObject *self;
      61      self = (BLAKE2bObject *)type->tp_alloc(type, 0);
      62      if (self != NULL) {
      63          self->lock = NULL;
      64      }
      65      return self;
      66  }
      67  
      68  /*[clinic input]
      69  @classmethod
      70  _blake2.blake2b.__new__ as py_blake2b_new
      71      data: object(c_default="NULL") = b''
      72      /
      73      *
      74      digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
      75      key: Py_buffer(c_default="NULL", py_default="b''") = None
      76      salt: Py_buffer(c_default="NULL", py_default="b''") = None
      77      person: Py_buffer(c_default="NULL", py_default="b''") = None
      78      fanout: int = 1
      79      depth: int = 1
      80      leaf_size: unsigned_long = 0
      81      node_offset: unsigned_long_long = 0
      82      node_depth: int = 0
      83      inner_size: int = 0
      84      last_node: bool = False
      85      usedforsecurity: bool = True
      86  
      87  Return a new BLAKE2b hash object.
      88  [clinic start generated code]*/
      89  
      90  static PyObject *
      91  py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
      92                      Py_buffer *key, Py_buffer *salt, Py_buffer *person,
      93                      int fanout, int depth, unsigned long leaf_size,
      94                      unsigned long long node_offset, int node_depth,
      95                      int inner_size, int last_node, int usedforsecurity)
      96  /*[clinic end generated code: output=32bfd8f043c6896f input=b947312abff46977]*/
      97  {
      98      BLAKE2bObject *self = NULL;
      99      Py_buffer buf;
     100  
     101      self = new_BLAKE2bObject(type);
     102      if (self == NULL) {
     103          goto error;
     104      }
     105  
     106      /* Zero parameter block. */
     107      memset(&self->param, 0, sizeof(self->param));
     108  
     109      /* Set digest size. */
     110      if (digest_size <= 0 || digest_size > BLAKE2B_OUTBYTES) {
     111          PyErr_Format(PyExc_ValueError,
     112                  "digest_size must be between 1 and %d bytes",
     113                  BLAKE2B_OUTBYTES);
     114          goto error;
     115      }
     116      self->param.digest_length = digest_size;
     117  
     118      /* Set salt parameter. */
     119      if ((salt->obj != NULL) && salt->len) {
     120          if (salt->len > BLAKE2B_SALTBYTES) {
     121              PyErr_Format(PyExc_ValueError,
     122                  "maximum salt length is %d bytes",
     123                  BLAKE2B_SALTBYTES);
     124              goto error;
     125          }
     126          memcpy(self->param.salt, salt->buf, salt->len);
     127      }
     128  
     129      /* Set personalization parameter. */
     130      if ((person->obj != NULL) && person->len) {
     131          if (person->len > BLAKE2B_PERSONALBYTES) {
     132              PyErr_Format(PyExc_ValueError,
     133                  "maximum person length is %d bytes",
     134                  BLAKE2B_PERSONALBYTES);
     135              goto error;
     136          }
     137          memcpy(self->param.personal, person->buf, person->len);
     138      }
     139  
     140      /* Set tree parameters. */
     141      if (fanout < 0 || fanout > 255) {
     142          PyErr_SetString(PyExc_ValueError,
     143                  "fanout must be between 0 and 255");
     144          goto error;
     145      }
     146      self->param.fanout = (uint8_t)fanout;
     147  
     148      if (depth <= 0 || depth > 255) {
     149          PyErr_SetString(PyExc_ValueError,
     150                  "depth must be between 1 and 255");
     151          goto error;
     152      }
     153      self->param.depth = (uint8_t)depth;
     154  
     155      if (leaf_size > 0xFFFFFFFFU) {
     156          PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
     157          goto error;
     158      }
     159      // NB: Simple assignment here would be incorrect on big endian platforms.
     160      store32(&(self->param.leaf_length), leaf_size);
     161  
     162  #ifdef HAVE_BLAKE2S
     163      if (node_offset > 0xFFFFFFFFFFFFULL) {
     164          /* maximum 2**48 - 1 */
     165           PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
     166           goto error;
     167       }
     168      store48(&(self->param.node_offset), node_offset);
     169  #else
     170      // NB: Simple assignment here would be incorrect on big endian platforms.
     171      store64(&(self->param.node_offset), node_offset);
     172  #endif
     173  
     174      if (node_depth < 0 || node_depth > 255) {
     175          PyErr_SetString(PyExc_ValueError,
     176                  "node_depth must be between 0 and 255");
     177          goto error;
     178      }
     179      self->param.node_depth = node_depth;
     180  
     181      if (inner_size < 0 || inner_size > BLAKE2B_OUTBYTES) {
     182          PyErr_Format(PyExc_ValueError,
     183                  "inner_size must be between 0 and is %d",
     184                  BLAKE2B_OUTBYTES);
     185          goto error;
     186      }
     187      self->param.inner_length = inner_size;
     188  
     189      /* Set key length. */
     190      if ((key->obj != NULL) && key->len) {
     191          if (key->len > BLAKE2B_KEYBYTES) {
     192              PyErr_Format(PyExc_ValueError,
     193                  "maximum key length is %d bytes",
     194                  BLAKE2B_KEYBYTES);
     195              goto error;
     196          }
     197          self->param.key_length = (uint8_t)key->len;
     198      }
     199  
     200      /* Initialize hash state. */
     201      if (blake2b_init_param(&self->state, &self->param) < 0) {
     202          PyErr_SetString(PyExc_RuntimeError,
     203                  "error initializing hash state");
     204          goto error;
     205      }
     206  
     207      /* Set last node flag (must come after initialization). */
     208      self->state.last_node = last_node;
     209  
     210      /* Process key block if any. */
     211      if (self->param.key_length) {
     212          uint8_t block[BLAKE2B_BLOCKBYTES];
     213          memset(block, 0, sizeof(block));
     214          memcpy(block, key->buf, key->len);
     215          blake2b_update(&self->state, block, sizeof(block));
     216          secure_zero_memory(block, sizeof(block));
     217      }
     218  
     219      /* Process initial data if any. */
     220      if (data != NULL) {
     221          GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
     222  
     223          if (buf.len >= HASHLIB_GIL_MINSIZE) {
     224              Py_BEGIN_ALLOW_THREADS
     225              blake2b_update(&self->state, buf.buf, buf.len);
     226              Py_END_ALLOW_THREADS
     227          } else {
     228              blake2b_update(&self->state, buf.buf, buf.len);
     229          }
     230          PyBuffer_Release(&buf);
     231      }
     232  
     233      return (PyObject *)self;
     234  
     235    error:
     236      if (self != NULL) {
     237          Py_DECREF(self);
     238      }
     239      return NULL;
     240  }
     241  
     242  /*[clinic input]
     243  _blake2.blake2b.copy
     244  
     245  Return a copy of the hash object.
     246  [clinic start generated code]*/
     247  
     248  static PyObject *
     249  _blake2_blake2b_copy_impl(BLAKE2bObject *self)
     250  /*[clinic end generated code: output=ff6acee5f93656ae input=e383c2d199fd8a2e]*/
     251  {
     252      BLAKE2bObject *cpy;
     253  
     254      if ((cpy = new_BLAKE2bObject(Py_TYPE(self))) == NULL)
     255          return NULL;
     256  
     257      ENTER_HASHLIB(self);
     258      cpy->param = self->param;
     259      cpy->state = self->state;
     260      LEAVE_HASHLIB(self);
     261      return (PyObject *)cpy;
     262  }
     263  
     264  /*[clinic input]
     265  _blake2.blake2b.update
     266  
     267      data: object
     268      /
     269  
     270  Update this hash object's state with the provided bytes-like object.
     271  [clinic start generated code]*/
     272  
     273  static PyObject *
     274  _blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
     275  /*[clinic end generated code: output=010dfcbe22654359 input=ffc4aa6a6a225d31]*/
     276  {
     277      Py_buffer buf;
     278  
     279      GET_BUFFER_VIEW_OR_ERROUT(data, &buf);
     280  
     281      if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
     282          self->lock = PyThread_allocate_lock();
     283  
     284      if (self->lock != NULL) {
     285         Py_BEGIN_ALLOW_THREADS
     286         PyThread_acquire_lock(self->lock, 1);
     287         blake2b_update(&self->state, buf.buf, buf.len);
     288         PyThread_release_lock(self->lock);
     289         Py_END_ALLOW_THREADS
     290      } else {
     291          blake2b_update(&self->state, buf.buf, buf.len);
     292      }
     293      PyBuffer_Release(&buf);
     294  
     295      Py_RETURN_NONE;
     296  }
     297  
     298  /*[clinic input]
     299  _blake2.blake2b.digest
     300  
     301  Return the digest value as a bytes object.
     302  [clinic start generated code]*/
     303  
     304  static PyObject *
     305  _blake2_blake2b_digest_impl(BLAKE2bObject *self)
     306  /*[clinic end generated code: output=a5864660f4bfc61a input=7d21659e9c5fff02]*/
     307  {
     308      uint8_t digest[BLAKE2B_OUTBYTES];
     309      blake2b_state state_cpy;
     310  
     311      ENTER_HASHLIB(self);
     312      state_cpy = self->state;
     313      blake2b_final(&state_cpy, digest, self->param.digest_length);
     314      LEAVE_HASHLIB(self);
     315      return PyBytes_FromStringAndSize((const char *)digest,
     316              self->param.digest_length);
     317  }
     318  
     319  /*[clinic input]
     320  _blake2.blake2b.hexdigest
     321  
     322  Return the digest value as a string of hexadecimal digits.
     323  [clinic start generated code]*/
     324  
     325  static PyObject *
     326  _blake2_blake2b_hexdigest_impl(BLAKE2bObject *self)
     327  /*[clinic end generated code: output=b5598a87d8794a60 input=76930f6946351f56]*/
     328  {
     329      uint8_t digest[BLAKE2B_OUTBYTES];
     330      blake2b_state state_cpy;
     331  
     332      ENTER_HASHLIB(self);
     333      state_cpy = self->state;
     334      blake2b_final(&state_cpy, digest, self->param.digest_length);
     335      LEAVE_HASHLIB(self);
     336      return _Py_strhex((const char *)digest, self->param.digest_length);
     337  }
     338  
     339  
     340  static PyMethodDef py_blake2b_methods[] = {
     341      _BLAKE2_BLAKE2B_COPY_METHODDEF
     342      _BLAKE2_BLAKE2B_DIGEST_METHODDEF
     343      _BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF
     344      _BLAKE2_BLAKE2B_UPDATE_METHODDEF
     345      {NULL, NULL}
     346  };
     347  
     348  
     349  
     350  static PyObject *
     351  py_blake2b_get_name(BLAKE2bObject *self, void *closure)
     352  {
     353      return PyUnicode_FromString("blake2b");
     354  }
     355  
     356  
     357  
     358  static PyObject *
     359  py_blake2b_get_block_size(BLAKE2bObject *self, void *closure)
     360  {
     361      return PyLong_FromLong(BLAKE2B_BLOCKBYTES);
     362  }
     363  
     364  
     365  
     366  static PyObject *
     367  py_blake2b_get_digest_size(BLAKE2bObject *self, void *closure)
     368  {
     369      return PyLong_FromLong(self->param.digest_length);
     370  }
     371  
     372  
     373  static PyGetSetDef py_blake2b_getsetters[] = {
     374      {"name", (getter)py_blake2b_get_name,
     375          NULL, NULL, NULL},
     376      {"block_size", (getter)py_blake2b_get_block_size,
     377          NULL, NULL, NULL},
     378      {"digest_size", (getter)py_blake2b_get_digest_size,
     379          NULL, NULL, NULL},
     380      {NULL}
     381  };
     382  
     383  
     384  static void
     385  py_blake2b_dealloc(PyObject *self)
     386  {
     387      BLAKE2bObject *obj = (BLAKE2bObject *)self;
     388  
     389      /* Try not to leave state in memory. */
     390      secure_zero_memory(&obj->param, sizeof(obj->param));
     391      secure_zero_memory(&obj->state, sizeof(obj->state));
     392      if (obj->lock) {
     393          PyThread_free_lock(obj->lock);
     394          obj->lock = NULL;
     395      }
     396  
     397      PyTypeObject *type = Py_TYPE(self);
     398      PyObject_Free(self);
     399      Py_DECREF(type);
     400  }
     401  
     402  static PyType_Slot blake2b_type_slots[] = {
     403      {Py_tp_dealloc, py_blake2b_dealloc},
     404      {Py_tp_doc, (char *)py_blake2b_new__doc__},
     405      {Py_tp_methods, py_blake2b_methods},
     406      {Py_tp_getset, py_blake2b_getsetters},
     407      {Py_tp_new, py_blake2b_new},
     408      {0,0}
     409  };
     410  
     411  PyType_Spec blake2b_type_spec = {
     412      .name = "_blake2.blake2b",
     413      .basicsize =  sizeof(BLAKE2bObject),
     414      .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
     415      .slots = blake2b_type_slots
     416  };