components/python/pyopenssl/patches/3_add_if.patch
changeset 1456 b367e3ae9667
equal deleted inserted replaced
1455:74681f26bd4e 1456:b367e3ae9667
       
     1 #
       
     2 # This patch adds a few more interfaces to OpenSSL functions required for IPS.
       
     3 # The additional interfaces are:
       
     4 #     pyOpenSSL                     -> OpenSSL
       
     5 #      crypto.CRL.verify()              X509_CRL_verify()
       
     6 #      crypto.CRL.get_issuer()          X509_CRL_get_issuer()
       
     7 #      crypto.CRL.get_next_update()     X509_CRL_get_nextUpdate()
       
     8 #      crypto.X509.verify()             X509_verify()
       
     9 #      crypto.X509.check_ca()           X509_check_ca()
       
    10 #
       
    11 # The patch also adds test cases to the pyOpenSSL test suite for the added
       
    12 # functions.
       
    13 #
       
    14 --- pyOpenSSL-0.13/OpenSSL/crypto/crl.c	2013-08-26 15:04:14.949389722 -0700
       
    15 +++ pyOpenSSL-0.13/OpenSSL/crypto/crl.c	2013-08-26 15:05:00.183031221 -0700
       
    16 @@ -180,6 +180,84 @@
       
    17      return buffer;
       
    18  }
       
    19  
       
    20 +static char crypto_CRL_verify_doc[] = "\n\
       
    21 +Verifies the CRL using the supplied public key\n\
       
    22 +\n\
       
    23 +@param key: a public key\n\
       
    24 +@type key: L{PKey}\n\
       
    25 +@return: True if the signature is correct.\n\
       
    26 +@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
       
    27 +    problem verifying the signature.\n\
       
    28 +";
       
    29 +
       
    30 +PyObject *
       
    31 +crypto_CRL_verify(crypto_CRLObj *self, PyObject *args)
       
    32 +{
       
    33 +    PyObject *obj;
       
    34 +    crypto_PKeyObj *key;
       
    35 +    int answer;
       
    36 +
       
    37 +    if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj)) {
       
    38 +        return NULL;
       
    39 +    }
       
    40 +
       
    41 +    key = (crypto_PKeyObj *)obj;
       
    42 +
       
    43 +    if ((answer = X509_CRL_verify(self->crl, key->pkey)) <= 0) {
       
    44 +        exception_from_error_queue(crypto_Error);
       
    45 +        return NULL;
       
    46 +    }
       
    47 +
       
    48 +    return PyLong_FromLong(answer);
       
    49 +}
       
    50 +
       
    51 +static char crypto_CRL_get_issuer_doc[] = "\n\
       
    52 +Create an X509Name object for the issuer of the certificate\n\
       
    53 +\n\
       
    54 +@return: An X509Name object\n\
       
    55 +";
       
    56 +
       
    57 +static PyObject *
       
    58 +crypto_CRL_get_issuer(crypto_CRLObj *self, PyObject *args)
       
    59 +{
       
    60 +    crypto_X509NameObj *pyname;
       
    61 +    X509_NAME *name;
       
    62 +
       
    63 +    if (!PyArg_ParseTuple(args, ":get_issuer"))
       
    64 +        return NULL;
       
    65 +
       
    66 +    name = X509_CRL_get_issuer(self->crl);
       
    67 +    pyname = crypto_X509Name_New(name, 0);
       
    68 +    if (pyname != NULL)
       
    69 +    {
       
    70 +        pyname->parent_cert = (PyObject *)self;
       
    71 +        Py_INCREF(self);
       
    72 +    }
       
    73 +    return (PyObject *)pyname;
       
    74 +}
       
    75 +
       
    76 +static char crypto_CRL_get_nextUpdate_doc[] = "\n\
       
    77 +Retrieve the time stamp for when the CRL gets its next update\n\
       
    78 +\n\
       
    79 +@return: A string giving the timestamp, in the format:\n\
       
    80 +\n\
       
    81 +                 YYYYMMDDhhmmssZ\n\
       
    82 +                 YYYYMMDDhhmmss+hhmm\n\
       
    83 +                 YYYYMMDDhhmmss-hhmm\n\
       
    84 +           or None if there is no value set.\n\
       
    85 +";
       
    86 +
       
    87 +static PyObject*
       
    88 +crypto_CRL_get_nextUpdate(crypto_CRLObj *self, PyObject *args)
       
    89 +{
       
    90 +	/*
       
    91 +	 * X509_CRL_get_nextUpdate returns a borrowed reference.
       
    92 +	 */
       
    93 +	return _get_asn1_time(
       
    94 +		":get_nextUpdate", X509_CRL_get_nextUpdate(self->crl), args);
       
    95 +}
       
    96 +
       
    97 +
       
    98  crypto_CRLObj *
       
    99  crypto_CRL_New(X509_CRL *crl) {
       
   100      crypto_CRLObj *self;
       
   101 @@ -205,6 +283,9 @@
       
   102      ADD_KW_METHOD(add_revoked),
       
   103      ADD_METHOD(get_revoked),
       
   104      ADD_KW_METHOD(export),
       
   105 +    ADD_KW_METHOD(verify),
       
   106 +    ADD_KW_METHOD(get_issuer),
       
   107 +    ADD_KW_METHOD(get_nextUpdate),
       
   108      { NULL, NULL }
       
   109  };
       
   110  #undef ADD_METHOD
       
   111 --- pyOpenSSL-0.13/OpenSSL/crypto/x509.c	2013-08-26 15:04:14.943271276 -0700
       
   112 +++ pyOpenSSL-0.13/OpenSSL/crypto/x509.c	2013-08-26 15:05:00.183501160 -0700
       
   113 @@ -761,6 +761,57 @@
       
   114      return (PyObject*)extobj;
       
   115  }
       
   116  
       
   117 +static char crypto_X509_verify_doc[] = "\n\
       
   118 +Verifies the certificate using the supplied public key\n\
       
   119 +\n\
       
   120 +@param key: a public key\n\
       
   121 +@type key: L{PKey}\n\
       
   122 +@return: True if the signature is correct.\n\
       
   123 +@raise OpenSSL.crypto.Error: If the signature is invalid or there is a\n\
       
   124 +    problem verifying the signature.\n\
       
   125 +";
       
   126 +
       
   127 +PyObject *
       
   128 +crypto_X509_verify(crypto_X509Obj *self, PyObject *args)
       
   129 +{
       
   130 +    PyObject *obj;
       
   131 +    crypto_PKeyObj *key;
       
   132 +    int answer;
       
   133 +
       
   134 +    if (!PyArg_ParseTuple(args, "O!:verify", &crypto_PKey_Type, &obj)) {
       
   135 +        return NULL;
       
   136 +    }
       
   137 +
       
   138 +    key = (crypto_PKeyObj *)obj;
       
   139 +
       
   140 +    if ((answer = X509_verify(self->x509, key->pkey)) <= 0) {
       
   141 +        exception_from_error_queue(crypto_Error);
       
   142 +        return NULL;
       
   143 +    }
       
   144 +
       
   145 +    return PyLong_FromLong(answer);
       
   146 +}
       
   147 +
       
   148 +
       
   149 +static char crypto_X509_check_ca_doc[] = "\n\
       
   150 +Checks if the certificate is a CA\n\
       
   151 +\n\
       
   152 +@return: 0 if not a CA, >0 if a CA\n\
       
   153 +";
       
   154 +
       
   155 +PyObject *
       
   156 +crypto_X509_check_ca(crypto_X509Obj *self, PyObject *args)
       
   157 +{
       
   158 +    int answer;
       
   159 +
       
   160 +    if (!PyArg_ParseTuple(args, ":check_ca"))
       
   161 +        return NULL;
       
   162 +
       
   163 +    answer = X509_check_ca(self->x509);
       
   164 +
       
   165 +    return PyLong_FromLong(answer);
       
   166 +}
       
   167 +
       
   168  /*
       
   169   * ADD_METHOD(name) expands to a correct PyMethodDef declaration
       
   170   *   {  'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
       
   171 @@ -794,6 +845,8 @@
       
   172      ADD_METHOD(add_extensions),
       
   173      ADD_METHOD(get_extension),
       
   174      ADD_METHOD(get_extension_count),
       
   175 +    ADD_METHOD(verify),
       
   176 +    ADD_METHOD(check_ca),
       
   177      { NULL, NULL }
       
   178  };
       
   179  #undef ADD_METHOD
       
   180 --- pyOpenSSL-0.13/OpenSSL/test/test_crypto.py	2013-08-26 15:04:14.951459483 -0700
       
   181 +++ pyOpenSSL-0.13/OpenSSL/test/test_crypto.py	2013-08-26 15:14:40.335995703 -0700
       
   182 @@ -1090,6 +1090,18 @@
       
   183  WpOdIpB8KksUTCzV591Nr1wd
       
   184  -----END CERTIFICATE-----
       
   185      """
       
   186 +    def setUp(self):
       
   187 +        # create new CA
       
   188 +        self.ca_key = PKey()
       
   189 +        self.ca_key.generate_key(TYPE_RSA, 384)
       
   190 +     
       
   191 +        self.ca = X509()
       
   192 +        self.ca.get_subject().commonName = "Yoda root CA"
       
   193 +        self.ca.set_issuer(self.ca.get_subject())
       
   194 +        self.ca.set_pubkey(self.ca_key)
       
   195 +        self.ca.sign(self.ca_key, "sha1")
       
   196 +
       
   197 +
       
   198      def signable(self):
       
   199          """
       
   200          Create and return a new L{X509}.
       
   201 @@ -1620,6 +1632,51 @@
       
   202          self.assertRaises(ValueError, cert.get_signature_algorithm)
       
   203  
       
   204  
       
   205 +    def test_key_verify(self):
       
   206 +        """
       
   207 +        L{X509.verify} succeeds when passed a valid CA key, raises
       
   208 +        L{OpenSSL.crypto.Error} otherwise.
       
   209 +        """
       
   210 +        key = PKey()
       
   211 +        key.generate_key(TYPE_RSA, 384)
       
   212 +        req = X509Req()
       
   213 +        req.get_subject().commonName = "Master Luke"
       
   214 +        req.set_pubkey(key)
       
   215 +        req.sign(key, "sha1")
       
   216 +        cert = X509()
       
   217 +        cert.set_subject(req.get_subject())
       
   218 +        cert.set_pubkey(key)
       
   219 +        cert.set_issuer(self.ca.get_subject())
       
   220 +        cert.sign(self.ca_key, "sha1")
       
   221 +
       
   222 +        self.assertTrue(cert.verify(self.ca_key))
       
   223 +        self.assertRaises(Error, cert.verify, key)
       
   224 +
       
   225 +
       
   226 +    def test_is_ca(self):
       
   227 +        """
       
   228 +        L{X509.check_ca} returns a value >0 if certificate is a CA, returns 0 
       
   229 +        if not.
       
   230 +        """
       
   231 +        res = self.ca.check_ca()
       
   232 +        self.assertTrue(res > 0)
       
   233 +
       
   234 +        # Try with a non-ca cert
       
   235 +        key = PKey()
       
   236 +        key.generate_key(TYPE_RSA, 384)
       
   237 +        req = X509Req()
       
   238 +        req.get_subject().commonName = "Master Luke"
       
   239 +        req.set_pubkey(key)
       
   240 +        req.sign(key, "sha1")
       
   241 +        cert = X509()
       
   242 +        cert.set_subject(req.get_subject())
       
   243 +        cert.set_pubkey(key)
       
   244 +        cert.set_issuer(self.ca.get_subject())
       
   245 +        cert.sign(self.ca_key, "sha1")
       
   246 +        res = cert.check_ca()
       
   247 +        self.assertEqual(res, 0)
       
   248 +
       
   249 +
       
   250  
       
   251  class PKCS12Tests(TestCase):
       
   252      """
       
   253 @@ -2521,6 +2578,18 @@
       
   254      cert = load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
       
   255      pkey = load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
       
   256  
       
   257 +    def setUp(self):
       
   258 +        # create new CA
       
   259 +        self.ca_key = PKey()
       
   260 +        self.ca_key.generate_key(TYPE_RSA, 384)
       
   261 +     
       
   262 +        self.ca = X509()
       
   263 +        self.ca.get_subject().commonName = "Yoda root CA"
       
   264 +        self.ca.set_issuer(self.ca.get_subject())
       
   265 +        self.ca.set_pubkey(self.ca_key)
       
   266 +        self.ca.sign(self.ca_key, "sha1")
       
   267 +
       
   268 +
       
   269      def test_construction(self):
       
   270          """
       
   271          Confirm we can create L{OpenSSL.crypto.CRL}.  Check
       
   272 @@ -2712,6 +2781,44 @@
       
   273          self.assertRaises(Error, load_crl, FILETYPE_PEM, "hello, world")
       
   274  
       
   275  
       
   276 +    def test_crl_verify(self):
       
   277 +        """
       
   278 +        Test that L{OpenSSL.CRL.verify} correctly verifies CRL with the
       
   279 +        pubkey of the issuing CA, raises L{OpenSSL.crypto.Error} in case of
       
   280 +        bogus key.
       
   281 +        """
       
   282 +        s = CRL().export(self.ca, self.ca_key)
       
   283 +        crl = load_crl(FILETYPE_PEM, s)
       
   284 +        res = crl.verify(self.ca_key)
       
   285 +        self.assertTrue(res)
       
   286 +
       
   287 +        boguskey = PKey()
       
   288 +        boguskey.generate_key(TYPE_RSA, 384)
       
   289 +        self.assertRaises(Error, crl.verify, boguskey)
       
   290 +
       
   291 +
       
   292 +    def test_crl_get_issuer(self):
       
   293 +        """
       
   294 +        Test that L{OpenSSL.CRL.get_issuer} returns a L{OpenSSL.X509Name} object
       
   295 +        with the correct issuer information.
       
   296 +         """
       
   297 +        s = CRL().export(self.ca, self.ca_key)
       
   298 +        crl = load_crl(FILETYPE_PEM, s)
       
   299 +        issuer = crl.get_issuer()
       
   300 +        self.assertTrue(isinstance(issuer, X509Name))
       
   301 +        self.assertTrue(issuer.commonName == self.ca.get_subject().commonName)
       
   302 +
       
   303 +
       
   304 +    def test_crl_get_nextUpdate(self):
       
   305 +        """
       
   306 +        Test that L{OpenSSL.CRL.get_nextUpdate} returns the correct date and
       
   307 +        time of next update.
       
   308 +         """
       
   309 +        crl = load_crl(FILETYPE_PEM, crlData)
       
   310 +        self.assertEqual(crl.get_nextUpdate(), "20120927024152Z")
       
   311 +
       
   312 +
       
   313 +
       
   314  class SignVerifyTests(TestCase):
       
   315      """
       
   316      Tests for L{OpenSSL.crypto.sign} and L{OpenSSL.crypto.verify}.