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