diff --git a/whirlpool/pywhirlpool.c b/whirlpool/pywhirlpool.c index 643bf13..9ec950f 100644 --- a/whirlpool/pywhirlpool.c +++ b/whirlpool/pywhirlpool.c @@ -1,42 +1,34 @@ -/** +/* * This is just a wrapper to the Whirlpool hashing function. * The Whirlpool reference implementations are public domain, * as is this code. - * - * Wrapper written by James Cleveland with help from #python - * on irc.freenode.net - * - * Wrapper extended to use the hashlib interface and ported to - * Python 3 by Olaf Conradi. */ - #include #include "Whirlpool.c" #if PY_MAJOR_VERSION >= 3 -#ifndef GET_BUFFER_VIEW_OR_ERROUT -/* Same as defined in hashlib.h */ +#ifndef GET_BUFFER_VIEW_OR_ERROUT /* Same as defined in hashlib.h */ #define GET_BUFFER_VIEW_OR_ERROUT(obj, viewp) do { \ - if (PyUnicode_Check((obj))) { \ - PyErr_SetString(PyExc_TypeError, \ - "Unicode-objects must be encoded before hashing");\ - return NULL; \ - } \ - if (!PyObject_CheckBuffer((obj))) { \ - PyErr_SetString(PyExc_TypeError, \ - "object supporting the buffer API required"); \ - return NULL; \ - } \ - if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \ - return NULL; \ - } \ - if ((viewp)->ndim > 1) { \ - PyErr_SetString(PyExc_BufferError, \ - "Buffer must be single dimension"); \ - PyBuffer_Release((viewp)); \ - return NULL; \ - } \ - } while(0); + if (PyUnicode_Check((obj))) { \ + PyErr_SetString(PyExc_TypeError, \ + "Unicode-objects must be encoded before hashing");\ + return NULL; \ + } \ + if (!PyObject_CheckBuffer((obj))) { \ + PyErr_SetString(PyExc_TypeError, \ + "object supporting the buffer API required"); \ + return NULL; \ + } \ + if (PyObject_GetBuffer((obj), (viewp), PyBUF_SIMPLE) == -1) { \ + return NULL; \ + } \ + if ((viewp)->ndim > 1) { \ + PyErr_SetString(PyExc_BufferError, \ + "Buffer must be single dimension"); \ + PyBuffer_Release((viewp)); \ + return NULL; \ + } \ +} while(0); #endif #endif @@ -46,6 +38,7 @@ #define HEXDIGITS(c) ((c>9) ? c+'a'-10 : c+'0') #endif +// CRITICAL FIX: Add backward compatibility for Py_SET_TYPE #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) #if !defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER < 1900 #define inline __inline @@ -67,19 +60,16 @@ static whirlpoolobject * newwhirlpoolobject(void) { whirlpoolobject *wpp; - wpp = PyObject_New(whirlpoolobject, &Whirlpooltype); if (wpp == NULL) return NULL; - NESSIEinit(&wpp->whirlpool); /* actual initialisation */ return wpp; } /* Whirlpool methods */ -static void -whirlpool_dealloc(whirlpoolobject *wpp) +static void whirlpool_dealloc(whirlpoolobject *wpp) { PyObject_Del(wpp); } @@ -92,7 +82,6 @@ whirlpool_update(whirlpoolobject *self, PyObject *args) Py_buffer view = { 0 }; #if PY_MAJOR_VERSION >= 3 PyObject *obj = NULL; - if (!PyArg_ParseTuple(args, "O:update", &obj)) return NULL; if (obj) @@ -101,33 +90,19 @@ whirlpool_update(whirlpoolobject *self, PyObject *args) if (!PyArg_ParseTuple(args, "s*:update", &view)) return NULL; #endif - - NESSIEadd((unsigned char*)view.buf, - Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8, - &self->whirlpool); - + NESSIEadd((unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8, &self->whirlpool); PyBuffer_Release(&view); Py_RETURN_NONE; } -PyDoc_STRVAR(update_doc, -"update (arg)\n\ -\n\ -Update the whirlpool object with the string arg. Repeated calls are\n\ -equivalent to a single call with the concatenation of all the\n\ -arguments."); - - static PyObject * whirlpool_digest(whirlpoolobject *self) { NESSIEstruct wpContext; unsigned char digest[DIGESTBYTES]; - /* Make a temporary copy, and perform the final */ wpContext = self->whirlpool; NESSIEfinalize(&wpContext, digest); - #if PY_MAJOR_VERSION >= 3 return PyBytes_FromStringAndSize((const char *)digest, sizeof(digest)); #else @@ -135,14 +110,6 @@ whirlpool_digest(whirlpoolobject *self) #endif } -PyDoc_STRVAR(digest_doc, -"digest() -> string of binary data\n\ -\n\ -Return the digest of the strings passed to the update() method so\n\ -far. This is a binary string which may contain non-ASCII characters,\n\ -including null bytes."); - - static PyObject * whirlpool_hexdigest(whirlpoolobject *self) { @@ -155,11 +122,9 @@ whirlpool_hexdigest(whirlpoolobject *self) char *hexdigest; #endif unsigned int i, j; - /* Get the raw (binary) digest value */ wpContext = self->whirlpool; NESSIEfinalize(&wpContext, digest); - /* Create a new string */ #if PY_MAJOR_VERSION >= 3 retval = PyUnicode_New(sizeof(digest) * 2, 127); @@ -168,7 +133,6 @@ whirlpool_hexdigest(whirlpoolobject *self) #endif if (!retval) return NULL; - #if PY_MAJOR_VERSION >= 3 hexdigest = PyUnicode_1BYTE_DATA(retval); #else @@ -178,7 +142,6 @@ whirlpool_hexdigest(whirlpoolobject *self) Py_DECREF(retval); return NULL; } - /* Make hex version of the digest */ for(i=j=0; i string\n\ -\n\ -Like digest(), but returns the digest as a string of hexadecimal digits."); - - static PyObject * whirlpool_copy(whirlpoolobject *self) { whirlpoolobject *wpp; - if ((wpp = newwhirlpoolobject()) == NULL) return NULL; - wpp->whirlpool = self->whirlpool; return (PyObject *)wpp; } -PyDoc_STRVAR(copy_doc, -"copy() -> whirlpool object\n\ -\n\ -Return a copy (``clone'') of the whirlpool object."); - - static PyMethodDef whirlpool_methods[] = { - {"update", (PyCFunction)whirlpool_update, METH_VARARGS, update_doc}, - {"digest", (PyCFunction)whirlpool_digest, METH_NOARGS, digest_doc}, - {"hexdigest", (PyCFunction)whirlpool_hexdigest, METH_NOARGS, hexdigest_doc}, - {"copy", (PyCFunction)whirlpool_copy, METH_NOARGS, copy_doc}, + {"update", (PyCFunction)whirlpool_update, METH_VARARGS, "Update hash with data"}, + {"digest", (PyCFunction)whirlpool_digest, METH_NOARGS, "Return digest as bytes"}, + {"hexdigest", (PyCFunction)whirlpool_hexdigest, METH_NOARGS, "Return digest as hex string"}, + {"copy", (PyCFunction)whirlpool_copy, METH_NOARGS, "Return copy of hash object"}, {NULL, NULL} /* sentinel */ }; - static PyObject * whirlpool_get_block_size(PyObject *self, void *closure) { @@ -254,98 +202,45 @@ whirlpool_get_name(PyObject *self, void *closure) } static PyGetSetDef whirlpool_getseters[] = { - {"digest_size", - (getter)whirlpool_get_digest_size, NULL, - NULL, - NULL}, - {"block_size", - (getter)whirlpool_get_block_size, NULL, - NULL, - NULL}, - {"name", - (getter)whirlpool_get_name, NULL, - NULL, - NULL}, + {"digest_size", (getter)whirlpool_get_digest_size, NULL, NULL, NULL}, + {"block_size", (getter)whirlpool_get_block_size, NULL, NULL, NULL}, + {"name", (getter)whirlpool_get_name, NULL, NULL, NULL}, {NULL} /* sentinel */ }; -#if PY_MAJOR_VERSION >= 3 -PyDoc_STRVAR(module_doc, -"This module implements the interface to the whirlpool message digest\n\ -algorithm. It operates on messages less than 2^256 bits in length,\n\ -and produces a message digest of 512 bits. Its use is quite straighforward:\n\ -use new() to create a whirlpool object. You can now feed this object with\n\ -arbitrary strings using the update() method. At any point you can ask it for\n\ -the digest of the concatenation of the strings fed to it so far.\n\ -\n\ -Functions:\n\ -new([arg]) -- return a new whirlpool object, initialized with arg if provided\n\ -\n\ -Special Objects:\n\ -WhirlpoolType -- type object for whirlpool objects"); -#else -PyDoc_STRVAR(module_doc, -"This module implements the interface to the whirlpool message digest\n\ -algorithm. It operates on messages less than 2^256 bits in length,\n\ -and produces a message digest of 512 bits. Its use is quite straighforward:\n\ -use new() to create a whirlpool object. You can now feed this object with\n\ -arbitrary strings using the update() method. At any point you can ask it for\n\ -the digest of the concatenation of the strings fed to it so far.\n\ -\n\ -Functions:\n\ -new([arg]) -- return a new whirlpool object, initialized with arg if provided\n\ -hash(arg) -- DEPRECATED, returns a whirlpool digest of arg, for backward \ -compatibility\n\ -\n\ -Special Objects:\n\ -WhirlpoolType -- type object for whirlpool objects"); -#endif - -PyDoc_STRVAR(whirlpooltype_doc, -"A whirlpool represents the object used to calculate the WHIRLPOOL checksum of\n\ -a string of information.\n\ -\n\ -Methods:\n\ -update(arg) -- updates the current digest with an additional string\n\ -digest() -- return the current digest value\n\ -hexdigest() -- return the current digest as a string of hexadecimal digits\n\ -copy() -- return a copy of the current whirlpool object"); - static PyTypeObject Whirlpooltype = { PyVarObject_HEAD_INIT(NULL, 0) - "whirlpool.whirlpool", /*tp_name*/ - sizeof(whirlpoolobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ + "whirlpool.whirlpool", /*tp_name*/ + sizeof(whirlpoolobject), /*tp_size*/ + 0, /*tp_itemsize*/ (destructor)whirlpool_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - whirlpooltype_doc, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - whirlpool_methods, /*tp_methods */ - 0, /*tp_members */ - whirlpool_getseters, /*tp_getset */ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Whirlpool hash object", /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + whirlpool_methods, /*tp_methods */ + 0, /*tp_members */ + whirlpool_getseters, /*tp_getset */ }; - /* Whirlpool functions */ static PyObject * @@ -355,7 +250,6 @@ whirlpool_new(PyObject *self, PyObject *args) Py_buffer view = { 0 }; #if PY_MAJOR_VERSION >= 3 PyObject *obj = NULL; - if (!PyArg_ParseTuple(args, "|O:new", &obj)) return NULL; if (obj) @@ -364,50 +258,37 @@ whirlpool_new(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "|s*:new", &view)) return NULL; #endif - if ((wpp = newwhirlpoolobject()) == NULL) { PyBuffer_Release(&view); return NULL; } - if (view.len > 0) { - NESSIEadd((unsigned char*)view.buf, - Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8, - &wpp->whirlpool); + NESSIEadd((unsigned char*)view.buf, Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8, &wpp->whirlpool); } PyBuffer_Release(&view); - return (PyObject *)wpp; } -PyDoc_STRVAR(new_doc, -"new([arg]) -> whirlpool object\n\ -\n\ -Return a new whirlpool object. If arg is present, the method call update(arg)\n\ -is made."); - - /* List of functions exported by this module */ static struct PyMethodDef whirlpool_functions[] = { - {"new", (PyCFunction)whirlpool_new, METH_VARARGS, new_doc}, + {"new", (PyCFunction)whirlpool_new, METH_VARARGS, "Create new whirlpool object"}, {NULL, NULL} /* sentinel */ }; - /* Initialize this module */ #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, - "whirlpool", /* m_name */ - module_doc, /* m_doc */ - -1, /* m_size */ + "whirlpool", /* m_name */ + "Whirlpool hash algorithm implementation", /* m_doc */ + -1, /* m_size */ whirlpool_functions, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ }; #endif @@ -415,24 +296,22 @@ static PyObject * moduleinit(void) { PyObject *m, *d; - + // CRITICAL FIX: Use Py_SET_TYPE instead of direct assignment Py_SET_TYPE(&Whirlpooltype, &PyType_Type); if (PyType_Ready(&Whirlpooltype) < 0) return NULL; - #if PY_MAJOR_VERSION >= 3 m = PyModule_Create(&moduledef); #else - m = Py_InitModule3("whirlpool", whirlpool_functions, module_doc); + m = Py_InitModule3("whirlpool", whirlpool_functions, + "Whirlpool hash module"); #endif if (m == NULL) return NULL; - PyModule_AddIntConstant(m, "digest_size", DIGESTBYTES); PyModule_AddIntConstant(m, "block_size", WBLOCKBYTES); d = PyModule_GetDict(m); PyDict_SetItemString(d, "WhirlpoolType", (PyObject *)&Whirlpooltype); - return m; }