diff options
-rw-r--r-- | pow/POW-0.7/POW.c | 452 |
1 files changed, 448 insertions, 4 deletions
diff --git a/pow/POW-0.7/POW.c b/pow/POW-0.7/POW.c index 9a642a04..eec9e476 100644 --- a/pow/POW-0.7/POW.c +++ b/pow/POW-0.7/POW.c @@ -52,6 +52,7 @@ #include <openssl/hmac.h> #include <openssl/ripemd.h> #include <openssl/pkcs7.h> +#include <openssl/cms.h> #include <time.h> @@ -119,6 +120,7 @@ #define X509_CERTIFICATE 7 #define X_X509_CRL 8 //X509_CRL already used by OpenSSL library #define PKCS7_MESSAGE 9 +#define CMS_MESSAGE 10 // Asymmetric ciphers #define RSA_CIPHER 1 @@ -156,6 +158,7 @@ #define X_hmac_Check(op) ((op)->ob_type == &hmactype) #define X_ssl_Check(op) ((op)->ob_type == &ssltype) #define X_pkcs7_Check(op) ((op)->ob_type == &pkcs7type) +#define X_cms_Check(op) ((op)->ob_type == &cmstype) static char pow_module__doc__ [] = "<moduleDescription>\n" @@ -214,6 +217,7 @@ static PyTypeObject digesttype; static PyTypeObject hmactype; static PyTypeObject ssltype; static PyTypeObject pkcs7type; +static PyTypeObject cmstype; /*========== Pre-definitions ==========*/ /*========== C stucts ==========*/ @@ -272,6 +276,12 @@ typedef struct { PyObject_HEAD PKCS7 *pkcs7; } pkcs7_object; + +typedef struct { + PyObject_HEAD + CMS_ContentInfo *cms; +} cms_object; + /*========== C structs ==========*/ /*========== helper functions ==========*/ @@ -4549,7 +4559,7 @@ static ssl_object * newssl_object(int type) { ssl_object *self; - SSL_METHOD *method; + const SSL_METHOD *method; if ( !(self = PyObject_NEW(ssl_object, &ssltype) ) ) @@ -6550,6 +6560,393 @@ static PyTypeObject pkcs7type = { }; /*========== PKCS7 Code ==========*/ +/*========== CMS code ==========*/ +static cms_object * +CMS_object_new(void) +{ + cms_object *self; + + self = PyObject_New( cms_object, &cmstype ); + if (self == NULL) + goto error; + + self->cms = NULL; + return self; + +error: + + Py_XDECREF(self); + return NULL; +} + +static cms_object * +CMS_object_pem_read(BIO *in) +{ + cms_object *self; + + if ( !(self = PyObject_New( cms_object, &cmstype ) ) ) + goto error; + + if( !(self->cms = PEM_read_bio_CMS( in, NULL, NULL, NULL ) ) ) + { PyErr_SetString( SSLErrorObject, "could not load PEM encoded CMS message" ); goto error; } + + return self; + +error: + + Py_XDECREF(self); + return NULL; +} + +static cms_object * +CMS_object_der_read(char *src, int len) +{ + cms_object *self; + BIO *bio = NULL; + + if ( !(self = PyObject_New( cms_object, &cmstype ) ) ) + goto error; + + self->cms = CMS_ContentInfo_new(); + + if ( !(bio = BIO_new_mem_buf(src, len) ) ) + goto error; + + if( !(d2i_CMS_bio( bio, &self->cms ) ) ) + { PyErr_SetString( SSLErrorObject, "could not load PEM encoded CMS message" ); goto error; } + + BIO_free(bio); + + return self; + +error: + + if (bio) + BIO_free(bio); + + Py_XDECREF(self); + return NULL; +} + +static PyObject * +CMS_object_write_helper(cms_object *self, PyObject *args, int format) +{ + int len=0; + char *buf=NULL; + BIO *out_bio=NULL; + PyObject *cert=NULL; + + if (!PyArg_ParseTuple(args, "")) + return NULL; + + out_bio = BIO_new(BIO_s_mem()); + + if (format == DER_FORMAT) + { + if (!i2d_CMS_bio(out_bio, self->cms) ) + { PyErr_SetString( SSLErrorObject, "unable to write certificate" ); goto error; } + } + else if (format == PEM_FORMAT) + { + if (!PEM_write_bio_CMS(out_bio, self->cms) ) + { PyErr_SetString( SSLErrorObject, "unable to write certificate" ); goto error; } + } + else + { PyErr_SetString( SSLErrorObject, "internal error, unkown output format" ); goto error; } + + if ( !(len = BIO_ctrl_pending(out_bio) ) ) + { PyErr_SetString( SSLErrorObject, "unable to get bytes stored in bio" ); goto error; } + + if ( !(buf = malloc(len) ) ) + { PyErr_SetString( SSLErrorObject, "unable to allocate memory" ); goto error; } + + if ( BIO_read( out_bio, buf, len ) != len ) + { PyErr_SetString( SSLErrorObject, "unable to write out cert" ); goto error; } + + cert = Py_BuildValue("s#", buf, len); + + BIO_free(out_bio); + free(buf); + return cert; + +error: + + if (out_bio) + BIO_free(out_bio); + + if (buf) + free(buf); + + Py_XDECREF(cert); + return NULL; +} + +static char CMS_object_pem_write__doc__[] = +"<method>\n" +" <header>\n" +" <memberof>CMS</memberof>\n" +" <name>pemWrite</name>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This method returns a PEM encoded CMS message as a\n" +" string.\n" +" </para>\n" +" </body>\n" +"</method>\n" +; + +static PyObject * +CMS_object_pem_write(cms_object *self, PyObject *args) +{ + return CMS_object_write_helper(self, args, PEM_FORMAT); +} + +static char CMS_object_der_write__doc__[] = +"<method>\n" +" <header>\n" +" <memberof>CMS</memberof>\n" +" <name>derWrite</name>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This method returns a DER encoded CMS message as a\n" +" string.\n" +" </para>\n" +" </body>\n" +"</method>\n" +; + +static PyObject * +CMS_object_der_write(cms_object *self, PyObject *args) +{ + return CMS_object_write_helper(self, args, DER_FORMAT); +} + +static char CMS_object_sign__doc__[] = +"<method>\n" +" <header>\n" +" <memberof>CMS</memberof>\n" +" <name>sign</name>\n" +" <parameter>signcert</parameter>\n" +" <parameter>key</parameter>\n" +" <parameter>certs</parameter>\n" +" <parameter>data</parameter>\n" +" <optional><parameter>no_certs</parameter></optional>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This method signs a message with a private key.\n" +" </para>\n" +" </body>\n" +"</method>\n" +; + +static PyObject * +CMS_object_sign(cms_object *self, PyObject *args) +{ + asymmetric_object *signkey = NULL; + x509_object *signcert = NULL; + PyObject *x509_sequence = NULL; + STACK_OF(X509) *x509_stack = NULL; + EVP_PKEY *pkey = NULL; + char *buf = NULL; + int len, flags = CMS_BINARY | CMS_NOATTR; + BIO *bio = NULL; + CMS_ContentInfo *cms = NULL; + PyObject *no_certs = Py_False; + + if (!PyArg_ParseTuple(args, "O!O!Os#|O!", + &x509type, &signcert, + &asymmetrictype, &signkey, + &x509_sequence, + &buf, &len, + &PyBool_Type, &no_certs)) + goto error; + + if (signkey->key_type != RSA_PRIVATE_KEY) + { PyErr_SetString( SSLErrorObject, "unsupported key type" ); goto error; } + + if ( !(x509_stack = x509_helper_sequence_to_stack(x509_sequence)) ) + goto error; + + if ( !(pkey = EVP_PKEY_new() ) ) + { PyErr_SetString( SSLErrorObject, "could not allocate memory" ); goto error; } + + if ( !(EVP_PKEY_assign_RSA(pkey, signkey->cipher) ) ) + { PyErr_SetString( SSLErrorObject, "EVP_PKEY assignment error" ); goto error; } + + if ( !(bio = BIO_new_mem_buf(buf, len))) + goto error; + + if ( no_certs == Py_True ) + flags |= CMS_NOCERTS; + + if ( !(cms = CMS_sign(signcert->x509, pkey, x509_stack, bio, flags))) + { set_openssl_pyerror( "could not sign CMS message" ); goto error; } + + if (self->cms) + CMS_ContentInfo_free(self->cms); + self->cms = cms; + cms = NULL; + + sk_X509_free(x509_stack); + BIO_free(bio); + + return Py_BuildValue(""); + +error: + + if (cms) + CMS_ContentInfo_free(cms); + + if (bio) + BIO_free(bio); + + if (x509_stack) + sk_X509_free(x509_stack); + + if (pkey) + EVP_PKEY_free(pkey); + + return NULL; +} + +static char CMS_object_verify__doc__[] = +"<method>\n" +" <header>\n" +" <memberof>CMS</memberof>\n" +" <name>verify</name>\n" +" <parameter>store</parameter>\n" +" <optional><parameter>certs</parameter></optional>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This method verifies a message against a trusted store.\n" +" The optional certs parameter is a set of certificates to search\n" +" for the signer's certificate.\n" +" </para>\n" +" </body>\n" +"</method>\n" +; + +static PyObject * +CMS_object_verify(cms_object *self, PyObject *args) +{ + x509_store_object *store = NULL; + PyObject *result = NULL, *certs_sequence = Py_None; + STACK_OF(X509) *certs_stack = NULL; + char *buf = NULL; + BIO *bio = NULL; + int len; + + if (!(bio = BIO_new(BIO_s_mem()))) + goto error; + + if (!PyArg_ParseTuple(args, "O!|O", &x509_storetype, &store, &certs_sequence)) + goto error; + + if (certs_sequence != Py_None && + !(certs_stack = x509_helper_sequence_to_stack(certs_sequence))) + goto error; + + if (CMS_verify(self->cms, certs_stack, store->store, NULL, bio, 0) <= 0) + { set_openssl_pyerror( "could not verify CMS message" ); goto error; } + + if (!(len = BIO_ctrl_pending(bio))) + { PyErr_SetString( SSLErrorObject, "unable to get bytes stored in bio" ); goto error; } + + if (!(buf = malloc(len) ) ) + { PyErr_SetString( SSLErrorObject, "unable to allocate memory" ); goto error; } + + if (BIO_read( bio, buf, len ) != len) + { PyErr_SetString( SSLErrorObject, "unable to write out CMS content" ); goto error; } + + result = Py_BuildValue("s#", buf, len); + + if (certs_stack) + sk_X509_free(certs_stack); + BIO_free(bio); + free(buf); + + return result; + +error: + + if (certs_stack) + sk_X509_free(certs_stack); + + if (bio) + BIO_free(bio); + + if (buf) + free(buf); + + return NULL; +} + + +static struct PyMethodDef CMS_object_methods[] = { + {"pemWrite", (PyCFunction)CMS_object_pem_write, METH_VARARGS, NULL}, + {"derWrite", (PyCFunction)CMS_object_der_write, METH_VARARGS, NULL}, + {"sign", (PyCFunction)CMS_object_sign, METH_VARARGS, NULL}, + {"verify", (PyCFunction)CMS_object_verify, METH_VARARGS, NULL}, + + {NULL, NULL} /* sentinel */ +}; + +static PyObject * +CMS_object_getattr(cms_object *self, char *name) +{ + return Py_FindMethod(CMS_object_methods, (PyObject *)self, name); +} + +static void +CMS_object_dealloc(cms_object *self, char *name) +{ + CMS_ContentInfo_free( self->cms ); + PyObject_Del(self); +} + +static char cmstype__doc__[] = +"<class>\n" +" <header>\n" +" <name>CMS</name>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This class provides basic access OpenSSL's CMS functionality.\n" +" </para>\n" +" </body>\n" +"</class>\n" +; + +static PyTypeObject cmstype = { + PyObject_HEAD_INIT(0) + 0, /*ob_size*/ + "CMS", /*tp_name*/ + sizeof(cms_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)CMS_object_dealloc, /*tp_dealloc*/ + (printfunc)0, /*tp_print*/ + (getattrfunc)CMS_object_getattr, /*tp_getattr*/ + (setattrfunc)0, /*tp_setattr*/ + (cmpfunc)0, /*tp_compare*/ + (reprfunc)0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + (hashfunc)0, /*tp_hash*/ + (ternaryfunc)0, /*tp_call*/ + (reprfunc)0, /*tp_str*/ + 0, + 0, + 0, + 0, + cmstype__doc__ /* Documentation string */ +}; +/*========== CMS Code ==========*/ + /*========== module functions ==========*/ static char pow_module_new_ssl__doc__[] = "<constructor>\n" @@ -6797,7 +7194,7 @@ pow_module_new_pkcs7 (PyObject *self, PyObject *args) goto error; if ( !(pkcs7 = PKCS7_object_new() ) ) - { PyErr_SetString( SSLErrorObject, "could not create new pkcs7 object" ); goto error; } + { PyErr_SetString( SSLErrorObject, "could not create new PKCS7 object" ); goto error; } return (PyObject*)pkcs7; @@ -6806,6 +7203,37 @@ error: return NULL; } +static char pow_module_new_cms__doc__[] = +"<constructor>\n" +" <header>\n" +" <memberof>CMS</memberof>\n" +" </header>\n" +" <body>\n" +" <para>\n" +" This constructor creates a skeletal CMS object.\n" +" </para>\n" +" </body>\n" +"</constructor>\n" +; + +static PyObject * +pow_module_new_cms (PyObject *self, PyObject *args) +{ + cms_object *cms = NULL; + + if (!PyArg_ParseTuple(args, "")) + goto error; + + if ( !(cms = CMS_object_new() ) ) + { PyErr_SetString( SSLErrorObject, "could not create new CMS object" ); goto error; } + + return (PyObject*)cms; + +error: + + return NULL; +} + static char pow_module_pem_read__doc__[] = "<modulefunction>\n" " <header>\n" @@ -6826,6 +7254,7 @@ static char pow_module_pem_read__doc__[] = " <member><constant>X509_CERTIFICATE</constant></member>\n" " <member><constant>X509_CRL</constant></member>\n" " <member><constant>PKCS7_MESSAGE</constant></member>\n" +" <member><constant>CMS_MESSAGE</constant></member>\n" " </simplelist>\n" " <para>\n" " <parameter>pass</parameter> should only be provided if an encrypted\n" @@ -6835,7 +7264,7 @@ static char pow_module_pem_read__doc__[] = " not desirable, always supply a password. The object returned will be \n" " and instance of <classname>Asymmetric</classname>, \n" " <classname>X509</classname>, <classname>X509Crl</classname>,\n" -" or <classname>PKCS7</classname>.\n" +" <classname>PKCS7</classname>, or <classname>CMS</classname>.\n" " </para>\n" " </body>\n" "</modulefunction>\n" @@ -6870,6 +7299,8 @@ pow_module_pem_read (PyObject *self, PyObject *args) { obj = (PyObject*)x509_crl_object_pem_read( in ); break ; } case PKCS7_MESSAGE: { obj = (PyObject*)PKCS7_object_pem_read( in ); break ; } + case CMS_MESSAGE: + { obj = (PyObject*)CMS_object_pem_read( in ); break ; } default: { PyErr_SetString( SSLErrorObject, "unknown pem encoding" ); goto error; } @@ -6907,11 +7338,13 @@ static char pow_module_der_read__doc__[] = " <member><constant>X509_CERTIFICATE</constant></member>\n" " <member><constant>X509_CRL</constant></member>\n" " <member><constant>PKCS7_MESSAGE</constant></member>\n" +" <member><constant>CMS_MESSAGE</constant></member>\n" " </simplelist>\n" " <para>\n" " As with the PEM operations, the object returned will be and instance \n" " of <classname>Asymmetric</classname>, <classname>X509</classname>,\n" -" <classname>X509Crl</classname>, or <classname>PKCS7</classname>.\n" +" <classname>X509Crl</classname>, <classname>PKCS7</classname>,\n" +" or <classname>CMS</classname>.\n" " </para>\n" " </body>\n" "</modulefunction>\n" @@ -6939,6 +7372,8 @@ pow_module_der_read (PyObject *self, PyObject *args) { obj = (PyObject*)x509_crl_object_der_read( src, len ); break ; } case PKCS7_MESSAGE: { obj = (PyObject*)PKCS7_object_der_read( src, len ); break ; } + case CMS_MESSAGE: + { obj = (PyObject*)CMS_object_der_read( src, len ); break ; } default: { PyErr_SetString( SSLErrorObject, "unknown der encoding" ); goto error; } @@ -7511,6 +7946,12 @@ pow_module_docset(PyObject *self, PyObject *args) docset_helper_add( docset, PKCS7_object_sign__doc__ ); docset_helper_add( docset, PKCS7_object_verify__doc__ ); + // cms documentation + docset_helper_add( docset, CMS_object_pem_write__doc__ ); + docset_helper_add( docset, CMS_object_der_write__doc__ ); + docset_helper_add( docset, CMS_object_sign__doc__ ); + docset_helper_add( docset, CMS_object_verify__doc__ ); + // symmetric documentation docset_helper_add( docset, symmetrictype__doc__ ); docset_helper_add( docset, symmetric_object_encrypt_init__doc__ ); @@ -7544,6 +7985,7 @@ static struct PyMethodDef pow_module_methods[] = { {"Digest", (PyCFunction)pow_module_new_digest, METH_VARARGS, NULL}, {"Hmac", (PyCFunction)pow_module_new_hmac, METH_VARARGS, NULL}, {"PKCS7", (PyCFunction)pow_module_new_pkcs7, METH_VARARGS, NULL}, + {"CMS", (PyCFunction)pow_module_new_cms, METH_VARARGS, NULL}, {"Asymmetric", (PyCFunction)pow_module_new_asymmetric, METH_VARARGS, NULL}, {"Symmetric", (PyCFunction)pow_module_new_symmetric, METH_VARARGS, NULL}, {"X509Store", (PyCFunction)pow_module_new_x509_store, METH_VARARGS, NULL}, @@ -7580,6 +8022,7 @@ init_POW(void) digesttype.ob_type = &PyType_Type; hmactype.ob_type = &PyType_Type; pkcs7type.ob_type = &PyType_Type; + cmstype.ob_type = &PyType_Type; m = Py_InitModule4("_POW", pow_module_methods, pow_module__doc__, @@ -7640,6 +8083,7 @@ init_POW(void) install_int_const( d, "X509_CERTIFICATE", X509_CERTIFICATE ); install_int_const( d, "X509_CRL", X_X509_CRL ); install_int_const( d, "PKCS7_MESSAGE", PKCS7_MESSAGE ); + install_int_const( d, "CMS_MESSAGE", CMS_MESSAGE ); // asymmetric ciphers #ifndef OPENSSL_NO_RSA |