289 lines
8.1 KiB
C
289 lines
8.1 KiB
C
/*
|
|
* _pyecc - Copyright 2009 Slide, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this library; if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <Python.h>
|
|
|
|
#include "_pyecc.h"
|
|
|
|
/*
|
|
* Creating a function pointer type for casting
|
|
*/
|
|
typedef void (*fp)(void *);
|
|
|
|
static char pyecc_doc[] = "\
|
|
The _pyecc module provides underlying C hooks for the \
|
|
\"pyecc\" module\n\n\
|
|
Refer to the pyecc documentation for it's use as \
|
|
_pyecc is not intended for public consumption as \
|
|
it does not provide the proper wrapper and object-\
|
|
oriented support that the pyecc module does\n\
|
|
";
|
|
|
|
|
|
|
|
static char new_state_doc[] = "\
|
|
Generate a new ECC_State object that will ensure the \
|
|
libgcrypt state necessary for crypto is all set up and \
|
|
ready for use\n\
|
|
";
|
|
static void *_release_state(void *_state)
|
|
{
|
|
if (_state)
|
|
ecc_free_state((ECC_State)(_state));
|
|
Py_RETURN_NONE;
|
|
}
|
|
static PyObject *py_new_state(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
ECC_State state = ecc_new_state(NULL);
|
|
|
|
PyObject *rc = PyCObject_FromVoidPtr(state, (fp)(_release_state));
|
|
if (!PyCObject_Check(rc)) {
|
|
if (state)
|
|
ecc_free_state(state);
|
|
Py_RETURN_NONE;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
static char encrypt_doc[] = "\
|
|
Encrypt a string buffer of data, expects to be \
|
|
passed a buffer, a ECC_KeyPair PyCObject and a \
|
|
ECC_State PyCObject \
|
|
\n\
|
|
";
|
|
static PyObject *py_encrypt(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *temp_state, *temp_keypair;
|
|
ECC_State state;
|
|
ECC_KeyPair keypair;
|
|
char *data;
|
|
unsigned int datalen;
|
|
|
|
if (!PyArg_ParseTuple(args, "s#OO", &data, &datalen, &temp_keypair,
|
|
&temp_state)) {
|
|
return NULL;
|
|
}
|
|
|
|
if (datalen <= 0) {
|
|
PyErr_SetString(PyExc_TypeError, "data can not have a length of zero");
|
|
return NULL;
|
|
}
|
|
|
|
state = (ECC_State)(PyCObject_AsVoidPtr(temp_state));
|
|
keypair = (ECC_KeyPair)(PyCObject_AsVoidPtr(temp_keypair));
|
|
|
|
ECC_Data result = ecc_encrypt(data, datalen, keypair, state);
|
|
|
|
if ( (result == NULL) || (result->data == NULL) )
|
|
Py_RETURN_NONE;
|
|
|
|
return PyString_FromStringAndSize((char *)(result->data), result->datalen);
|
|
}
|
|
|
|
static char decrypt_doc[] = "\
|
|
Decrypt a buffer of encrypted data, expects to be \
|
|
passed a buffer, a ECC_KeyPair PyCObject and a \
|
|
ECC_State PyCObject \
|
|
\n\
|
|
";
|
|
static PyObject *py_decrypt(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *temp_state, *temp_keypair;
|
|
ECC_State state;
|
|
ECC_KeyPair keypair;
|
|
ECC_Data encrypted;
|
|
char *data;
|
|
int datalen;
|
|
|
|
if (!PyArg_ParseTuple(args, "s#OO", &data, &datalen, &temp_keypair,
|
|
&temp_state)) {
|
|
return NULL;
|
|
}
|
|
|
|
state = (ECC_State)(PyCObject_AsVoidPtr(temp_state));
|
|
keypair = (ECC_KeyPair)(PyCObject_AsVoidPtr(temp_keypair));
|
|
|
|
encrypted = ecc_new_data();
|
|
encrypted->data = data;
|
|
encrypted->datalen = datalen;
|
|
|
|
ECC_Data result = ecc_decrypt(encrypted, keypair, state);
|
|
|
|
if ( (result == NULL) || (result->data == NULL) )
|
|
Py_RETURN_NONE;
|
|
|
|
return PyString_FromStringAndSize((char *)(result->data), result->datalen);
|
|
}
|
|
|
|
static char new_keypair_doc[] = "\
|
|
Return a new ECC_KeyPair object that will contain the appropriate \
|
|
references to the public and private keys in memory\n\
|
|
";
|
|
static void *_release_keypair(void *_keypair)
|
|
{
|
|
if (_keypair) {
|
|
ECC_KeyPair kp = (ECC_KeyPair)(_keypair);
|
|
if (kp->priv) {
|
|
free(kp->priv);
|
|
}
|
|
if (kp->pub) {
|
|
free(kp->pub);
|
|
}
|
|
free(kp);
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
static PyObject *py_new_keypair(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
char *privkey, *temp_pubkey, *pubkey;
|
|
PyObject *temp_state;
|
|
ECC_State state;
|
|
unsigned int pubkeylen, privkeylen;
|
|
|
|
if (!PyArg_ParseTuple(args, "s#z#O", &temp_pubkey, &pubkeylen,
|
|
&privkey, &privkeylen, &temp_state))
|
|
return NULL;
|
|
|
|
/*
|
|
* Copying into a separate buffer lest Python deallocate our
|
|
* string out from under us
|
|
*/
|
|
pubkey = (char *)(malloc(sizeof(char) * pubkeylen + 1));
|
|
memcpy(pubkey, temp_pubkey, pubkeylen + 1);
|
|
|
|
state = (ECC_State)(PyCObject_AsVoidPtr(temp_state));
|
|
|
|
ECC_KeyPair kp = ecc_new_keypair_s(pubkey, pubkeylen, privkey, privkeylen, state);
|
|
|
|
PyObject *rc = PyCObject_FromVoidPtr(kp, (fp)(_release_keypair));
|
|
if (!PyCObject_Check(rc)) {
|
|
if (kp)
|
|
_release_keypair(kp);
|
|
Py_RETURN_NONE;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
static char verify_doc[] = "\
|
|
Verify that the specified data matches the given signature \
|
|
and vice versa. Should return a True/False depending on the \
|
|
success of the verification call\n\
|
|
";
|
|
static PyObject *py_verify(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *temp_state, *temp_keypair;
|
|
ECC_State state;
|
|
ECC_KeyPair keypair;
|
|
char *data, *signature;
|
|
|
|
if (!PyArg_ParseTuple(args, "ssOO", &data, &signature, &temp_keypair,
|
|
&temp_state)) {
|
|
return NULL;
|
|
}
|
|
|
|
state = (ECC_State)(PyCObject_AsVoidPtr(temp_state));
|
|
keypair = (ECC_KeyPair)(PyCObject_AsVoidPtr(temp_keypair));
|
|
|
|
if (ecc_verify(data, signature, keypair, state))
|
|
Py_RETURN_TRUE;
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
|
|
static char sign_doc[] = "\
|
|
Sign the specified string or block of data \
|
|
being passed in. Should return a string representation \
|
|
of the signature or None\n\
|
|
";
|
|
static PyObject *py_sign(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
PyObject *temp_state, *temp_keypair;
|
|
ECC_State state;
|
|
ECC_KeyPair keypair;
|
|
char *data;
|
|
|
|
if (!PyArg_ParseTuple(args, "zOO", &data, &temp_keypair,
|
|
&temp_state)) {
|
|
return NULL;
|
|
}
|
|
|
|
state = (ECC_State)(PyCObject_AsVoidPtr(temp_state));
|
|
keypair = (ECC_KeyPair)(PyCObject_AsVoidPtr(temp_keypair));
|
|
|
|
ECC_Data result = ecc_sign(data, keypair, state);
|
|
if ( (result == NULL) || (result->data == NULL) )
|
|
Py_RETURN_NONE;
|
|
|
|
return PyString_FromString((const char *)(result->data));
|
|
}
|
|
|
|
static char keygen_doc[] = "\
|
|
Generate a set of keys, returns a tuple containing \
|
|
three values: (serialized public key, serialized private key, curve)\n\
|
|
";
|
|
static PyObject *py_keygen(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
{
|
|
ECC_State state;
|
|
ECC_KeyPair keypair;
|
|
PyObject *rc;
|
|
|
|
state = ecc_new_state(NULL);
|
|
if (!state)
|
|
Py_RETURN_NONE;
|
|
|
|
keypair = ecc_keygen(NULL, state);
|
|
if (!keypair) {
|
|
ecc_free_state(state);
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
rc = PyTuple_New(3);
|
|
|
|
/*
|
|
* Returns (pub, priv, curve)
|
|
*/
|
|
PyTuple_SetItem(rc, 0, PyString_FromString((const char *)(keypair->pub)));
|
|
PyTuple_SetItem(rc, 1, PyString_FromString(ecc_serialize_private_key(keypair, state)));
|
|
PyTuple_SetItem(rc, 2, PyString_FromString(DEFAULT_CURVE));
|
|
|
|
ecc_free_state(state);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
static struct PyMethodDef _pyecc_methods[] = {
|
|
{"new_state", (PyCFunction)py_new_state, METH_NOARGS, new_state_doc},
|
|
{"new_keypair", (PyCFunction)py_new_keypair, METH_VARARGS, new_keypair_doc},
|
|
{"verify", (PyCFunction)py_verify, METH_VARARGS, verify_doc},
|
|
{"sign", (PyCFunction)py_sign, METH_VARARGS, sign_doc},
|
|
{"encrypt", (PyCFunction)py_encrypt, METH_VARARGS, encrypt_doc},
|
|
{"decrypt", (PyCFunction)py_decrypt, METH_VARARGS, decrypt_doc},
|
|
{"keygen", (PyCFunction)(py_keygen), METH_NOARGS, keygen_doc},
|
|
{NULL}
|
|
};
|
|
|
|
PyMODINIT_FUNC init_pyecc(void)
|
|
{
|
|
PyObject *module = Py_InitModule3("_pyecc", _pyecc_methods, pyecc_doc);
|
|
PyModule_AddStringConstant(module, "DEFAULT_CURVE", DEFAULT_CURVE);
|
|
}
|