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}. |
|