Home | History | Annotate | Download | only in _blake2
      1 /*
      2  * Written in 2013 by Dmitry Chestnykh <dmitry (at) codingrobots.com>
      3  * Modified for CPython by Christian Heimes <christian (at) 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 blake2s_impl.c.
     14  */
     15 
     16 #include "Python.h"
     17 #include "pystrhex.h"
     18 #ifdef WITH_THREAD
     19 #include "pythread.h"
     20 #endif
     21 
     22 #include "../hashlib.h"
     23 #include "blake2ns.h"
     24 
     25 #define HAVE_BLAKE2S 1
     26 #define BLAKE2_LOCAL_INLINE(type) Py_LOCAL_INLINE(type)
     27 
     28 #include "impl/blake2.h"
     29 #include "impl/blake2-impl.h" /* for secure_zero_memory() and store48() */
     30 
     31 #ifdef BLAKE2_USE_SSE
     32 #include "impl/blake2s.c"
     33 #else
     34 #include "impl/blake2s-ref.c"
     35 #endif
     36 
     37 
     38 extern PyTypeObject PyBlake2_BLAKE2sType;
     39 
     40 typedef struct {
     41     PyObject_HEAD
     42     blake2s_param    param;
     43     blake2s_state    state;
     44 #ifdef WITH_THREAD
     45     PyThread_type_lock lock;
     46 #endif
     47 } BLAKE2sObject;
     48 
     49 #include "clinic/blake2s_impl.c.h"
     50 
     51 /*[clinic input]
     52 module _blake2s
     53 class _blake2s.blake2s "BLAKE2sObject *" "&PyBlake2_BLAKE2sType"
     54 [clinic start generated code]*/
     55 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=edbfcf7557a685a7]*/
     56 
     57 
     58 static BLAKE2sObject *
     59 new_BLAKE2sObject(PyTypeObject *type)
     60 {
     61     BLAKE2sObject *self;
     62     self = (BLAKE2sObject *)type->tp_alloc(type, 0);
     63 #ifdef WITH_THREAD
     64     if (self != NULL) {
     65         self->lock = NULL;
     66     }
     67 #endif
     68     return self;
     69 }
     70 
     71 /*[clinic input]
     72 @classmethod
     73 _blake2s.blake2s.__new__ as py_blake2s_new
     74     string as data: object = NULL
     75     *
     76     digest_size: int(c_default="BLAKE2S_OUTBYTES") = _blake2s.blake2s.MAX_DIGEST_SIZE
     77     key: Py_buffer = None
     78     salt: Py_buffer = None
     79     person: Py_buffer = None
     80     fanout: int = 1
     81     depth: int = 1
     82     leaf_size as leaf_size_obj: object = NULL
     83     node_offset as node_offset_obj: object = NULL
     84     node_depth: int = 0
     85     inner_size: int = 0
     86     last_node: bool = False
     87 
     88 Return a new BLAKE2s hash object.
     89 [clinic start generated code]*/
     90 
     91 static PyObject *
     92 py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
     93                     Py_buffer *key, Py_buffer *salt, Py_buffer *person,
     94                     int fanout, int depth, PyObject *leaf_size_obj,
     95                     PyObject *node_offset_obj, int node_depth,
     96                     int inner_size, int last_node)
     97 /*[clinic end generated code: output=fe060b258a8cbfc6 input=458cfdcb3d0d47ff]*/
     98 {
     99     BLAKE2sObject *self = NULL;
    100     Py_buffer buf;
    101 
    102     unsigned long leaf_size = 0;
    103     unsigned long long node_offset = 0;
    104 
    105     self = new_BLAKE2sObject(type);
    106     if (self == NULL) {
    107         goto error;
    108     }
    109 
    110     /* Zero parameter block. */
    111     memset(&self->param, 0, sizeof(self->param));
    112 
    113     /* Set digest size. */
    114     if (digest_size <= 0 || digest_size > BLAKE2S_OUTBYTES) {
    115         PyErr_Format(PyExc_ValueError,
    116                 "digest_size must be between 1 and %d bytes",
    117                 BLAKE2S_OUTBYTES);
    118         goto error;
    119     }
    120     self->param.digest_length = digest_size;
    121 
    122     /* Set salt parameter. */
    123     if ((salt->obj != NULL) && salt->len) {
    124         if (salt->len > BLAKE2S_SALTBYTES) {
    125             PyErr_Format(PyExc_ValueError,
    126                 "maximum salt length is %d bytes",
    127                 BLAKE2S_SALTBYTES);
    128             goto error;
    129         }
    130         memcpy(self->param.salt, salt->buf, salt->len);
    131     }
    132 
    133     /* Set personalization parameter. */
    134     if ((person->obj != NULL) && person->len) {
    135         if (person->len > BLAKE2S_PERSONALBYTES) {
    136             PyErr_Format(PyExc_ValueError,
    137                 "maximum person length is %d bytes",
    138                 BLAKE2S_PERSONALBYTES);
    139             goto error;
    140         }
    141         memcpy(self->param.personal, person->buf, person->len);
    142     }
    143 
    144     /* Set tree parameters. */
    145     if (fanout < 0 || fanout > 255) {
    146         PyErr_SetString(PyExc_ValueError,
    147                 "fanout must be between 0 and 255");
    148         goto error;
    149     }
    150     self->param.fanout = (uint8_t)fanout;
    151 
    152     if (depth <= 0 || depth > 255) {
    153         PyErr_SetString(PyExc_ValueError,
    154                 "depth must be between 1 and 255");
    155         goto error;
    156     }
    157     self->param.depth = (uint8_t)depth;
    158 
    159     if (leaf_size_obj != NULL) {
    160         leaf_size = PyLong_AsUnsignedLong(leaf_size_obj);
    161         if (leaf_size == (unsigned long) -1 && PyErr_Occurred()) {
    162             goto error;
    163         }
    164         if (leaf_size > 0xFFFFFFFFU) {
    165             PyErr_SetString(PyExc_OverflowError, "leaf_size is too large");
    166             goto error;
    167         }
    168     }
    169     self->param.leaf_length = (unsigned int)leaf_size;
    170 
    171     if (node_offset_obj != NULL) {
    172         node_offset = PyLong_AsUnsignedLongLong(node_offset_obj);
    173         if (node_offset == (unsigned long long) -1 && PyErr_Occurred()) {
    174             goto error;
    175         }
    176     }
    177 #ifdef HAVE_BLAKE2S
    178     if (node_offset > 0xFFFFFFFFFFFFULL) {
    179         /* maximum 2**48 - 1 */
    180          PyErr_SetString(PyExc_OverflowError, "node_offset is too large");
    181          goto error;
    182      }
    183     store48(&(self->param.node_offset), node_offset);
    184 #else
    185     self->param.node_offset = node_offset;
    186 #endif
    187 
    188     if (node_depth < 0 || node_depth > 255) {
    189         PyErr_SetString(PyExc_ValueError,
    190                 "node_depth must be between 0 and 255");
    191         goto error;
    192     }
    193     self->param.node_depth = node_depth;
    194 
    195     if (inner_size < 0 || inner_size > BLAKE2S_OUTBYTES) {
    196         PyErr_Format(PyExc_ValueError,
    197                 "inner_size must be between 0 and is %d",
    198                 BLAKE2S_OUTBYTES);
    199         goto error;
    200     }
    201     self->param.inner_length = inner_size;
    202 
    203     /* Set key length. */
    204     if ((key->obj != NULL) && key->len) {
    205         if (key->len > BLAKE2S_KEYBYTES) {
    206             PyErr_Format(PyExc_ValueError,
    207                 "maximum key length is %d bytes",
    208                 BLAKE2S_KEYBYTES);
    209             goto error;
    210         }
    211         self->param.key_length = (uint8_t)key->len;
    212     }
    213 
    214     /* Initialize hash state. */
    215     if (blake2s_init_param(&self->state, &self->param) < 0) {
    216         PyErr_SetString(PyExc_RuntimeError,
    217                 "error initializing hash state");
    218         goto error;
    219     }
    220 
    221     /* Set last node flag (must come after initialization). */
    222     self->state.last_node = last_node;
    223 
    224     /* Process key block if any. */
    225     if (self->param.key_length) {
    226         uint8_t block[BLAKE2S_BLOCKBYTES];
    227         memset(block, 0, sizeof(block));
    228         memcpy(block, key->buf, key->len);
    229         blake2s_update(&self->state, block, sizeof(block));
    230         secure_zero_memory(block, sizeof(block));
    231     }
    232 
    233     /* Process initial data if any. */
    234     if (data != NULL) {
    235         GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error);
    236 
    237         if (buf.len >= HASHLIB_GIL_MINSIZE) {
    238             Py_BEGIN_ALLOW_THREADS
    239             blake2s_update(&self->state, buf.buf, buf.len);
    240             Py_END_ALLOW_THREADS
    241         } else {
    242             blake2s_update(&self->state, buf.buf, buf.len);
    243         }
    244         PyBuffer_Release(&buf);
    245     }
    246 
    247     return (PyObject *)self;
    248 
    249   error:
    250     if (self != NULL) {
    251         Py_DECREF(self);
    252     }
    253     return NULL;
    254 }
    255 
    256 /*[clinic input]
    257 _blake2s.blake2s.copy
    258 
    259 Return a copy of the hash object.
    260 [clinic start generated code]*/
    261 
    262 static PyObject *
    263 _blake2s_blake2s_copy_impl(BLAKE2sObject *self)
    264 /*[clinic end generated code: output=6c5bada404b7aed7 input=c8858e887ae4a07a]*/
    265 {
    266     BLAKE2sObject *cpy;
    267 
    268     if ((cpy = new_BLAKE2sObject(Py_TYPE(self))) == NULL)
    269         return NULL;
    270 
    271     ENTER_HASHLIB(self);
    272     cpy->param = self->param;
    273     cpy->state = self->state;
    274     LEAVE_HASHLIB(self);
    275     return (PyObject *)cpy;
    276 }
    277 
    278 /*[clinic input]
    279 _blake2s.blake2s.update
    280 
    281     obj: object
    282     /
    283 
    284 Update this hash object's state with the provided string.
    285 [clinic start generated code]*/
    286 
    287 static PyObject *
    288 _blake2s_blake2s_update(BLAKE2sObject *self, PyObject *obj)
    289 /*[clinic end generated code: output=fe8438a1d3cede87 input=47a408b9a3cc05c5]*/
    290 {
    291     Py_buffer buf;
    292 
    293     GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
    294 
    295 #ifdef WITH_THREAD
    296     if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
    297         self->lock = PyThread_allocate_lock();
    298 
    299     if (self->lock != NULL) {
    300        Py_BEGIN_ALLOW_THREADS
    301        PyThread_acquire_lock(self->lock, 1);
    302        blake2s_update(&self->state, buf.buf, buf.len);
    303        PyThread_release_lock(self->lock);
    304        Py_END_ALLOW_THREADS
    305     } else {
    306         blake2s_update(&self->state, buf.buf, buf.len);
    307     }
    308 #else
    309     blake2s_update(&self->state, buf.buf, buf.len);
    310 #endif /* !WITH_THREAD */
    311     PyBuffer_Release(&buf);
    312 
    313     Py_INCREF(Py_None);
    314     return Py_None;
    315 }
    316 
    317 /*[clinic input]
    318 _blake2s.blake2s.digest
    319 
    320 Return the digest value as a string of binary data.
    321 [clinic start generated code]*/
    322 
    323 static PyObject *
    324 _blake2s_blake2s_digest_impl(BLAKE2sObject *self)
    325 /*[clinic end generated code: output=80e81a48c6f79cf9 input=feb9a220135bdeba]*/
    326 {
    327     uint8_t digest[BLAKE2S_OUTBYTES];
    328     blake2s_state state_cpy;
    329 
    330     ENTER_HASHLIB(self);
    331     state_cpy = self->state;
    332     blake2s_final(&state_cpy, digest, self->param.digest_length);
    333     LEAVE_HASHLIB(self);
    334     return PyBytes_FromStringAndSize((const char *)digest,
    335             self->param.digest_length);
    336 }
    337 
    338 /*[clinic input]
    339 _blake2s.blake2s.hexdigest
    340 
    341 Return the digest value as a string of hexadecimal digits.
    342 [clinic start generated code]*/
    343 
    344 static PyObject *
    345 _blake2s_blake2s_hexdigest_impl(BLAKE2sObject *self)
    346 /*[clinic end generated code: output=db6c5028c0a3c2e5 input=4e4877b8bd7aea91]*/
    347 {
    348     uint8_t digest[BLAKE2S_OUTBYTES];
    349     blake2s_state state_cpy;
    350 
    351     ENTER_HASHLIB(self);
    352     state_cpy = self->state;
    353     blake2s_final(&state_cpy, digest, self->param.digest_length);
    354     LEAVE_HASHLIB(self);
    355     return _Py_strhex((const char *)digest, self->param.digest_length);
    356 }
    357 
    358 
    359 static PyMethodDef py_blake2s_methods[] = {
    360     _BLAKE2S_BLAKE2S_COPY_METHODDEF
    361     _BLAKE2S_BLAKE2S_DIGEST_METHODDEF
    362     _BLAKE2S_BLAKE2S_HEXDIGEST_METHODDEF
    363     _BLAKE2S_BLAKE2S_UPDATE_METHODDEF
    364     {NULL, NULL}
    365 };
    366 
    367 
    368 
    369 static PyObject *
    370 py_blake2s_get_name(BLAKE2sObject *self, void *closure)
    371 {
    372     return PyUnicode_FromString("blake2s");
    373 }
    374 
    375 
    376 
    377 static PyObject *
    378 py_blake2s_get_block_size(BLAKE2sObject *self, void *closure)
    379 {
    380     return PyLong_FromLong(BLAKE2S_BLOCKBYTES);
    381 }
    382 
    383 
    384 
    385 static PyObject *
    386 py_blake2s_get_digest_size(BLAKE2sObject *self, void *closure)
    387 {
    388     return PyLong_FromLong(self->param.digest_length);
    389 }
    390 
    391 
    392 static PyGetSetDef py_blake2s_getsetters[] = {
    393     {"name", (getter)py_blake2s_get_name,
    394         NULL, NULL, NULL},
    395     {"block_size", (getter)py_blake2s_get_block_size,
    396         NULL, NULL, NULL},
    397     {"digest_size", (getter)py_blake2s_get_digest_size,
    398         NULL, NULL, NULL},
    399     {NULL}
    400 };
    401 
    402 
    403 static void
    404 py_blake2s_dealloc(PyObject *self)
    405 {
    406     BLAKE2sObject *obj = (BLAKE2sObject *)self;
    407 
    408     /* Try not to leave state in memory. */
    409     secure_zero_memory(&obj->param, sizeof(obj->param));
    410     secure_zero_memory(&obj->state, sizeof(obj->state));
    411 #ifdef WITH_THREAD
    412     if (obj->lock) {
    413         PyThread_free_lock(obj->lock);
    414         obj->lock = NULL;
    415     }
    416 #endif
    417     PyObject_Del(self);
    418 }
    419 
    420 
    421 PyTypeObject PyBlake2_BLAKE2sType = {
    422     PyVarObject_HEAD_INIT(NULL, 0)
    423     "_blake2.blake2s",        /* tp_name            */
    424     sizeof(BLAKE2sObject),    /* tp_size            */
    425     0,                        /* tp_itemsize        */
    426     py_blake2s_dealloc,       /* tp_dealloc         */
    427     0,                        /* tp_print           */
    428     0,                        /* tp_getattr         */
    429     0,                        /* tp_setattr         */
    430     0,                        /* tp_compare         */
    431     0,                        /* tp_repr            */
    432     0,                        /* tp_as_number       */
    433     0,                        /* tp_as_sequence     */
    434     0,                        /* tp_as_mapping      */
    435     0,                        /* tp_hash            */
    436     0,                        /* tp_call            */
    437     0,                        /* tp_str             */
    438     0,                        /* tp_getattro        */
    439     0,                        /* tp_setattro        */
    440     0,                        /* tp_as_buffer       */
    441     Py_TPFLAGS_DEFAULT,       /* tp_flags           */
    442     py_blake2s_new__doc__,    /* tp_doc             */
    443     0,                        /* tp_traverse        */
    444     0,                        /* tp_clear           */
    445     0,                        /* tp_richcompare     */
    446     0,                        /* tp_weaklistoffset  */
    447     0,                        /* tp_iter            */
    448     0,                        /* tp_iternext        */
    449     py_blake2s_methods,       /* tp_methods         */
    450     0,                        /* tp_members         */
    451     py_blake2s_getsetters,    /* tp_getset          */
    452     0,                        /* tp_base            */
    453     0,                        /* tp_dict            */
    454     0,                        /* tp_descr_get       */
    455     0,                        /* tp_descr_set       */
    456     0,                        /* tp_dictoffset      */
    457     0,                        /* tp_init            */
    458     0,                        /* tp_alloc           */
    459     py_blake2s_new,           /* tp_new             */
    460 };
    461