--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/pyopenssl/patches/3_add_if.patch Wed Aug 28 13:41:11 2013 -0700
@@ -0,0 +1,316 @@
+#
+# This patch adds a few more interfaces to OpenSSL functions required for IPS.
+# The additional interfaces are:
+# pyOpenSSL -> OpenSSL
+# crypto.CRL.verify() X509_CRL_verify()
+# crypto.CRL.get_issuer() X509_CRL_get_issuer()
+# crypto.CRL.get_next_update() X509_CRL_get_nextUpdate()
+# crypto.X509.verify() X509_verify()
+# crypto.X509.check_ca() X509_check_ca()
+#
+# The patch also adds test cases to the pyOpenSSL test suite for the added
+# functions.
+#
+--- pyOpenSSL-0.13/OpenSSL/crypto/crl.c 2013-08-26 15:04:14.949389722 -0700
++++ pyOpenSSL-0.13/OpenSSL/crypto/crl.c 2013-08-26 15:05:00.183031221 -0700
+@@ -180,6 +180,84 @@
+ return buffer;
+ }
+
++static char crypto_CRL_verify_doc[] = "\n\
++Verifies the CRL using the supplied public key\n\
++\n\
++@param key: a public key\n\
++@type key: L{PKey}\n\
++@return: True if the signature is correct.\n\
++@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
++ problem verifying the signature.\n\
++";
++
++PyObject *
++crypto_CRL_verify(crypto_CRLObj *self, PyObject *args)
++{
++ PyObject *obj;
++ crypto_PKeyObj *key;
++ int answer;
++
++ if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj)) {
++ return NULL;
++ }
++
++ key = (crypto_PKeyObj *)obj;
++
++ if ((answer = X509_CRL_verify(self->crl, key->pkey)) <= 0) {
++ exception_from_error_queue(crypto_Error);
++ return NULL;
++ }
++
++ return PyLong_FromLong(answer);
++}
++
++static char crypto_CRL_get_issuer_doc[] = "\n\
++Create an X509Name object for the issuer of the certificate\n\
++\n\
++@return: An X509Name object\n\
++";
++
++static PyObject *
++crypto_CRL_get_issuer(crypto_CRLObj *self, PyObject *args)
++{
++ crypto_X509NameObj *pyname;
++ X509_NAME *name;
++
++ if (!PyArg_ParseTuple(args, ":get_issuer"))
++ return NULL;
++
++ name = X509_CRL_get_issuer(self->crl);
++ pyname = crypto_X509Name_New(name, 0);
++ if (pyname != NULL)
++ {
++ pyname->parent_cert = (PyObject *)self;
++ Py_INCREF(self);
++ }
++ return (PyObject *)pyname;
++}
++
++static char crypto_CRL_get_nextUpdate_doc[] = "\n\
++Retrieve the time stamp for when the CRL gets its next update\n\
++\n\
++@return: A string giving the timestamp, in the format:\n\
++\n\
++ YYYYMMDDhhmmssZ\n\
++ YYYYMMDDhhmmss+hhmm\n\
++ YYYYMMDDhhmmss-hhmm\n\
++ or None if there is no value set.\n\
++";
++
++static PyObject*
++crypto_CRL_get_nextUpdate(crypto_CRLObj *self, PyObject *args)
++{
++ /*
++ * X509_CRL_get_nextUpdate returns a borrowed reference.
++ */
++ return _get_asn1_time(
++ ":get_nextUpdate", X509_CRL_get_nextUpdate(self->crl), args);
++}
++
++
+ crypto_CRLObj *
+ crypto_CRL_New(X509_CRL *crl) {
+ crypto_CRLObj *self;
+@@ -205,6 +283,9 @@
+ ADD_KW_METHOD(add_revoked),
+ ADD_METHOD(get_revoked),
+ ADD_KW_METHOD(export),
++ ADD_KW_METHOD(verify),
++ ADD_KW_METHOD(get_issuer),
++ ADD_KW_METHOD(get_nextUpdate),
+ { NULL, NULL }
+ };
+ #undef ADD_METHOD
+--- pyOpenSSL-0.13/OpenSSL/crypto/x509.c 2013-08-26 15:04:14.943271276 -0700
++++ pyOpenSSL-0.13/OpenSSL/crypto/x509.c 2013-08-26 15:05:00.183501160 -0700
+@@ -761,6 +761,57 @@
+ return (PyObject*)extobj;
+ }
+
++static char crypto_X509_verify_doc[] = "\n\
++Verifies the certificate using the supplied public key\n\
++\n\
++@param key: a public key\n\
++@type key: L{PKey}\n\
++@return: True if the signature is correct.\n\
++@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
++ problem verifying the signature.\n\
++";
++
++PyObject *
++crypto_X509_verify(crypto_X509Obj *self, PyObject *args)
++{
++ PyObject *obj;
++ crypto_PKeyObj *key;
++ int answer;
++
++ if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj)) {
++ return NULL;
++ }
++
++ key = (crypto_PKeyObj *)obj;
++
++ if ((answer = X509_verify(self->x509, key->pkey)) <= 0) {
++ exception_from_error_queue(crypto_Error);
++ return NULL;
++ }
++
++ return PyLong_FromLong(answer);
++}
++
++
++static char crypto_X509_check_ca_doc[] = "\n\
++Checks if the certificate is a CA\n\
++\n\
++@return: 0 if not a CA, >0 if a CA\n\
++";
++
++PyObject *
++crypto_X509_check_ca(crypto_X509Obj *self, PyObject *args)
++{
++ int answer;
++
++ if (!PyArg_ParseTuple(args, ":check_ca"))
++ return NULL;
++
++ answer = X509_check_ca(self->x509);
++
++ return PyLong_FromLong(answer);
++}
++
+ /*
+ * ADD_METHOD(name) expands to a correct PyMethodDef declaration
+ * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
+@@ -794,6 +845,8 @@
+ ADD_METHOD(add_extensions),
+ ADD_METHOD(get_extension),
+ ADD_METHOD(get_extension_count),
++ ADD_METHOD(verify),
++ ADD_METHOD(check_ca),
+ { NULL, NULL }
+ };
+ #undef ADD_METHOD
+--- pyOpenSSL-0.13/OpenSSL/test/test_crypto.py 2013-08-26 15:04:14.951459483 -0700
++++ pyOpenSSL-0.13/OpenSSL/test/test_crypto.py 2013-08-26 15:14:40.335995703 -0700
+@@ -1090,6 +1090,18 @@
+ WpOdIpB8KksUTCzV591Nr1wd
+ -----END CERTIFICATE-----
+ """
++ def setUp(self):
++ # create new CA
++ self.ca_key = PKey()
++ self.ca_key.generate_key(TYPE_RSA, 384)
++
++ self.ca = X509()
++ self.ca.get_subject().commonName = "Yoda root CA"
++ self.ca.set_issuer(self.ca.get_subject())
++ self.ca.set_pubkey(self.ca_key)
++ self.ca.sign(self.ca_key, "sha1")
++
++
+ def signable(self):
+ """
+ Create and return a new L{X509}.
+@@ -1620,6 +1632,51 @@
+ self.assertRaises(ValueError, cert.get_signature_algorithm)
+
+
++ def test_key_verify(self):
++ """
++ L{X509.verify} succeeds when passed a valid CA key, raises
++ L{OpenSSL.crypto.Error} otherwise.
++ """
++ key = PKey()
++ key.generate_key(TYPE_RSA, 384)
++ req = X509Req()
++ req.get_subject().commonName = "Master Luke"
++ req.set_pubkey(key)
++ req.sign(key, "sha1")
++ cert = X509()
++ cert.set_subject(req.get_subject())
++ cert.set_pubkey(key)
++ cert.set_issuer(self.ca.get_subject())
++ cert.sign(self.ca_key, "sha1")
++
++ self.assertTrue(cert.verify(self.ca_key))
++ self.assertRaises(Error, cert.verify, key)
++
++
++ def test_is_ca(self):
++ """
++ L{X509.check_ca} returns a value >0 if certificate is a CA, returns 0
++ if not.
++ """
++ res = self.ca.check_ca()
++ self.assertTrue(res > 0)
++
++ # Try with a non-ca cert
++ key = PKey()
++ key.generate_key(TYPE_RSA, 384)
++ req = X509Req()
++ req.get_subject().commonName = "Master Luke"
++ req.set_pubkey(key)
++ req.sign(key, "sha1")
++ cert = X509()
++ cert.set_subject(req.get_subject())
++ cert.set_pubkey(key)
++ cert.set_issuer(self.ca.get_subject())
++ cert.sign(self.ca_key, "sha1")
++ res = cert.check_ca()
++ self.assertEqual(res, 0)
++
++
+
+ class PKCS12Tests(TestCase):
+ """
+@@ -2521,6 +2578,18 @@
+ cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
+ pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
+
++ def setUp(self):
++ # create new CA
++ self.ca_key = PKey()
++ self.ca_key.generate_key(TYPE_RSA, 384)
++
++ self.ca = X509()
++ self.ca.get_subject().commonName = "Yoda root CA"
++ self.ca.set_issuer(self.ca.get_subject())
++ self.ca.set_pubkey(self.ca_key)
++ self.ca.sign(self.ca_key, "sha1")
++
++
+ def test_construction(self):
+ """
+ Confirm we can create L{OpenSSL.crypto.CRL}. Check
+@@ -2712,6 +2781,44 @@
+ self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
+
+
++ def test_crl_verify(self):
++ """
++ Test that L{OpenSSL.CRL.verify} correctly verifies CRL with the
++ pubkey of the issuing CA, raises L{OpenSSL.crypto.Error} in case of
++ bogus key.
++ """
++ s = CRL().export(self.ca, self.ca_key)
++ crl = load_crl(FILETYPE_PEM, s)
++ res = crl.verify(self.ca_key)
++ self.assertTrue(res)
++
++ boguskey = PKey()
++ boguskey.generate_key(TYPE_RSA, 384)
++ self.assertRaises(Error, crl.verify, boguskey)
++
++
++ def test_crl_get_issuer(self):
++ """
++ Test that L{OpenSSL.CRL.get_issuer} returns a L{OpenSSL.X509Name} object
++ with the correct issuer information.
++ """
++ s = CRL().export(self.ca, self.ca_key)
++ crl = load_crl(FILETYPE_PEM, s)
++ issuer = crl.get_issuer()
++ self.assertTrue(isinstance(issuer, X509Name))
++ self.assertTrue(issuer.commonName == self.ca.get_subject().commonName)
++
++
++ def test_crl_get_nextUpdate(self):
++ """
++ Test that L{OpenSSL.CRL.get_nextUpdate} returns the correct date and
++ time of next update.
++ """
++ crl = load_crl(FILETYPE_PEM, crlData)
++ self.assertEqual(crl.get_nextUpdate(), "20120927024152Z")
++
++
++
+ class SignVerifyTests(TestCase):
+ """
+ Tests for L{OpenSSL.crypto.sign} and L{OpenSSL.crypto.verify}.