/* -*- C -*- */ /* * stream_template.c : Generic framework for stream ciphers * * Written by Andrew Kuchling and others * * =================================================================== * The contents of this file are dedicated to the public domain. To * the extent that dedication to the public domain is not available, * everyone is granted a worldwide, perpetual, royalty-free, * non-exclusive license to exercise all rights associated with the * contents of this file for any purpose whatsoever. * No rights are reserved. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * =================================================================== */ #include "pycrypto_common.h" #include "modsupport.h" #define _STR(x) #x #define _XSTR(x) _STR(x) #define _PASTE(x,y) x##y #define _PASTE2(x,y) _PASTE(x,y) #ifdef IS_PY3K #define _MODULE_NAME _PASTE2(PyInit_,MODULE_NAME) #else #define _MODULE_NAME _PASTE2(init,MODULE_NAME) #endif #define _MODULE_STRING _XSTR(MODULE_NAME) /* * * Python interface * */ typedef struct { PyObject_HEAD stream_state st; } ALGobject; /* Please see PEP3123 for a discussion of PyObject_HEAD and changes made in 3.x to make it conform to Standard C. * These changes also dictate using Py_TYPE to check type, and PyVarObject_HEAD_INIT(NULL, 0) to initialize */ #ifdef IS_PY3K static PyTypeObject ALGtype; #define is_ALGobject(v) (Py_TYPE(v) == &ALGtype) #else staticforward PyTypeObject ALGtype; #define is_ALGobject(v) ((v)->ob_type == &ALGtype) #define PyLong_FromLong PyInt_FromLong /* For Python 2.x */ #endif static ALGobject * newALGobject(void) { ALGobject * new; new = PyObject_New(ALGobject, &ALGtype); return new; } static void ALGdealloc(PyObject *ptr) { ALGobject *self = (ALGobject *)ptr; /* Overwrite the contents of the object */ memset((char*)&(self->st), 0, sizeof(stream_state)); PyObject_Del(ptr); } static char ALGnew__doc__[] = "Return a new " _MODULE_STRING " encryption object."; static char *kwlist[] = {"key", NULL}; static ALGobject * ALGnew(PyObject *self, PyObject *args, PyObject *kwdict) { unsigned char *key; ALGobject * new; int keylen; new = newALGobject(); if (!PyArg_ParseTupleAndKeywords(args, kwdict, "s#", kwlist, &key, &keylen)) { Py_DECREF(new); return NULL; } if (KEY_SIZE!=0 && keylen != KEY_SIZE) { PyErr_SetString(PyExc_ValueError, _MODULE_STRING " key must be " "KEY_SIZE bytes long"); return NULL; } if (KEY_SIZE== 0 && keylen == 0) { PyErr_SetString(PyExc_ValueError, _MODULE_STRING " key cannot be " "the null string (0 bytes long)"); return NULL; } stream_init(&(new->st), key, keylen); if (PyErr_Occurred()) { Py_DECREF(new); return NULL; } return new; } static char ALG_Encrypt__doc__[] = "Decrypt the provided string of binary data."; static PyObject * ALG_Encrypt(ALGobject *self, PyObject *args) { unsigned char *buffer, *str; int len; PyObject *result; if (!PyArg_Parse(args, "s#", &str, &len)) return NULL; if (len == 0) /* Handle empty string */ { return PyBytes_FromStringAndSize(NULL, 0); } buffer = malloc(len); if (buffer == NULL) { PyErr_SetString(PyExc_MemoryError, "No memory available in " _MODULE_STRING " encrypt"); return NULL; } Py_BEGIN_ALLOW_THREADS; memcpy(buffer, str, len); stream_encrypt(&(self->st), buffer, len); Py_END_ALLOW_THREADS; result = PyBytes_FromStringAndSize((char *)buffer, len); free(buffer); return (result); } static char ALG_Decrypt__doc__[] = "decrypt(string): Decrypt the provided string of binary data."; static PyObject * ALG_Decrypt(ALGobject *self, PyObject *args) { unsigned char *buffer, *str; int len; PyObject *result; if (!PyArg_Parse(args, "s#", &str, &len)) return NULL; if (len == 0) /* Handle empty string */ { return PyBytes_FromStringAndSize(NULL, 0); } buffer = malloc(len); if (buffer == NULL) { PyErr_SetString(PyExc_MemoryError, "No memory available in " _MODULE_STRING " decrypt"); return NULL; } Py_BEGIN_ALLOW_THREADS; memcpy(buffer, str, len); stream_decrypt(&(self->st), buffer, len); Py_END_ALLOW_THREADS; result = PyBytes_FromStringAndSize((char *)buffer, len); free(buffer); return (result); } /* ALGobject methods */ static PyMethodDef ALGmethods[] = { #ifdef IS_PY3K {"encrypt", (PyCFunction) ALG_Encrypt, METH_O, ALG_Encrypt__doc__}, {"decrypt", (PyCFunction) ALG_Decrypt, METH_O, ALG_Decrypt__doc__}, #else {"encrypt", (PyCFunction) ALG_Encrypt, 0, ALG_Encrypt__doc__}, {"decrypt", (PyCFunction) ALG_Decrypt, 0, ALG_Decrypt__doc__}, #endif {NULL, NULL} /* sentinel */ }; static PyObject * #ifdef IS_PY3K ALGgetattro(PyObject *self, PyObject *attr) #else ALGgetattr(PyObject *self, char *name) #endif { #ifdef IS_PY3K if (!PyUnicode_Check(attr)) goto generic; if (PyUnicode_CompareWithASCIIString(attr, "block_size") == 0) #else if (strcmp(name, "block_size") == 0) #endif { return PyLong_FromLong(BLOCK_SIZE); } #ifdef IS_PY3K if (PyUnicode_CompareWithASCIIString(attr, "key_size") == 0) #else if (strcmp(name, "key_size") == 0) #endif { return PyLong_FromLong(KEY_SIZE); } #ifdef IS_PY3K generic: return PyObject_GenericGetAttr(self, attr); #else return Py_FindMethod(ALGmethods, self, name); #endif } /* List of functions defined in the module */ static struct PyMethodDef modulemethods[] = { {"new", (PyCFunction) ALGnew, METH_VARARGS|METH_KEYWORDS, ALGnew__doc__}, {NULL, NULL} /* sentinel */ }; static PyTypeObject ALGtype = { #ifdef IS_PY3K PyVarObject_HEAD_INIT(NULL, 0) /* deferred type init for compilation on Windows, type will be filled in at runtime */ #else PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ #endif _MODULE_STRING, /*tp_name*/ sizeof(ALGobject), /*tp_size*/ 0, /*tp_itemsize*/ /* methods */ (destructor) ALGdealloc, /*tp_dealloc*/ 0, /*tp_print*/ #ifdef IS_PY3K 0, /*tp_getattr*/ #else ALGgetattr, /*tp_getattr*/ #endif 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ #ifdef IS_PY3K 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ ALGgetattro, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ ALGmethods, /*tp_methods*/ #endif }; #ifdef IS_PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "Crypto.Cipher." _MODULE_STRING, NULL, -1, modulemethods, NULL, NULL, NULL, NULL }; #endif /* Initialization function for the module */ /* Deal with old API in Python 2.1 */ #if PYTHON_API_VERSION < 1011 #define PyModule_AddIntConstant(m,n,v) {PyObject *o=PyInt_FromLong(v); \ if (o!=NULL) \ {PyDict_SetItemString(PyModule_GetDict(m),n,o); Py_DECREF(o);}} #endif #ifdef IS_PY3K PyMODINIT_FUNC #else void #endif _MODULE_NAME (void) { PyObject *m, *d, *x; #ifdef IS_PY3K /* PyType_Ready automatically fills in ob_type with &PyType_Type if it's not already set */ if (PyType_Ready(&ALGtype) < 0) return NULL; /* Create the module and add the functions */ m = PyModule_Create(&moduledef); if (m == NULL) return NULL; #else ALGtype.ob_type = &PyType_Type; /* Create the module and add the functions */ m = Py_InitModule("Crypto.Cipher." _MODULE_STRING, modulemethods); #endif /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); x = PyUnicode_FromString(_MODULE_STRING ".error"); PyDict_SetItemString(d, "error", x); PyModule_AddIntConstant(m, "block_size", BLOCK_SIZE); PyModule_AddIntConstant(m, "key_size", KEY_SIZE); /* Check for errors */ if (PyErr_Occurred()) Py_FatalError("can't initialize module " _MODULE_STRING); #ifdef IS_PY3K return m; #endif } /* vim:set ts=4 sw=4 sts=0 noexpandtab: */