blob: 4329ddbceec7b0b211fc4b736386499cb8c741aa [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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090026: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090041: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090062: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090088: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900179: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900204:param issuer: The issuer name\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900205:type issuer: :py:class:`X509Name`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900206: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900231: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900256:param subject: The subject name\n\
Jonathan Ballet6a0b57b2011-07-16 14:22:14 +0900257:type subject: :py:class:`X509Name`\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900258: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900283: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900312: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900361: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900367: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900381: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900387: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\
Jonathan Ballet6a0b57b2011-07-16 14:22:14 +0900436: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\
Jonathan Ballet6a0b57b2011-07-16 14:22:14 +0900441\n\
442 or None if there is no value set.\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400443";
444
445static PyObject*
446crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
447{
448 /*
449 * X509_get_notBefore returns a borrowed reference.
450 */
451 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500452 ":get_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400453}
454
455
456static char crypto_X509_get_notAfter_doc[] = "\n\
457Retrieve the time stamp for when the certificate stops being valid\n\
458\n\
Jonathan Ballet6a0b57b2011-07-16 14:22:14 +0900459:return: A string giving the timestamp, in the format::\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400460\n\
461 YYYYMMDDhhmmssZ\n\
462 YYYYMMDDhhmmss+hhmm\n\
463 YYYYMMDDhhmmss-hhmm\n\
Jonathan Ballet6a0b57b2011-07-16 14:22:14 +0900464\n\
465 or None if there is no value set.\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400466";
467
468static PyObject*
469crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
470{
471 /*
472 * X509_get_notAfter returns a borrowed reference.
473 */
474 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500475 ":get_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400476}
477
478
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500479static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400480Change the timestamp for when the certificate starts being valid to the current\n\
481time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500482\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900483:param amount: The number of seconds by which to adjust the starting validity\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400484 time.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900485:return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500486";
487
488static PyObject *
489crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
490{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400491 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400493 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500494 return NULL;
495
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400496 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500497
498 Py_INCREF(Py_None);
499 return Py_None;
500}
501
502static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
503Adjust the time stamp for when the certificate stops being valid\n\
504\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900505:param amount: The number of seconds by which to adjust the ending validity\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400506 time.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900507:return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500508";
509
510static PyObject *
511crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
512{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400513 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500514
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400515 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500516 return NULL;
517
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400518 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500519
520 Py_INCREF(Py_None);
521 return Py_None;
522}
523
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400524
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400525static char crypto_X509_get_signature_algorithm_doc[] = "\n\
526Retrieve the signature algorithm used in the certificate\n\
527\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900528:return: A byte string giving the name of the signature algorithm used in\n\
Jean-Paul Calderone4a3a7c12011-05-19 17:46:40 -0400529 the certificate.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900530:raise ValueError: If the signature algorithm is undefined.\n\
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400531";
532
533static PyObject *
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400534crypto_X509_get_signature_algorithm(crypto_X509Obj *self, PyObject *args) {
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400535 ASN1_OBJECT *alg;
536 int nid;
537
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400538 if (!PyArg_ParseTuple(args, ":get_signature_algorithm")) {
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400539 return NULL;
Jean-Paul Calderoneff404b82011-05-17 15:49:10 -0400540 }
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400541
542 alg = self->x509->cert_info->signature->algorithm;
543 nid = OBJ_obj2nid(alg);
Jean-Paul Calderone2755fa52011-05-18 19:42:10 -0400544 if (nid == NID_undef) {
545 PyErr_SetString(PyExc_ValueError, "Undefined signature algorithm");
546 return NULL;
547 }
Jean-Paul Calderone489969f2011-05-18 20:53:07 -0400548 return PyBytes_FromString(OBJ_nid2ln(nid));
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400549}
550
551
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500552static char crypto_X509_sign_doc[] = "\n\
553Sign the certificate using the supplied key and digest\n\
554\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900555:param pkey: The key to sign with\n\
556:param digest: The message digest to use\n\
557:return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500558";
559
560static PyObject *
561crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
562{
563 crypto_PKeyObj *pkey;
564 char *digest_name;
565 const EVP_MD *digest;
566
567 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
568 &digest_name))
569 return NULL;
570
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400571 if (pkey->only_public) {
572 PyErr_SetString(PyExc_ValueError, "Key has only public part");
573 return NULL;
574 }
575
576 if (!pkey->initialized) {
577 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
578 return NULL;
579 }
580
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500581 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
582 {
583 PyErr_SetString(PyExc_ValueError, "No such digest method");
584 return NULL;
585 }
586
587 if (!X509_sign(self->x509, pkey->pkey, digest))
588 {
Rick Deand369c932009-07-08 11:48:33 -0500589 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500590 return NULL;
591 }
592
593 Py_INCREF(Py_None);
594 return Py_None;
595}
596
597static char crypto_X509_has_expired_doc[] = "\n\
598Check whether the certificate has expired.\n\
599\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900600:return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500601";
602
603static PyObject *
604crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
605{
606 time_t tnow;
607
608 if (!PyArg_ParseTuple(args, ":has_expired"))
609 return NULL;
610
611 tnow = time(NULL);
612 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400613 return PyLong_FromLong(1L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500614 else
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400615 return PyLong_FromLong(0L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500616}
617
618static char crypto_X509_subject_name_hash_doc[] = "\n\
619Return the hash of the X509 subject.\n\
620\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900621:return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500622";
623
624static PyObject *
625crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
626{
627 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
628 return NULL;
629
Jean-Paul Calderone37306a62010-08-28 15:09:24 -0400630 return PyLong_FromLongLong(X509_subject_name_hash(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500631}
632
633static char crypto_X509_digest_doc[] = "\n\
634Return the digest of the X509 object.\n\
635\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900636:return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500637";
638
639static PyObject *
640crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
641{
642 unsigned char fp[EVP_MAX_MD_SIZE];
643 char *tmp;
644 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500645 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500646 PyObject *ret;
647 const EVP_MD *digest;
648
649 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
650 return NULL;
651
652 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
653 {
654 PyErr_SetString(PyExc_ValueError, "No such digest method");
655 return NULL;
656 }
657
658 if (!X509_digest(self->x509,digest,fp,&len))
659 {
Rick Deand369c932009-07-08 11:48:33 -0500660 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500661 }
662 tmp = malloc(3*len+1);
663 memset(tmp, 0, 3*len+1);
664 for (i = 0; i < len; i++) {
665 sprintf(tmp+i*3,"%02X:",fp[i]);
666 }
667 tmp[3*len-1] = 0;
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400668 ret = PyBytes_FromStringAndSize(tmp,3*len-1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500669 free(tmp);
670 return ret;
671}
672
673
674static char crypto_X509_add_extensions_doc[] = "\n\
675Add extensions to the certificate.\n\
676\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900677:param extensions: a sequence of X509Extension objects\n\
678:return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500679";
680
681static PyObject *
682crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
683{
684 PyObject *extensions, *seq;
685 crypto_X509ExtensionObj *ext;
686 int nr_of_extensions, i;
687
688 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
689 return NULL;
690
691 seq = PySequence_Fast(extensions, "Expected a sequence");
692 if (seq == NULL)
693 return NULL;
694
695 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
696
697 for (i = 0; i < nr_of_extensions; i++)
698 {
699 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
700 if (!crypto_X509Extension_Check(ext))
701 {
702 Py_DECREF(seq);
703 PyErr_SetString(PyExc_ValueError,
704 "One of the elements is not an X509Extension");
705 return NULL;
706 }
707 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
708 {
709 Py_DECREF(seq);
Rick Deand369c932009-07-08 11:48:33 -0500710 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500711 return NULL;
712 }
713 }
714
715 Py_INCREF(Py_None);
716 return Py_None;
717}
718
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200719static char crypto_X509_get_extension_count_doc[] = "\n\
720Get the number of extensions on the certificate.\n\
721\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900722:return: Number of extensions as a Python integer\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200723";
724
725static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400726crypto_X509_get_extension_count(crypto_X509Obj *self, PyObject *args) {
727 if (!PyArg_ParseTuple(args, ":get_extension_count")) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200728 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400729 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200730
Jean-Paul Calderone48659612011-04-06 17:22:15 -0400731 return PyLong_FromLong((long)X509_get_ext_count(self->x509));
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200732}
733
734static char crypto_X509_get_extension_doc[] = "\n\
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400735Get a specific extension of the certificate by index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200736\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900737:param index: The index of the extension to retrieve.\n\
738:return: The X509Extension object at the specified index.\n\
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200739";
740
741static PyObject *
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400742crypto_X509_get_extension(crypto_X509Obj *self, PyObject *args) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200743 crypto_X509ExtensionObj *extobj;
744 int loc;
745 X509_EXTENSION *ext;
746
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400747 if (!PyArg_ParseTuple(args, "i:get_extension", &loc)) {
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200748 return NULL;
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400749 }
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200750
751 /* will return NULL if loc is outside the range of extensions,
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400752 not registered as an error*/
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200753 ext = X509_get_ext(self->x509, loc);
754 if (!ext) {
Jean-Paul Calderone83a593d2011-04-01 17:45:07 -0400755 PyErr_SetString(PyExc_IndexError, "extension index out of bounds");
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200756 return NULL; /* Should be reported as an IndexError ? */
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200757 }
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400758
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200759 extobj = PyObject_New(crypto_X509ExtensionObj, &crypto_X509Extension_Type);
760 extobj->x509_extension = X509_EXTENSION_dup(ext);
Jean-Paul Calderone24ebc4f2011-04-01 17:07:24 -0400761
Jean-Paul Calderonef7b3ee62011-04-01 17:36:24 -0400762 return (PyObject*)extobj;
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200763}
764
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500765/*
766 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
767 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
768 * for convenience
769 */
770#define ADD_METHOD(name) \
771 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
772static PyMethodDef crypto_X509_methods[] =
773{
774 ADD_METHOD(get_version),
775 ADD_METHOD(set_version),
776 ADD_METHOD(get_serial_number),
777 ADD_METHOD(set_serial_number),
778 ADD_METHOD(get_issuer),
779 ADD_METHOD(set_issuer),
780 ADD_METHOD(get_subject),
781 ADD_METHOD(set_subject),
782 ADD_METHOD(get_pubkey),
783 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400784 ADD_METHOD(get_notBefore),
785 ADD_METHOD(set_notBefore),
786 ADD_METHOD(get_notAfter),
787 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500788 ADD_METHOD(gmtime_adj_notBefore),
789 ADD_METHOD(gmtime_adj_notAfter),
Jean-Paul Calderone5d190522011-05-17 15:43:51 -0400790 ADD_METHOD(get_signature_algorithm),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500791 ADD_METHOD(sign),
792 ADD_METHOD(has_expired),
793 ADD_METHOD(subject_name_hash),
794 ADD_METHOD(digest),
795 ADD_METHOD(add_extensions),
Roland Hedberg7e4930e2008-04-22 22:58:50 +0200796 ADD_METHOD(get_extension),
797 ADD_METHOD(get_extension_count),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500798 { NULL, NULL }
799};
800#undef ADD_METHOD
801
802
803/*
804 * Constructor for X509 objects, never called by Python code directly
805 *
806 * Arguments: cert - A "real" X509 certificate object
807 * dealloc - Boolean value to specify whether the destructor should
808 * free the "real" X509 object
809 * Returns: The newly created X509 object
810 */
811crypto_X509Obj *
812crypto_X509_New(X509 *cert, int dealloc)
813{
814 crypto_X509Obj *self;
815
816 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
817
818 if (self == NULL)
819 return NULL;
820
821 self->x509 = cert;
822 self->dealloc = dealloc;
823
824 return self;
825}
826
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400827
828static char crypto_X509_doc[] = "\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900829A class representing X.509 certificates.\n\
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400830\n\
831Create a new X509 object.\n\
832\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900833:returns: The :class:`X509` object\n\
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400834";
835
836static PyObject *
837crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
838{
839 if (!PyArg_ParseTuple(args, ":X509")) {
840 return NULL;
841 }
842
843 return (PyObject *)crypto_X509_New(X509_new(), 1);
844}
845
846
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500847/*
848 * Deallocate the memory used by the X509 object
849 *
850 * Arguments: self - The X509 object
851 * Returns: None
852 */
853static void
854crypto_X509_dealloc(crypto_X509Obj *self)
855{
856 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
857 if (self->dealloc)
858 X509_free(self->x509);
859
860 PyObject_Del(self);
861}
862
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500863PyTypeObject crypto_X509_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400864 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500865 "X509",
866 sizeof(crypto_X509Obj),
867 0,
868 (destructor)crypto_X509_dealloc,
869 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400870 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400871 NULL, /* setattr */
872 NULL, /* compare */
873 NULL, /* repr */
874 NULL, /* as_number */
875 NULL, /* as_sequence */
876 NULL, /* as_mapping */
877 NULL, /* hash */
878 NULL, /* call */
879 NULL, /* str */
880 NULL, /* getattro */
881 NULL, /* setattro */
882 NULL, /* as_buffer */
883 Py_TPFLAGS_DEFAULT,
884 crypto_X509_doc, /* doc */
885 NULL, /* traverse */
886 NULL, /* clear */
887 NULL, /* tp_richcompare */
888 0, /* tp_weaklistoffset */
889 NULL, /* tp_iter */
890 NULL, /* tp_iternext */
891 crypto_X509_methods, /* tp_methods */
892 NULL, /* tp_members */
893 NULL, /* tp_getset */
894 NULL, /* tp_base */
895 NULL, /* tp_dict */
896 NULL, /* tp_descr_get */
897 NULL, /* tp_descr_set */
898 0, /* tp_dictoffset */
899 NULL, /* tp_init */
900 NULL, /* tp_alloc */
901 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500902};
903
904/*
905 * Initialize the X509 part of the crypto sub module
906 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400907 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500908 * Returns: None
909 */
910int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400911init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500912{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400913 if (PyType_Ready(&crypto_X509_Type) < 0) {
914 return 0;
915 }
916
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500917 /* PyModule_AddObject steals a reference.
Jean-Paul Calderone86ad7112010-05-11 16:08:45 -0400918 */
919 Py_INCREF((PyObject *)&crypto_X509_Type);
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400920 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
921 return 0;
922 }
923
Jean-Paul Calderoned07d57d2011-03-12 22:35:24 -0500924 Py_INCREF((PyObject *)&crypto_X509_Type);
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400925 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
926 return 0;
927 }
928
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500929 return 1;
930}
931