diff options
author | Rob Austein <sra@hactrn.net> | 2008-03-24 19:54:05 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2008-03-24 19:54:05 +0000 |
commit | 295269dd4e66d592ca112a96e28ab7d87a6af0c1 (patch) | |
tree | 019df15092c4830097a9c035c0c7a846e5627c5b | |
parent | 738be12e5fdf4a89e25f7e4d65b8dd07cf693e05 (diff) |
Support verification of CMS without bundled EE cert.
svn path=/pow/POW-0.7/POW.c; revision=1562
-rw-r--r-- | pow/POW-0.7/POW.c | 209 | ||||
-rw-r--r-- | rpkid/rpki/cms.py | 9 | ||||
-rw-r--r-- | rpkid/test-pow-cms.py | 62 |
3 files changed, 155 insertions, 125 deletions
diff --git a/pow/POW-0.7/POW.c b/pow/POW-0.7/POW.c index e457453a..9a642a04 100644 --- a/pow/POW-0.7/POW.c +++ b/pow/POW-0.7/POW.c @@ -580,6 +580,52 @@ error: free(buf); } +static STACK_OF(X509) * +x509_helper_sequence_to_stack(PyObject *x509_sequence) +{ + x509_object *tmpX509 = NULL; + STACK_OF(X509) *x509_stack = NULL; + int size = 0, i = 0; + + if ( x509_sequence != Py_None && !PyTuple_Check( x509_sequence ) && !PyList_Check(x509_sequence) ) + { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } + + if (!(x509_stack = sk_X509_new_null() ) ) + { PyErr_SetString( SSLErrorObject, "could not create new x509 stack" ); goto error; } + + if ( x509_sequence != Py_None ) + { + size = PySequence_Size( x509_sequence ); + + for (i=0; i < size; i++) + { + if ( !( tmpX509 = (x509_object*)PySequence_GetItem( x509_sequence, i ) ) ) + goto error; + + if ( !X_X509_Check( tmpX509 ) ) + { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } + + if (!sk_X509_push( x509_stack, tmpX509->x509 ) ) + { PyErr_SetString( SSLErrorObject, "could not add x509 to stack" ); goto error; } + Py_DECREF(tmpX509); + tmpX509 = NULL; + } + } + + return x509_stack; + +error: + + if(x509_stack) + sk_X509_free(x509_stack); + + Py_XDECREF(tmpX509); + + return NULL; +} + + + /*========== helper funcitons ==========*/ /*========== X509 code ==========*/ @@ -1865,36 +1911,17 @@ static char x509_store_object_verify_chain__doc__[] = static PyObject * x509_store_object_verify_chain(x509_store_object *self, PyObject *args) { - PyObject *x509_sequence=NULL; + PyObject *x509_sequence = NULL; X509_STORE_CTX csc; - x509_object *x509=NULL, *tmpX509=NULL; - STACK_OF(X509) *x509_stack=NULL; - int result=0, size=0, i=0; + x509_object *x509 = NULL; + STACK_OF(X509) *x509_stack = NULL; + int result = 0; if (!PyArg_ParseTuple(args, "O!O", &x509type, &x509, &x509_sequence)) goto error; - if ( !( PyTuple_Check( x509_sequence ) || PyList_Check(x509_sequence) ) ) - { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } - - size = PySequence_Size( x509_sequence ); - - if (!(x509_stack = sk_X509_new_null() ) ) - { PyErr_SetString( SSLErrorObject, "could not create new x509 stack" ); goto error; } - - for (i=0; i < size; i++) - { - if ( !( tmpX509 = (x509_object*)PySequence_GetItem( x509_sequence, i ) ) ) - goto error; - - if ( !X_X509_Check( tmpX509 ) ) - { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } - - if (!sk_X509_push( x509_stack, tmpX509->x509 ) ) - { PyErr_SetString( SSLErrorObject, "could not add x509 to stack" ); goto error; } - Py_DECREF(tmpX509); - tmpX509 = NULL; - } + if ( !(x509_stack = x509_helper_sequence_to_stack(x509_sequence)) ) + goto error; X509_STORE_CTX_init( &csc, self->store, x509->x509, x509_stack ); result = X509_verify_cert( &csc ); @@ -1908,8 +1935,6 @@ error: if(x509_stack) sk_X509_free(x509_stack); - Py_XDECREF(tmpX509); - return NULL; } @@ -6324,12 +6349,12 @@ static PyObject * PKCS7_object_sign(pkcs7_object *self, PyObject *args) { asymmetric_object *signkey = NULL; - x509_object *signcert = NULL, *tmpX509 = NULL; + x509_object *signcert = NULL; PyObject *x509_sequence = NULL; STACK_OF(X509) *x509_stack = NULL; EVP_PKEY *pkey = NULL; char *buf = NULL; - int len, size = 0, i, flags = PKCS7_BINARY | PKCS7_NOATTR; + int len, flags = PKCS7_BINARY | PKCS7_NOATTR; BIO *bio = NULL; PKCS7 *p7 = NULL; PyObject *no_certs = Py_False; @@ -6345,27 +6370,8 @@ PKCS7_object_sign(pkcs7_object *self, PyObject *args) if (signkey->key_type != RSA_PRIVATE_KEY) { PyErr_SetString( SSLErrorObject, "unsupported key type" ); goto error; } - if ( !PyTuple_Check( x509_sequence ) && !PyList_Check( x509_sequence ) ) - { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } - - size = PySequence_Size( x509_sequence ); - - if (!(x509_stack = sk_X509_new_null() ) ) - { PyErr_SetString( SSLErrorObject, "could not create new x509 stack" ); goto error; } - - for (i=0; i < size; i++) - { - if ( !( tmpX509 = (x509_object*)PySequence_GetItem( x509_sequence, i ) ) ) - goto error; - - if ( !X_X509_Check( tmpX509 ) ) - { PyErr_SetString( PyExc_TypeError, "inapropriate type" ); goto error; } - - if (!sk_X509_push( x509_stack, tmpX509->x509 ) ) - { PyErr_SetString( SSLErrorObject, "could not add x509 to stack" ); goto error; } - Py_DECREF(tmpX509); - tmpX509 = NULL; - } + 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; } @@ -6394,8 +6400,6 @@ PKCS7_object_sign(pkcs7_object *self, PyObject *args) error: - Py_XDECREF(tmpX509); - if (p7) PKCS7_free(p7); @@ -6411,46 +6415,60 @@ error: return NULL; } +static char PKCS7_object_verify__doc__[] = +"<method>\n" +" <header>\n" +" <memberof>PKCS7</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 * -PKCS7_object_verify_helper(pkcs7_object *self, PyObject *args, int noverify) +PKCS7_object_verify(pkcs7_object *self, PyObject *args) { x509_store_object *store = NULL; - PyObject *result = 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()))) + if (!(bio = BIO_new(BIO_s_mem()))) goto error; - if (noverify) { - - if (!PyArg_ParseTuple(args, "")) - goto error; - if (PKCS7_verify(self->pkcs7, NULL, NULL, NULL, bio, PKCS7_NOVERIFY) <= 0) - { set_openssl_pyerror( "could not extract PKCS7 message" ); goto error; } - - } else { - - if (!PyArg_ParseTuple(args, "O!", &x509_storetype, &store)) - goto error; + if (!PyArg_ParseTuple(args, "O!|O", &x509_storetype, &store, &certs_sequence)) + goto error; - if (PKCS7_verify(self->pkcs7, NULL, store->store, NULL, bio, 0) <= 0) - { set_openssl_pyerror( "could not verify PKCS7 message" ); goto error; } + if (certs_sequence != Py_None && + !(certs_stack = x509_helper_sequence_to_stack(certs_sequence))) + goto error; - } + if (PKCS7_verify(self->pkcs7, certs_stack, store->store, NULL, bio, 0) <= 0) + { set_openssl_pyerror( "could not verify PKCS7 message" ); goto error; } - if ( !(len = BIO_ctrl_pending(bio) ) ) + if (!(len = BIO_ctrl_pending(bio))) { PyErr_SetString( SSLErrorObject, "unable to get bytes stored in bio" ); goto error; } - if ( !(buf = malloc(len) ) ) + if (!(buf = malloc(len) ) ) { PyErr_SetString( SSLErrorObject, "unable to allocate memory" ); goto error; } - if ( BIO_read( bio, buf, len ) != len ) + if (BIO_read( bio, buf, len ) != len) { PyErr_SetString( SSLErrorObject, "unable to write out PKCS7 content" ); goto error; } result = Py_BuildValue("s#", buf, len); + if (certs_stack) + sk_X509_free(certs_stack); BIO_free(bio); free(buf); @@ -6458,6 +6476,9 @@ PKCS7_object_verify_helper(pkcs7_object *self, PyObject *args, int noverify) error: + if (certs_stack) + sk_X509_free(certs_stack); + if (bio) BIO_free(bio); @@ -6467,55 +6488,12 @@ error: return NULL; } -static char PKCS7_object_verify__doc__[] = -"<method>\n" -" <header>\n" -" <memberof>PKCS7</memberof>\n" -" <name>verify</name>\n" -" <parameter>store</parameter>\n" -" </header>\n" -" <body>\n" -" <para>\n" -" This method verifies a message against a trusted store.\n" -" </para>\n" -" </body>\n" -"</method>\n" -; - -static PyObject * -PKCS7_object_verify(pkcs7_object *self, PyObject *args) -{ - return PKCS7_object_verify_helper(self, args, 0); -} - -static char PKCS7_object_extract__doc__[] = -"<method>\n" -" <header>\n" -" <memberof>PKCS7</memberof>\n" -" <name>extract</name>\n" -" </header>\n" -" <body>\n" -" <para>\n" -" This method extracts the content of a signed message without\n" -" verifying it.\n" -" </para>\n" -" </body>\n" -"</method>\n" -; - -static PyObject * -PKCS7_object_extract(pkcs7_object *self, PyObject *args) -{ - return PKCS7_object_verify_helper(self, args, 1); -} - static struct PyMethodDef PKCS7_object_methods[] = { {"pemWrite", (PyCFunction)PKCS7_object_pem_write, METH_VARARGS, NULL}, {"derWrite", (PyCFunction)PKCS7_object_der_write, METH_VARARGS, NULL}, {"sign", (PyCFunction)PKCS7_object_sign, METH_VARARGS, NULL}, {"verify", (PyCFunction)PKCS7_object_verify, METH_VARARGS, NULL}, - {"extract", (PyCFunction)PKCS7_object_extract, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ }; @@ -7532,7 +7510,6 @@ pow_module_docset(PyObject *self, PyObject *args) docset_helper_add( docset, PKCS7_object_der_write__doc__ ); docset_helper_add( docset, PKCS7_object_sign__doc__ ); docset_helper_add( docset, PKCS7_object_verify__doc__ ); - docset_helper_add( docset, PKCS7_object_extract__doc__ ); // symmetric documentation docset_helper_add( docset, symmetrictype__doc__ ); diff --git a/rpkid/rpki/cms.py b/rpkid/rpki/cms.py index 7b4916dc..1bbf18fd 100644 --- a/rpkid/rpki/cms.py +++ b/rpkid/rpki/cms.py @@ -80,15 +80,6 @@ def verify(cms, ta): dumpasn1(cms) raise rpki.exceptions.CMSVerificationFailed, "CMS verification failed" -# openssl smime -verify -noverify -inform DER -in THING.der - -def extract(cms): - """Extract the content of a signed CMS message WITHOUT verifying the - signature. Don't try this at home, kids. - """ - - return POW.derRead(POW.PKCS7_MESSAGE, cms).extract() - def xml_verify(cms, ta): """Composite routine to verify CMS-wrapped XML.""" diff --git a/rpkid/test-pow-cms.py b/rpkid/test-pow-cms.py new file mode 100644 index 00000000..fc2ef7a3 --- /dev/null +++ b/rpkid/test-pow-cms.py @@ -0,0 +1,62 @@ +# $Id$ + +# Copyright (C) 2008 American Registry for Internet Numbers ("ARIN") +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +import POW, rpki.x509, os + +key = rpki.x509.RSA(Auto_file = "biz-certs/Alice-EE.key").get_POW() +ee = rpki.x509.X509(Auto_file = "biz-certs/Alice-EE.cer").get_POW() + +ca = rpki.x509.X509(Auto_file = "biz-certs/Alice-CA.cer").get_POW() +ta = rpki.x509.X509(Auto_file = "biz-certs/Alice-Root.cer").get_POW() + +plaintext = "Wombats Are Us" + +p7 = POW.PKCS7() + +#p7.sign(ee, key, [ca], plaintext) +#p7.sign(ee, key, [], plaintext) +#p7.sign(ee, key, [], plaintext, False) +p7.sign(ee, key, [], plaintext, True) + +#print p7.pemWrite() + +if False: + f = open("test-pow-cms.der", "w") + f.write(p7.derWrite()) + f.close() + if False: + f = os.popen("dumpasn1 2>&1 -a test-pow-cms.der") + print "\n".join(x for x in f.read().splitlines() if x.startswith(" ")) + f.close() + +store = POW.X509Store() +store.addTrust(ta) + +if store.verify(ca): + print "Verified CA" + store.addTrust(ca) +else: + print "Couldn't verify CA" + +if store.verify(ee): + print "Verified EE" + store.addTrust(ee) +else: + print "Couldn't verify EE" + +result = p7.verify(store, [ee]) +print result + |