Christian Heimes | 121b948 | 2016-09-06 22:03:25 +0200 | [diff] [blame] | 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 | #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_BLAKE2B 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/blake2b.c" |
| 33 | #else |
| 34 | #include "impl/blake2b-ref.c" |
| 35 | #endif |
| 36 | |
| 37 | |
| 38 | extern PyTypeObject PyBlake2_BLAKE2bType; |
| 39 | |
| 40 | typedef struct { |
| 41 | PyObject_HEAD |
| 42 | blake2b_param param; |
| 43 | blake2b_state state; |
| 44 | #ifdef WITH_THREAD |
| 45 | PyThread_type_lock lock; |
| 46 | #endif |
| 47 | } BLAKE2bObject; |
| 48 | |
| 49 | #include "clinic/blake2b_impl.c.h" |
| 50 | |
| 51 | /*[clinic input] |
| 52 | module _blake2b |
| 53 | class _blake2b.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType" |
| 54 | [clinic start generated code]*/ |
| 55 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6893358c6622aecf]*/ |
| 56 | |
| 57 | |
| 58 | static BLAKE2bObject * |
| 59 | new_BLAKE2bObject(PyTypeObject *type) |
| 60 | { |
| 61 | BLAKE2bObject *self; |
| 62 | self = (BLAKE2bObject *)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 | _blake2b.blake2b.__new__ as py_blake2b_new |
| 74 | string as data: object = NULL |
| 75 | * |
| 76 | digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2b.blake2b.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 BLAKE2b hash object. |
| 89 | [clinic start generated code]*/ |
| 90 | |
| 91 | static PyObject * |
| 92 | py_blake2b_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=7506d8d890e5f13b input=e41548dfa0866031]*/ |
| 98 | { |
| 99 | BLAKE2bObject *self = NULL; |
| 100 | Py_buffer buf; |
| 101 | |
| 102 | unsigned long leaf_size = 0; |
Benjamin Peterson | 47ff073 | 2016-09-08 09:15:54 -0700 | [diff] [blame] | 103 | unsigned long long node_offset = 0; |
Christian Heimes | 121b948 | 2016-09-06 22:03:25 +0200 | [diff] [blame] | 104 | |
| 105 | self = new_BLAKE2bObject(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 > BLAKE2B_OUTBYTES) { |
| 115 | PyErr_Format(PyExc_ValueError, |
| 116 | "digest_size must be between 1 and %d bytes", |
| 117 | BLAKE2B_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 > BLAKE2B_SALTBYTES) { |
| 125 | PyErr_Format(PyExc_ValueError, |
| 126 | "maximum salt length is %d bytes", |
| 127 | BLAKE2B_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 > BLAKE2B_PERSONALBYTES) { |
| 136 | PyErr_Format(PyExc_ValueError, |
| 137 | "maximum person length is %d bytes", |
| 138 | BLAKE2B_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); |
Benjamin Peterson | 47ff073 | 2016-09-08 09:15:54 -0700 | [diff] [blame] | 173 | if (node_offset == (unsigned long long) -1 && PyErr_Occurred()) { |
Christian Heimes | 121b948 | 2016-09-06 22:03:25 +0200 | [diff] [blame] | 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 > BLAKE2B_OUTBYTES) { |
| 196 | PyErr_Format(PyExc_ValueError, |
| 197 | "inner_size must be between 0 and is %d", |
| 198 | BLAKE2B_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 > BLAKE2B_KEYBYTES) { |
| 206 | PyErr_Format(PyExc_ValueError, |
| 207 | "maximum key length is %d bytes", |
| 208 | BLAKE2B_KEYBYTES); |
| 209 | goto error; |
| 210 | } |
Christian Heimes | cc554b6 | 2016-09-07 02:49:11 +0200 | [diff] [blame] | 211 | self->param.key_length = (uint8_t)key->len; |
Christian Heimes | 121b948 | 2016-09-06 22:03:25 +0200 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | /* Initialize hash state. */ |
| 215 | if (blake2b_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[BLAKE2B_BLOCKBYTES]; |
| 227 | memset(block, 0, sizeof(block)); |
| 228 | memcpy(block, key->buf, key->len); |
| 229 | blake2b_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 | blake2b_update(&self->state, buf.buf, buf.len); |
| 240 | Py_END_ALLOW_THREADS |
| 241 | } else { |
| 242 | blake2b_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 | _blake2b.blake2b.copy |
| 258 | |
| 259 | Return a copy of the hash object. |
| 260 | [clinic start generated code]*/ |
| 261 | |
| 262 | static PyObject * |
| 263 | _blake2b_blake2b_copy_impl(BLAKE2bObject *self) |
| 264 | /*[clinic end generated code: output=c89cd33550ab1543 input=4c9c319f18f10747]*/ |
| 265 | { |
| 266 | BLAKE2bObject *cpy; |
| 267 | |
| 268 | if ((cpy = new_BLAKE2bObject(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 | _blake2b.blake2b.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 | _blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj) |
| 289 | /*[clinic end generated code: output=a888f07c4cddbe94 input=3ecb8c13ee4260f2]*/ |
| 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 | blake2b_update(&self->state, buf.buf, buf.len); |
| 303 | PyThread_release_lock(self->lock); |
| 304 | Py_END_ALLOW_THREADS |
| 305 | } else { |
| 306 | blake2b_update(&self->state, buf.buf, buf.len); |
| 307 | } |
| 308 | #else |
| 309 | blake2b_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 | _blake2b.blake2b.digest |
| 319 | |
| 320 | Return the digest value as a string of binary data. |
| 321 | [clinic start generated code]*/ |
| 322 | |
| 323 | static PyObject * |
| 324 | _blake2b_blake2b_digest_impl(BLAKE2bObject *self) |
| 325 | /*[clinic end generated code: output=b13a79360d984740 input=ac2fa462ebb1b9c7]*/ |
| 326 | { |
| 327 | uint8_t digest[BLAKE2B_OUTBYTES]; |
| 328 | blake2b_state state_cpy; |
| 329 | |
| 330 | ENTER_HASHLIB(self); |
| 331 | state_cpy = self->state; |
| 332 | blake2b_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 | _blake2b.blake2b.hexdigest |
| 340 | |
| 341 | Return the digest value as a string of hexadecimal digits. |
| 342 | [clinic start generated code]*/ |
| 343 | |
| 344 | static PyObject * |
| 345 | _blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self) |
| 346 | /*[clinic end generated code: output=6a503611715b24bd input=d58f0b2f37812e33]*/ |
| 347 | { |
| 348 | uint8_t digest[BLAKE2B_OUTBYTES]; |
| 349 | blake2b_state state_cpy; |
| 350 | |
| 351 | ENTER_HASHLIB(self); |
| 352 | state_cpy = self->state; |
| 353 | blake2b_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_blake2b_methods[] = { |
| 360 | _BLAKE2B_BLAKE2B_COPY_METHODDEF |
| 361 | _BLAKE2B_BLAKE2B_DIGEST_METHODDEF |
| 362 | _BLAKE2B_BLAKE2B_HEXDIGEST_METHODDEF |
| 363 | _BLAKE2B_BLAKE2B_UPDATE_METHODDEF |
| 364 | {NULL, NULL} |
| 365 | }; |
| 366 | |
| 367 | |
| 368 | |
| 369 | static PyObject * |
| 370 | py_blake2b_get_name(BLAKE2bObject *self, void *closure) |
| 371 | { |
| 372 | return PyUnicode_FromString("blake2b"); |
| 373 | } |
| 374 | |
| 375 | |
| 376 | |
| 377 | static PyObject * |
| 378 | py_blake2b_get_block_size(BLAKE2bObject *self, void *closure) |
| 379 | { |
| 380 | return PyLong_FromLong(BLAKE2B_BLOCKBYTES); |
| 381 | } |
| 382 | |
| 383 | |
| 384 | |
| 385 | static PyObject * |
| 386 | py_blake2b_get_digest_size(BLAKE2bObject *self, void *closure) |
| 387 | { |
| 388 | return PyLong_FromLong(self->param.digest_length); |
| 389 | } |
| 390 | |
| 391 | |
| 392 | static PyGetSetDef py_blake2b_getsetters[] = { |
| 393 | {"name", (getter)py_blake2b_get_name, |
| 394 | NULL, NULL, NULL}, |
| 395 | {"block_size", (getter)py_blake2b_get_block_size, |
| 396 | NULL, NULL, NULL}, |
| 397 | {"digest_size", (getter)py_blake2b_get_digest_size, |
| 398 | NULL, NULL, NULL}, |
| 399 | {NULL} |
| 400 | }; |
| 401 | |
| 402 | |
| 403 | static void |
| 404 | py_blake2b_dealloc(PyObject *self) |
| 405 | { |
| 406 | BLAKE2bObject *obj = (BLAKE2bObject *)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_BLAKE2bType = { |
| 422 | PyVarObject_HEAD_INIT(NULL, 0) |
| 423 | "_blake2.blake2b", /* tp_name */ |
| 424 | sizeof(BLAKE2bObject), /* tp_size */ |
| 425 | 0, /* tp_itemsize */ |
| 426 | py_blake2b_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_blake2b_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_blake2b_methods, /* tp_methods */ |
| 450 | 0, /* tp_members */ |
| 451 | py_blake2b_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_blake2b_new, /* tp_new */ |
| 460 | }; |