blob: 0754decf594dad202134a1f87ee17d029f4f2871 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509.c
3 *
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05004 * Copyright (C) AB Strakt
5 * Copyright (C) Jean-Paul Calderone
6 * See LICENSE for details.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 *
8 * Certificate (X.509) handling code, mostly thin wrappers around OpenSSL.
9 * See the file RATIONALE for a short explanation of why this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
Roland Hedberg7e4930e2008-04-22 22:58:50 +020016#include "x509ext.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040018/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050019 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
20 * http://www.openssl.org/ for more information
21 */
22
23static char crypto_X509_get_version_doc[] = "\n\
24Return version number of the certificate\n\
25\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040026@return: Version number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050027";
28
29static PyObject *
30crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
31{
32 if (!PyArg_ParseTuple(args, ":get_version"))
33 return NULL;
34
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -040035 return PyLong_FromLong((long)X509_get_version(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050036}
37
38static char crypto_X509_set_version_doc[] = "\n\
39Set version number of the certificate\n\
40\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040041@param version: The version number\n\
42@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050043";
44
45static PyObject *
46crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
47{
48 int version;
49
50 if (!PyArg_ParseTuple(args, "i:set_version", &version))
51 return NULL;
52
53 X509_set_version(self->x509, version);
54
55 Py_INCREF(Py_None);
56 return Py_None;
57}
58
59static char crypto_X509_get_serial_number_doc[] = "\n\
60Return serial number of the certificate\n\
61\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040062@return: Serial number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050063";
64
65static PyObject *
66crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
67{
68 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050069 BIGNUM *bignum;
70 char *hex;
71 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050072
73 if (!PyArg_ParseTuple(args, ":get_serial_number"))
74 return NULL;
75
76 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050077 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
78 hex = BN_bn2hex(bignum);
79 res = PyLong_FromString(hex, NULL, 16);
80 BN_free(bignum);
81 free(hex);
82 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050083}
84
85static char crypto_X509_set_serial_number_doc[] = "\n\
86Set serial number of the certificate\n\
87\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040088@param serial: The serial number\n\
89@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050090";
91
92static PyObject *
93crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
94{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050095 long small_serial;
96 PyObject *serial = NULL;
97 PyObject *hex = NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050098 ASN1_INTEGER *asn1_i = NULL;
99 BIGNUM *bignum = NULL;
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400100 char *hexstr;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500101
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500102 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500103 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500104 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500105
Jean-Paul Calderonec18669e2010-08-12 00:03:05 -0400106 if (!PyOpenSSL_Integer_Check(serial)) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500107 PyErr_SetString(
108 PyExc_TypeError, "serial number must be integer");
109 goto err;
110 }
111
Jean-Paul Calderonea5a032f2010-08-12 20:03:32 -0400112 if ((hex = PyOpenSSL_LongToHex(serial)) == NULL) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500113 goto err;
114 }
115
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400116#ifdef PY3
117 {
118 PyObject *hexbytes = PyUnicode_AsASCIIString(hex);
119 Py_DECREF(hex);
120 hex = hexbytes;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500121 }
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400122#endif
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500123
124 /**
125 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
126 * it. If bignum is still NULL after this call, then the return value
127 * is actually the result. I hope. -exarkun
128 */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400129 hexstr = PyBytes_AsString(hex);
Jean-Paul Calderone8eb46c72010-08-22 17:05:37 -0400130 if (hexstr[1] == 'x') {
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400131 /* +2 to skip the "0x" */
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400132 hexstr += 2;
Jean-Paul Calderone728eba92010-08-12 20:17:59 -0400133 }
Jean-Paul Calderonedd467fb2010-08-12 20:44:32 -0400134 small_serial = BN_hex2bn(&bignum, hexstr);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500135
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500136 Py_DECREF(hex);
137 hex = NULL;
138
139 if (bignum == NULL) {
140 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
Rick Deand369c932009-07-08 11:48:33 -0500141 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500142 goto err;
143 }
144 } else {
145 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
146 BN_free(bignum);
147 bignum = NULL;
148 if (asn1_i == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500149 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500150 goto err;
151 }
152 if (!X509_set_serialNumber(self->x509, asn1_i)) {
Rick Deand369c932009-07-08 11:48:33 -0500153 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500154 goto err;
155 }
156 ASN1_INTEGER_free(asn1_i);
157 asn1_i = NULL;
158 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500159
160 Py_INCREF(Py_None);
161 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500162
163 err:
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500164 if (hex) {
165 Py_DECREF(hex);
166 }
167 if (bignum) {
168 BN_free(bignum);
169 }
170 if (asn1_i) {
171 ASN1_INTEGER_free(asn1_i);
172 }
173 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500174}
175
176static char crypto_X509_get_issuer_doc[] = "\n\
177Create an X509Name object for the issuer of the certificate\n\
178\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400179@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500180";
181
182static PyObject *
183crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
184{
185 crypto_X509NameObj *pyname;
186 X509_NAME *name;
187
188 if (!PyArg_ParseTuple(args, ":get_issuer"))
189 return NULL;
190
191 name = X509_get_issuer_name(self->x509);
192 pyname = crypto_X509Name_New(name, 0);
193 if (pyname != NULL)
194 {
195 pyname->parent_cert = (PyObject *)self;
196 Py_INCREF(self);
197 }
198 return (PyObject *)pyname;
199}
200
201static char crypto_X509_set_issuer_doc[] = "\n\
202Set the issuer of the certificate\n\
203\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400204@param issuer: The issuer name\n\
205@type issuer: L{X509Name}\n\
206@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500207";
208
209static PyObject *
210crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
211{
212 crypto_X509NameObj *issuer;
213
214 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
215 &issuer))
216 return NULL;
217
218 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
219 {
Rick Deand369c932009-07-08 11:48:33 -0500220 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500221 return NULL;
222 }
223
224 Py_INCREF(Py_None);
225 return Py_None;
226}
227
228static char crypto_X509_get_subject_doc[] = "\n\
229Create an X509Name object for the subject of the certificate\n\
230\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400231@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500232";
233
234static PyObject *
235crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
236{
237 crypto_X509NameObj *pyname;
238 X509_NAME *name;
239
240 if (!PyArg_ParseTuple(args, ":get_subject"))
241 return NULL;
242
243 name = X509_get_subject_name(self->x509);
244 pyname = crypto_X509Name_New(name, 0);
245 if (pyname != NULL)
246 {
247 pyname->parent_cert = (PyObject *)self;
248 Py_INCREF(self);
249 }
250 return (PyObject *)pyname;
251}
252
253static char crypto_X509_set_subject_doc[] = "\n\
254Set the subject of the certificate\n\
255\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400256@param subject: The subject name\n\
257@type subject: L{X509Name}\n\
258@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500259";
260
261static PyObject *
262crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
263{
264 crypto_X509NameObj *subject;
265
266 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
267 &subject))
268 return NULL;
269
270 if (!X509_set_subject_name(self->x509, subject->x509_name))
271 {
Rick Deand369c932009-07-08 11:48:33 -0500272 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500273 return NULL;
274 }
275
276 Py_INCREF(Py_None);
277 return Py_None;
278}
279
280static char crypto_X509_get_pubkey_doc[] = "\n\
281Get the public key of the certificate\n\
282\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400283@return: The public key\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500284";
285
286static PyObject *
287crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
288{
289 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
290 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400291 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500292
293 if (!PyArg_ParseTuple(args, ":get_pubkey"))
294 return NULL;
295
296 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
297 {
Rick Deand369c932009-07-08 11:48:33 -0500298 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500299 return NULL;
300 }
301
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400302 py_pkey = crypto_PKey_New(pkey, 1);
303 if (py_pkey != NULL) {
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400304 py_pkey->only_public = 1;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400305 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400306 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500307}
308
309static char crypto_X509_set_pubkey_doc[] = "\n\
310Set the public key of the certificate\n\
311\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400312@param pkey: The public key\n\
313@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500314";
315
316static PyObject *
317crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
318{
319 crypto_PKeyObj *pkey;
320
321 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
322 return NULL;
323
324 if (!X509_set_pubkey(self->x509, pkey->pkey))
325 {
Rick Deand369c932009-07-08 11:48:33 -0500326 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500327 return NULL;
328 }
329
330 Py_INCREF(Py_None);
331 return Py_None;
332}
333
Rick Dean536ba022009-07-24 23:57:27 -0500334PyObject*
335_set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400336{
337 char *when;
338
339 if (!PyArg_ParseTuple(args, format, &when))
340 return NULL;
341
342 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
343 ASN1_GENERALIZEDTIME dummy;
344 dummy.type = V_ASN1_GENERALIZEDTIME;
345 dummy.length = strlen(when);
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500346 dummy.data = (unsigned char *)when;
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400347 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
348 PyErr_SetString(PyExc_ValueError, "Invalid string");
349 } else {
350 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
351 }
352 return NULL;
353 }
354 Py_INCREF(Py_None);
355 return Py_None;
356}
357
358static char crypto_X509_set_notBefore_doc[] = "\n\
359Set the time stamp for when the certificate starts being valid\n\
360\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400361@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400362\n\
363 YYYYMMDDhhmmssZ\n\
364 YYYYMMDDhhmmss+hhmm\n\
365 YYYYMMDDhhmmss-hhmm\n\
366\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400367@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400368";
369
370static PyObject*
371crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
372{
373 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400374 BYTESTRING_FMT ":set_notBefore",
375 X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400376}
377
378static char crypto_X509_set_notAfter_doc[] = "\n\
379Set the time stamp for when the certificate stops being valid\n\
380\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400381@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400382\n\
383 YYYYMMDDhhmmssZ\n\
384 YYYYMMDDhhmmss+hhmm\n\
385 YYYYMMDDhhmmss-hhmm\n\
386\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400387@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400388";
389
390static PyObject*
391crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
392{
393 return _set_asn1_time(
Jean-Paul Calderone40dd0992010-08-22 17:52:07 -0400394 BYTESTRING_FMT ":set_notAfter",
395 X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400396}
397
Rick Dean536ba022009-07-24 23:57:27 -0500398PyObject*
399_get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400400{
401 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
402 PyObject *py_timestamp = NULL;
403
404 if (!PyArg_ParseTuple(args, format)) {
405 return NULL;
406 }
407
408 /*
409 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
410 */
411 /*
412 * There must be a way to do this without touching timestamp->data
413 * directly. -exarkun
414 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400415 if (timestamp->length == 0) {
416 Py_INCREF(Py_None);
417 return Py_None;
418 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400419 return PyBytes_FromString((char *)timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400420 } else {
421 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400422 if (gt_timestamp == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500423 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400424 return NULL;
425 } else {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400426 py_timestamp = PyBytes_FromString((char *)gt_timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400427 ASN1_GENERALIZEDTIME_free(gt_timestamp);
428 return py_timestamp;
429 }
430 }
431}
432
433static char crypto_X509_get_notBefore_doc[] = "\n\
434Retrieve the time stamp for when the certificate starts being valid\n\
435\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400436@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400437\n\
438 YYYYMMDDhhmmssZ\n\
439 YYYYMMDDhhmmss+hhmm\n\
440 YYYYMMDDhhmmss-hhmm\n\
441 or None if there is no value set.\n\
442";
443
444static PyObject*
445crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
446{
447 /*
448 * X509_get_notBefore returns a borrowed reference.
449 */
450 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500451 ":get_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400452}
453
454
455static char crypto_X509_get_notAfter_doc[] = "\n\
456Retrieve the time stamp for when the certificate stops being valid\n\
457\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400458@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400459\n\
460 YYYYMMDDhhmmssZ\n\
461 YYYYMMDDhhmmss+hhmm\n\
462 YYYYMMDDhhmmss-hhmm\n\
463 or None if there is no value set.\n\
464";
465
466static PyObject*
467crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
468{
469 /*
470 * X509_get_notAfter returns a borrowed reference.
471 */
472 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500473 ":get_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400474}
475
476
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500477static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400478Change the timestamp for when the certificate starts being valid to the current\n\
479time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500480\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400481@param amount: The number of seconds by which to adjust the starting validity\n\
482 time.\n\
483@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500484";
485
486static PyObject *
487crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
488{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400489 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500490
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400491 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492 return NULL;
493
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400494 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500495
496 Py_INCREF(Py_None);
497 return Py_None;
498}
499
500static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
501Adjust the time stamp for when the certificate stops being valid\n\
502\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400503@param amount: The number of seconds by which to adjust the ending validity\n\
504 time.\n\
505@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500506";
507
508static PyObject *
509crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
510{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400511 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500512
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400513 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500514 return NULL;
515
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400516 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500517
518 Py_INCREF(Py_None);
519 return Py_None;
520}
521
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400522
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400523static char crypto_X509_get_signature_algorithm_doc[] = "\n\
524Retrieve the signature algorithm used in the certificate\n\
525\n\
Jean-Paul Calderone4a3a7c12011-05-19 17:46:40 -0400526@return: A byte string giving the name of the signature algorithm used in\n\
527 the certificate.\n\
528@raise ValueError: If the signature algorithm is undefined.\n\
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400529";
530
531static PyObject *
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400532crypto_X509_get_signature_algorithm(crypto_X509Obj *self, PyObject *args) {
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400533 ASN1_OBJECT *alg;
534 int nid;
535
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400536 if (!PyArg_ParseTuple(args, ":get_signature_algorithm")) {
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400537 return NULL;
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400538 }
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400539
540 alg = self->x509->cert_info->signature->algorithm;
541 nid = OBJ_obj2nid(alg);
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -0400542 if (nid == NID_undef) {
543 PyErr_SetString(PyExc_ValueError, "Undefined signature algorithm");
544 return NULL;
545 }
Jean-Paul Calderone489969f2011-05-18 20:53:07 -0400546 return PyBytes_FromString(OBJ_nid2ln(nid));
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400547}
548
549
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500550static char crypto_X509_sign_doc[] = "\n\
551Sign the certificate using the supplied key and digest\n\
552\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400553@param pkey: The key to sign with\n\
554@param digest: The message digest to use\n\
555@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500556";
557
558static PyObject *
559crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
560{
561 crypto_PKeyObj *pkey;
562 char *digest_name;
563 const EVP_MD *digest;
564
565 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
566 &digest_name))
567 return NULL;
568
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400569 if (pkey->only_public) {
570 PyErr_SetString(PyExc_ValueError, "Key has only public part");
571 return NULL;
572 }
573
574 if (!pkey->initialized) {
575 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
576 return NULL;
577 }
578
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500579 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
580 {
581 PyErr_SetString(PyExc_ValueError, "No such digest method");
582 return NULL;
583 }
584
585 if (!X509_sign(self->x509, pkey->pkey, digest))
586 {
Rick Deand369c932009-07-08 11:48:33 -0500587 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500588 return NULL;
589 }
590
591 Py_INCREF(Py_None);
592 return Py_None;
593}
594
595static char crypto_X509_has_expired_doc[] = "\n\
596Check whether the certificate has expired.\n\
597\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400598@return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500599";
600
601static PyObject *
602crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
603{
604 time_t tnow;
605
606 if (!PyArg_ParseTuple(args, ":has_expired"))
607 return NULL;
608
609 tnow = time(NULL);
610 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400611 return PyLong_FromLong(1L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500612 else
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400613 return PyLong_FromLong(0L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500614}
615
616static char crypto_X509_subject_name_hash_doc[] = "\n\
617Return the hash of the X509 subject.\n\
618\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400619@return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500620";
621
622static PyObject *
623crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
624{
625 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
626 return NULL;
627
Jean-Paul Calderone37306a62010-08-28 15:09:24 -0400628 return PyLong_FromLongLong(X509_subject_name_hash(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500629}
630
631static char crypto_X509_digest_doc[] = "\n\
632Return the digest of the X509 object.\n\
633\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400634@return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500635";
636
637static PyObject *
638crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
639{
640 unsigned char fp[EVP_MAX_MD_SIZE];
641 char *tmp;
642 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500643 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500644 PyObject *ret;
645 const EVP_MD *digest;
646
647 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
648 return NULL;
649
650 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
651 {
652 PyErr_SetString(PyExc_ValueError, "No such digest method");
653 return NULL;
654 }
655
656 if (!X509_digest(self->x509,digest,fp,&len))
657 {
Rick Deand369c932009-07-08 11:48:33 -0500658 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500659 }
660 tmp = malloc(3*len+1);
661 memset(tmp, 0, 3*len+1);
662 for (i = 0; i < len; i++) {
663 sprintf(tmp+i*3,"%02X:",fp[i]);
664 }
665 tmp[3*len-1] = 0;
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400666 ret = PyBytes_FromStringAndSize(tmp,3*len-1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500667 free(tmp);
668 return ret;
669}
670
671
672static char crypto_X509_add_extensions_doc[] = "\n\
673Add extensions to the certificate.\n\
674\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400675@param extensions: a sequence of X509Extension objects\n\
676@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500677";
678
679static PyObject *
680crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
681{
682 PyObject *extensions, *seq;
683 crypto_X509ExtensionObj *ext;
684 int nr_of_extensions, i;
685
686 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
687 return NULL;
688
689 seq = PySequence_Fast(extensions, "Expected a sequence");
690 if (seq == NULL)
691 return NULL;
692
693 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
694
695 for (i = 0; i < nr_of_extensions; i++)
696 {
697 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
698 if (!crypto_X509Extension_Check(ext))
699 {
700 Py_DECREF(seq);
701 PyErr_SetString(PyExc_ValueError,
702 "One of the elements is not an X509Extension");
703 return NULL;
704 }
705 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
706 {
707 Py_DECREF(seq);
Rick Deand369c932009-07-08 11:48:33 -0500708 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500709 return NULL;
710 }
711 }
712
713 Py_INCREF(Py_None);
714 return Py_None;
715}
716
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200717static char crypto_X509_get_extension_count_doc[] = "\n\
718Get the number of extensions on the certificate.\n\
719\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400720@return: Number of extensions as a Python integer\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200721";
722
723static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400724crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args) {
725 if (!PyArg_ParseTuple(args, ":get_extension_count")) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200726 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400727 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200728
Jean-Paul Calderone48659612011-04-06 17:22:15 -0400729 return PyLong_FromLong((long)X509_get_ext_count(self->x509));
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200730}
731
732static char crypto_X509_get_extension_doc[] = "\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400733Get a specific extension of the certificate by index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200734\n\
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -0400735@param index: The index of the extension to retrieve.\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400736@return: The X509Extension object at the specified index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200737";
738
739static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400740crypto_X509_get_extension(crypto_X509Obj *self, PyObject *args) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200741 crypto_X509ExtensionObj *extobj;
742 int loc;
743 X509_EXTENSION *ext;
744
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400745 if (!PyArg_ParseTuple(args, "i:get_extension", &loc)) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200746 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400747 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200748
749 /* will return NULL if loc is outside the range of extensions,
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400750 not registered as an error*/
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200751 ext = X509_get_ext(self->x509, loc);
752 if (!ext) {
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -0400753 PyErr_SetString(PyExc_IndexError, "extension index out of bounds");
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200754 return NULL; /* Should be reported as an IndexError ? */
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200755 }
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400756
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200757 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
758 extobj->x509_extension = X509_EXTENSION_dup(ext);
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400759
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -0400760 return (PyObject*)extobj;
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200761}
762
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500763/*
764 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
765 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
766 * for convenience
767 */
768#define ADD_METHOD(name) \
769 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
770static PyMethodDef crypto_X509_methods[] =
771{
772 ADD_METHOD(get_version),
773 ADD_METHOD(set_version),
774 ADD_METHOD(get_serial_number),
775 ADD_METHOD(set_serial_number),
776 ADD_METHOD(get_issuer),
777 ADD_METHOD(set_issuer),
778 ADD_METHOD(get_subject),
779 ADD_METHOD(set_subject),
780 ADD_METHOD(get_pubkey),
781 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400782 ADD_METHOD(get_notBefore),
783 ADD_METHOD(set_notBefore),
784 ADD_METHOD(get_notAfter),
785 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500786 ADD_METHOD(gmtime_adj_notBefore),
787 ADD_METHOD(gmtime_adj_notAfter),
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400788 ADD_METHOD(get_signature_algorithm),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500789 ADD_METHOD(sign),
790 ADD_METHOD(has_expired),
791 ADD_METHOD(subject_name_hash),
792 ADD_METHOD(digest),
793 ADD_METHOD(add_extensions),
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200794 ADD_METHOD(get_extension),
795 ADD_METHOD(get_extension_count),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500796 { NULL, NULL }
797};
798#undef ADD_METHOD
799
800
801/*
802 * Constructor for X509 objects, never called by Python code directly
803 *
804 * Arguments: cert - A "real" X509 certificate object
805 * dealloc - Boolean value to specify whether the destructor should
806 * free the "real" X509 object
807 * Returns: The newly created X509 object
808 */
809crypto_X509Obj *
810crypto_X509_New(X509 *cert, int dealloc)
811{
812 crypto_X509Obj *self;
813
814 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
815
816 if (self == NULL)
817 return NULL;
818
819 self->x509 = cert;
820 self->dealloc = dealloc;
821
822 return self;
823}
824
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400825
826static char crypto_X509_doc[] = "\n\
827X509() -> X509 instance\n\
828\n\
829Create a new X509 object.\n\
830\n\
831@returns: The X509 object\n\
832";
833
834static PyObject *
835crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
836{
837 if (!PyArg_ParseTuple(args, ":X509")) {
838 return NULL;
839 }
840
841 return (PyObject *)crypto_X509_New(X509_new(), 1);
842}
843
844
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500845/*
846 * Deallocate the memory used by the X509 object
847 *
848 * Arguments: self - The X509 object
849 * Returns: None
850 */
851static void
852crypto_X509_dealloc(crypto_X509Obj *self)
853{
854 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
855 if (self->dealloc)
856 X509_free(self->x509);
857
858 PyObject_Del(self);
859}
860
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500861PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400862 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500863 "X509",
864 sizeof(crypto_X509Obj),
865 0,
866 (destructor)crypto_X509_dealloc,
867 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400868 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400869 NULL, /* setattr */
870 NULL, /* compare */
871 NULL, /* repr */
872 NULL, /* as_number */
873 NULL, /* as_sequence */
874 NULL, /* as_mapping */
875 NULL, /* hash */
876 NULL, /* call */
877 NULL, /* str */
878 NULL, /* getattro */
879 NULL, /* setattro */
880 NULL, /* as_buffer */
881 Py_TPFLAGS_DEFAULT,
882 crypto_X509_doc, /* doc */
883 NULL, /* traverse */
884 NULL, /* clear */
885 NULL, /* tp_richcompare */
886 0, /* tp_weaklistoffset */
887 NULL, /* tp_iter */
888 NULL, /* tp_iternext */
889 crypto_X509_methods, /* tp_methods */
890 NULL, /* tp_members */
891 NULL, /* tp_getset */
892 NULL, /* tp_base */
893 NULL, /* tp_dict */
894 NULL, /* tp_descr_get */
895 NULL, /* tp_descr_set */
896 0, /* tp_dictoffset */
897 NULL, /* tp_init */
898 NULL, /* tp_alloc */
899 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500900};
901
902/*
903 * Initialize the X509 part of the crypto sub module
904 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400905 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500906 * Returns: None
907 */
908int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400909init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500910{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400911 if (PyType_Ready(&crypto_X509_Type) < 0) {
912 return 0;
913 }
914
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500915 /* PyModule_AddObject steals a reference.
Jean-Paul Calderone86ad7112010-05-11 16:08:45 -0400916 */
917 Py_INCREF((PyObject *)&crypto_X509_Type);
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400918 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
919 return 0;
920 }
921
Jean-Paul Calderoned07d57d2011-03-12 22:35:24 -0500922 Py_INCREF((PyObject *)&crypto_X509_Type);
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400923 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
924 return 0;
925 }
926
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500927 return 1;
928}
929