blob: c3effa499094f9c85b45042b61139ab8a9c9bd45 [file] [log] [blame] [edit]
/* -*- 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.
* ===================================================================
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _HAVE_STDC_HEADERS
#include <string.h>
#endif
#include "Python.h"
#include "pycrypto_compat.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: */