blob: 2f12437a24a615c3517978c9f89d6f6f8d250ff7 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * x509.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04005 * Copyright (C) Jean-Paul Calderone 2008, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 *
7 * Certificate (X.509) handling code, mostly thin wrappers around OpenSSL.
8 * See the file RATIONALE for a short explanation of why this module was written.
9 *
10 * Reviewed 2001-07-23
11 */
12#include <Python.h>
13#define crypto_MODULE
14#include "crypto.h"
15
Jean-Paul Calderone525ef802008-03-09 20:39:42 -040016/*
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017 * X.509 is a standard for digital certificates. See e.g. the OpenSSL homepage
18 * http://www.openssl.org/ for more information
19 */
20
21static char crypto_X509_get_version_doc[] = "\n\
22Return version number of the certificate\n\
23\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040024@return: Version number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050025";
26
27static PyObject *
28crypto_X509_get_version(crypto_X509Obj *self, PyObject *args)
29{
30 if (!PyArg_ParseTuple(args, ":get_version"))
31 return NULL;
32
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -040033 return PyLong_FromLong((long)X509_get_version(self->x509));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050034}
35
36static char crypto_X509_set_version_doc[] = "\n\
37Set version number of the certificate\n\
38\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040039@param version: The version number\n\
40@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050041";
42
43static PyObject *
44crypto_X509_set_version(crypto_X509Obj *self, PyObject *args)
45{
46 int version;
47
48 if (!PyArg_ParseTuple(args, "i:set_version", &version))
49 return NULL;
50
51 X509_set_version(self->x509, version);
52
53 Py_INCREF(Py_None);
54 return Py_None;
55}
56
57static char crypto_X509_get_serial_number_doc[] = "\n\
58Return serial number of the certificate\n\
59\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040060@return: Serial number as a Python integer\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061";
62
63static PyObject *
64crypto_X509_get_serial_number(crypto_X509Obj *self, PyObject *args)
65{
66 ASN1_INTEGER *asn1_i;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050067 BIGNUM *bignum;
68 char *hex;
69 PyObject *res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050070
71 if (!PyArg_ParseTuple(args, ":get_serial_number"))
72 return NULL;
73
74 asn1_i = X509_get_serialNumber(self->x509);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050075 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
76 hex = BN_bn2hex(bignum);
77 res = PyLong_FromString(hex, NULL, 16);
78 BN_free(bignum);
79 free(hex);
80 return res;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050081}
82
83static char crypto_X509_set_serial_number_doc[] = "\n\
84Set serial number of the certificate\n\
85\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040086@param serial: The serial number\n\
87@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050088";
89
90static PyObject *
91crypto_X509_set_serial_number(crypto_X509Obj *self, PyObject *args)
92{
Jean-Paul Calderone78381d22008-03-06 23:35:22 -050093 long small_serial;
94 PyObject *serial = NULL;
95 PyObject *hex = NULL;
96 PyObject *format = NULL;
97 PyObject *format_args = NULL;
98 ASN1_INTEGER *asn1_i = NULL;
99 BIGNUM *bignum = NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500100
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500101 if (!PyArg_ParseTuple(args, "O:set_serial_number", &serial)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500102 return NULL;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500103 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400105 if (!PyLong_Check(serial)) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500106 PyErr_SetString(
107 PyExc_TypeError, "serial number must be integer");
108 goto err;
109 }
110
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400111 if ((hex = PyNumber_ToBase(serial, 16)) == NULL) {
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500112 goto err;
113 }
114
115 /**
116 * BN_hex2bn stores the result in &bignum. Unless it doesn't feel like
117 * it. If bignum is still NULL after this call, then the return value
118 * is actually the result. I hope. -exarkun
119 */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400120 small_serial = BN_hex2bn(&bignum, PyBytes_AsString(hex));
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500121
122 Py_DECREF(format_args);
123 format_args = NULL;
124 Py_DECREF(format);
125 format = NULL;
126 Py_DECREF(hex);
127 hex = NULL;
128
129 if (bignum == NULL) {
130 if (ASN1_INTEGER_set(X509_get_serialNumber(self->x509), small_serial)) {
Rick Deand369c932009-07-08 11:48:33 -0500131 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500132 goto err;
133 }
134 } else {
135 asn1_i = BN_to_ASN1_INTEGER(bignum, NULL);
136 BN_free(bignum);
137 bignum = NULL;
138 if (asn1_i == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500139 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500140 goto err;
141 }
142 if (!X509_set_serialNumber(self->x509, asn1_i)) {
Rick Deand369c932009-07-08 11:48:33 -0500143 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500144 goto err;
145 }
146 ASN1_INTEGER_free(asn1_i);
147 asn1_i = NULL;
148 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500149
150 Py_INCREF(Py_None);
151 return Py_None;
Jean-Paul Calderone78381d22008-03-06 23:35:22 -0500152
153 err:
154 if (format_args) {
155 Py_DECREF(format_args);
156 }
157 if (format) {
158 Py_DECREF(format);
159 }
160 if (hex) {
161 Py_DECREF(hex);
162 }
163 if (bignum) {
164 BN_free(bignum);
165 }
166 if (asn1_i) {
167 ASN1_INTEGER_free(asn1_i);
168 }
169 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500170}
171
172static char crypto_X509_get_issuer_doc[] = "\n\
173Create an X509Name object for the issuer of the certificate\n\
174\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400175@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500176";
177
178static PyObject *
179crypto_X509_get_issuer(crypto_X509Obj *self, PyObject *args)
180{
181 crypto_X509NameObj *pyname;
182 X509_NAME *name;
183
184 if (!PyArg_ParseTuple(args, ":get_issuer"))
185 return NULL;
186
187 name = X509_get_issuer_name(self->x509);
188 pyname = crypto_X509Name_New(name, 0);
189 if (pyname != NULL)
190 {
191 pyname->parent_cert = (PyObject *)self;
192 Py_INCREF(self);
193 }
194 return (PyObject *)pyname;
195}
196
197static char crypto_X509_set_issuer_doc[] = "\n\
198Set the issuer of the certificate\n\
199\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400200@param issuer: The issuer name\n\
201@type issuer: L{X509Name}\n\
202@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500203";
204
205static PyObject *
206crypto_X509_set_issuer(crypto_X509Obj *self, PyObject *args)
207{
208 crypto_X509NameObj *issuer;
209
210 if (!PyArg_ParseTuple(args, "O!:set_issuer", &crypto_X509Name_Type,
211 &issuer))
212 return NULL;
213
214 if (!X509_set_issuer_name(self->x509, issuer->x509_name))
215 {
Rick Deand369c932009-07-08 11:48:33 -0500216 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500217 return NULL;
218 }
219
220 Py_INCREF(Py_None);
221 return Py_None;
222}
223
224static char crypto_X509_get_subject_doc[] = "\n\
225Create an X509Name object for the subject of the certificate\n\
226\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400227@return: An X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500228";
229
230static PyObject *
231crypto_X509_get_subject(crypto_X509Obj *self, PyObject *args)
232{
233 crypto_X509NameObj *pyname;
234 X509_NAME *name;
235
236 if (!PyArg_ParseTuple(args, ":get_subject"))
237 return NULL;
238
239 name = X509_get_subject_name(self->x509);
240 pyname = crypto_X509Name_New(name, 0);
241 if (pyname != NULL)
242 {
243 pyname->parent_cert = (PyObject *)self;
244 Py_INCREF(self);
245 }
246 return (PyObject *)pyname;
247}
248
249static char crypto_X509_set_subject_doc[] = "\n\
250Set the subject of the certificate\n\
251\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400252@param subject: The subject name\n\
253@type subject: L{X509Name}\n\
254@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500255";
256
257static PyObject *
258crypto_X509_set_subject(crypto_X509Obj *self, PyObject *args)
259{
260 crypto_X509NameObj *subject;
261
262 if (!PyArg_ParseTuple(args, "O!:set_subject", &crypto_X509Name_Type,
263 &subject))
264 return NULL;
265
266 if (!X509_set_subject_name(self->x509, subject->x509_name))
267 {
Rick Deand369c932009-07-08 11:48:33 -0500268 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500269 return NULL;
270 }
271
272 Py_INCREF(Py_None);
273 return Py_None;
274}
275
276static char crypto_X509_get_pubkey_doc[] = "\n\
277Get the public key of the certificate\n\
278\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400279@return: The public key\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500280";
281
282static PyObject *
283crypto_X509_get_pubkey(crypto_X509Obj *self, PyObject *args)
284{
285 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
286 EVP_PKEY *pkey;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400287 crypto_PKeyObj *py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500288
289 if (!PyArg_ParseTuple(args, ":get_pubkey"))
290 return NULL;
291
292 if ((pkey = X509_get_pubkey(self->x509)) == NULL)
293 {
Rick Deand369c932009-07-08 11:48:33 -0500294 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500295 return NULL;
296 }
297
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400298 py_pkey = crypto_PKey_New(pkey, 1);
299 if (py_pkey != NULL) {
300 py_pkey->only_public = 1;
301 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400302 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500303}
304
305static char crypto_X509_set_pubkey_doc[] = "\n\
306Set the public key of the certificate\n\
307\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400308@param pkey: The public key\n\
309@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500310";
311
312static PyObject *
313crypto_X509_set_pubkey(crypto_X509Obj *self, PyObject *args)
314{
315 crypto_PKeyObj *pkey;
316
317 if (!PyArg_ParseTuple(args, "O!:set_pubkey", &crypto_PKey_Type, &pkey))
318 return NULL;
319
320 if (!X509_set_pubkey(self->x509, pkey->pkey))
321 {
Rick Deand369c932009-07-08 11:48:33 -0500322 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500323 return NULL;
324 }
325
326 Py_INCREF(Py_None);
327 return Py_None;
328}
329
Rick Dean536ba022009-07-24 23:57:27 -0500330PyObject*
331_set_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400332{
333 char *when;
334
335 if (!PyArg_ParseTuple(args, format, &when))
336 return NULL;
337
338 if (ASN1_GENERALIZEDTIME_set_string(timestamp, when) == 0) {
339 ASN1_GENERALIZEDTIME dummy;
340 dummy.type = V_ASN1_GENERALIZEDTIME;
341 dummy.length = strlen(when);
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500342 dummy.data = (unsigned char *)when;
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400343 if (!ASN1_GENERALIZEDTIME_check(&dummy)) {
344 PyErr_SetString(PyExc_ValueError, "Invalid string");
345 } else {
346 PyErr_SetString(PyExc_RuntimeError, "Unknown ASN1_GENERALIZEDTIME_set_string failure");
347 }
348 return NULL;
349 }
350 Py_INCREF(Py_None);
351 return Py_None;
352}
353
354static char crypto_X509_set_notBefore_doc[] = "\n\
355Set the time stamp for when the certificate starts being valid\n\
356\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400357@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400358\n\
359 YYYYMMDDhhmmssZ\n\
360 YYYYMMDDhhmmss+hhmm\n\
361 YYYYMMDDhhmmss-hhmm\n\
362\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400363@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400364";
365
366static PyObject*
367crypto_X509_set_notBefore(crypto_X509Obj *self, PyObject *args)
368{
369 return _set_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500370 "s:set_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400371}
372
373static char crypto_X509_set_notAfter_doc[] = "\n\
374Set the time stamp for when the certificate stops being valid\n\
375\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400376@param when: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400377\n\
378 YYYYMMDDhhmmssZ\n\
379 YYYYMMDDhhmmss+hhmm\n\
380 YYYYMMDDhhmmss-hhmm\n\
381\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400382@return: None\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400383";
384
385static PyObject*
386crypto_X509_set_notAfter(crypto_X509Obj *self, PyObject *args)
387{
388 return _set_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500389 "s:set_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400390}
391
Rick Dean536ba022009-07-24 23:57:27 -0500392PyObject*
393_get_asn1_time(char *format, ASN1_TIME* timestamp, PyObject *args)
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400394{
395 ASN1_GENERALIZEDTIME *gt_timestamp = NULL;
396 PyObject *py_timestamp = NULL;
397
398 if (!PyArg_ParseTuple(args, format)) {
399 return NULL;
400 }
401
402 /*
403 * http://www.columbia.edu/~ariel/ssleay/asn1-time.html
404 */
405 /*
406 * There must be a way to do this without touching timestamp->data
407 * directly. -exarkun
408 */
Jean-Paul Calderonee0615b52008-03-09 21:44:46 -0400409 if (timestamp->length == 0) {
410 Py_INCREF(Py_None);
411 return Py_None;
412 } else if (timestamp->type == V_ASN1_GENERALIZEDTIME) {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400413 return PyBytes_FromString((char *)timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400414 } else {
415 ASN1_TIME_to_generalizedtime(timestamp, &gt_timestamp);
Jean-Paul Calderone38a646d2008-03-25 15:16:18 -0400416 if (gt_timestamp == NULL) {
Rick Deand369c932009-07-08 11:48:33 -0500417 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400418 return NULL;
419 } else {
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400420 py_timestamp = PyBytes_FromString((char *)gt_timestamp->data);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400421 ASN1_GENERALIZEDTIME_free(gt_timestamp);
422 return py_timestamp;
423 }
424 }
425}
426
427static char crypto_X509_get_notBefore_doc[] = "\n\
428Retrieve the time stamp for when the certificate starts being valid\n\
429\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400430@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400431\n\
432 YYYYMMDDhhmmssZ\n\
433 YYYYMMDDhhmmss+hhmm\n\
434 YYYYMMDDhhmmss-hhmm\n\
435 or None if there is no value set.\n\
436";
437
438static PyObject*
439crypto_X509_get_notBefore(crypto_X509Obj *self, PyObject *args)
440{
441 /*
442 * X509_get_notBefore returns a borrowed reference.
443 */
444 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500445 ":get_notBefore", X509_get_notBefore(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400446}
447
448
449static char crypto_X509_get_notAfter_doc[] = "\n\
450Retrieve the time stamp for when the certificate stops being valid\n\
451\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400452@return: A string giving the timestamp, in the format:\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400453\n\
454 YYYYMMDDhhmmssZ\n\
455 YYYYMMDDhhmmss+hhmm\n\
456 YYYYMMDDhhmmss-hhmm\n\
457 or None if there is no value set.\n\
458";
459
460static PyObject*
461crypto_X509_get_notAfter(crypto_X509Obj *self, PyObject *args)
462{
463 /*
464 * X509_get_notAfter returns a borrowed reference.
465 */
466 return _get_asn1_time(
Rick Dean536ba022009-07-24 23:57:27 -0500467 ":get_notAfter", X509_get_notAfter(self->x509), args);
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400468}
469
470
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500471static char crypto_X509_gmtime_adj_notBefore_doc[] = "\n\
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400472Change the timestamp for when the certificate starts being valid to the current\n\
473time plus an offset.\n \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500474\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400475@param amount: The number of seconds by which to adjust the starting validity\n\
476 time.\n\
477@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500478";
479
480static PyObject *
481crypto_X509_gmtime_adj_notBefore(crypto_X509Obj *self, PyObject *args)
482{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400483 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500484
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400485 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notBefore", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500486 return NULL;
487
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400488 X509_gmtime_adj(X509_get_notBefore(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500489
490 Py_INCREF(Py_None);
491 return Py_None;
492}
493
494static char crypto_X509_gmtime_adj_notAfter_doc[] = "\n\
495Adjust the time stamp for when the certificate stops being valid\n\
496\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400497@param amount: The number of seconds by which to adjust the ending validity\n\
498 time.\n\
499@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500500";
501
502static PyObject *
503crypto_X509_gmtime_adj_notAfter(crypto_X509Obj *self, PyObject *args)
504{
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400505 long amount;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500506
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400507 if (!PyArg_ParseTuple(args, "l:gmtime_adj_notAfter", &amount))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500508 return NULL;
509
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400510 X509_gmtime_adj(X509_get_notAfter(self->x509), amount);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500511
512 Py_INCREF(Py_None);
513 return Py_None;
514}
515
516static char crypto_X509_sign_doc[] = "\n\
517Sign the certificate using the supplied key and digest\n\
518\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400519@param pkey: The key to sign with\n\
520@param digest: The message digest to use\n\
521@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500522";
523
524static PyObject *
525crypto_X509_sign(crypto_X509Obj *self, PyObject *args)
526{
527 crypto_PKeyObj *pkey;
528 char *digest_name;
529 const EVP_MD *digest;
530
531 if (!PyArg_ParseTuple(args, "O!s:sign", &crypto_PKey_Type, &pkey,
532 &digest_name))
533 return NULL;
534
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400535 if (pkey->only_public) {
536 PyErr_SetString(PyExc_ValueError, "Key has only public part");
537 return NULL;
538 }
539
540 if (!pkey->initialized) {
541 PyErr_SetString(PyExc_ValueError, "Key is uninitialized");
542 return NULL;
543 }
544
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500545 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
546 {
547 PyErr_SetString(PyExc_ValueError, "No such digest method");
548 return NULL;
549 }
550
551 if (!X509_sign(self->x509, pkey->pkey, digest))
552 {
Rick Deand369c932009-07-08 11:48:33 -0500553 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500554 return NULL;
555 }
556
557 Py_INCREF(Py_None);
558 return Py_None;
559}
560
561static char crypto_X509_has_expired_doc[] = "\n\
562Check whether the certificate has expired.\n\
563\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400564@return: True if the certificate has expired, false otherwise\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500565";
566
567static PyObject *
568crypto_X509_has_expired(crypto_X509Obj *self, PyObject *args)
569{
570 time_t tnow;
571
572 if (!PyArg_ParseTuple(args, ":has_expired"))
573 return NULL;
574
575 tnow = time(NULL);
576 if (ASN1_UTCTIME_cmp_time_t(X509_get_notAfter(self->x509), tnow) < 0)
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400577 return PyLong_FromLong(1L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500578 else
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400579 return PyLong_FromLong(0L);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500580}
581
582static char crypto_X509_subject_name_hash_doc[] = "\n\
583Return the hash of the X509 subject.\n\
584\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400585@return: The hash of the subject\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500586";
587
588static PyObject *
589crypto_X509_subject_name_hash(crypto_X509Obj *self, PyObject *args)
590{
591 if (!PyArg_ParseTuple(args, ":subject_name_hash"))
592 return NULL;
593
594 return PyLong_FromLong(X509_subject_name_hash(self->x509));
595}
596
597static char crypto_X509_digest_doc[] = "\n\
598Return the digest of the X509 object.\n\
599\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400600@return: The digest of the object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500601";
602
603static PyObject *
604crypto_X509_digest(crypto_X509Obj *self, PyObject *args)
605{
606 unsigned char fp[EVP_MAX_MD_SIZE];
607 char *tmp;
608 char *digest_name;
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500609 unsigned int len,i;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500610 PyObject *ret;
611 const EVP_MD *digest;
612
613 if (!PyArg_ParseTuple(args, "s:digest", &digest_name))
614 return NULL;
615
616 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
617 {
618 PyErr_SetString(PyExc_ValueError, "No such digest method");
619 return NULL;
620 }
621
622 if (!X509_digest(self->x509,digest,fp,&len))
623 {
Rick Deand369c932009-07-08 11:48:33 -0500624 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500625 }
626 tmp = malloc(3*len+1);
627 memset(tmp, 0, 3*len+1);
628 for (i = 0; i < len; i++) {
629 sprintf(tmp+i*3,"%02X:",fp[i]);
630 }
631 tmp[3*len-1] = 0;
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400632 ret = PyBytes_FromStringAndSize(tmp,3*len-1);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500633 free(tmp);
634 return ret;
635}
636
637
638static char crypto_X509_add_extensions_doc[] = "\n\
639Add extensions to the certificate.\n\
640\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400641@param extensions: a sequence of X509Extension objects\n\
642@return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500643";
644
645static PyObject *
646crypto_X509_add_extensions(crypto_X509Obj *self, PyObject *args)
647{
648 PyObject *extensions, *seq;
649 crypto_X509ExtensionObj *ext;
650 int nr_of_extensions, i;
651
652 if (!PyArg_ParseTuple(args, "O:add_extensions", &extensions))
653 return NULL;
654
655 seq = PySequence_Fast(extensions, "Expected a sequence");
656 if (seq == NULL)
657 return NULL;
658
659 nr_of_extensions = PySequence_Fast_GET_SIZE(seq);
660
661 for (i = 0; i < nr_of_extensions; i++)
662 {
663 ext = (crypto_X509ExtensionObj *)PySequence_Fast_GET_ITEM(seq, i);
664 if (!crypto_X509Extension_Check(ext))
665 {
666 Py_DECREF(seq);
667 PyErr_SetString(PyExc_ValueError,
668 "One of the elements is not an X509Extension");
669 return NULL;
670 }
671 if (!X509_add_ext(self->x509, ext->x509_extension, -1))
672 {
673 Py_DECREF(seq);
Rick Deand369c932009-07-08 11:48:33 -0500674 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500675 return NULL;
676 }
677 }
678
679 Py_INCREF(Py_None);
680 return Py_None;
681}
682
683/*
684 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
685 * { 'name', (PyCFunction)crypto_X509_name, METH_VARARGS }
686 * for convenience
687 */
688#define ADD_METHOD(name) \
689 { #name, (PyCFunction)crypto_X509_##name, METH_VARARGS, crypto_X509_##name##_doc }
690static PyMethodDef crypto_X509_methods[] =
691{
692 ADD_METHOD(get_version),
693 ADD_METHOD(set_version),
694 ADD_METHOD(get_serial_number),
695 ADD_METHOD(set_serial_number),
696 ADD_METHOD(get_issuer),
697 ADD_METHOD(set_issuer),
698 ADD_METHOD(get_subject),
699 ADD_METHOD(set_subject),
700 ADD_METHOD(get_pubkey),
701 ADD_METHOD(set_pubkey),
Jean-Paul Calderone525ef802008-03-09 20:39:42 -0400702 ADD_METHOD(get_notBefore),
703 ADD_METHOD(set_notBefore),
704 ADD_METHOD(get_notAfter),
705 ADD_METHOD(set_notAfter),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500706 ADD_METHOD(gmtime_adj_notBefore),
707 ADD_METHOD(gmtime_adj_notAfter),
708 ADD_METHOD(sign),
709 ADD_METHOD(has_expired),
710 ADD_METHOD(subject_name_hash),
711 ADD_METHOD(digest),
712 ADD_METHOD(add_extensions),
713 { NULL, NULL }
714};
715#undef ADD_METHOD
716
717
718/*
719 * Constructor for X509 objects, never called by Python code directly
720 *
721 * Arguments: cert - A "real" X509 certificate object
722 * dealloc - Boolean value to specify whether the destructor should
723 * free the "real" X509 object
724 * Returns: The newly created X509 object
725 */
726crypto_X509Obj *
727crypto_X509_New(X509 *cert, int dealloc)
728{
729 crypto_X509Obj *self;
730
731 self = PyObject_New(crypto_X509Obj, &crypto_X509_Type);
732
733 if (self == NULL)
734 return NULL;
735
736 self->x509 = cert;
737 self->dealloc = dealloc;
738
739 return self;
740}
741
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400742
743static char crypto_X509_doc[] = "\n\
744X509() -> X509 instance\n\
745\n\
746Create a new X509 object.\n\
747\n\
748@returns: The X509 object\n\
749";
750
751static PyObject *
752crypto_X509_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
753{
754 if (!PyArg_ParseTuple(args, ":X509")) {
755 return NULL;
756 }
757
758 return (PyObject *)crypto_X509_New(X509_new(), 1);
759}
760
761
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500762/*
763 * Deallocate the memory used by the X509 object
764 *
765 * Arguments: self - The X509 object
766 * Returns: None
767 */
768static void
769crypto_X509_dealloc(crypto_X509Obj *self)
770{
771 /* Sometimes we don't have to dealloc the "real" X509 pointer ourselves */
772 if (self->dealloc)
773 X509_free(self->x509);
774
775 PyObject_Del(self);
776}
777
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500778PyTypeObject crypto_X509_Type = {
779 PyObject_HEAD_INIT(NULL)
780 0,
781 "X509",
782 sizeof(crypto_X509Obj),
783 0,
784 (destructor)crypto_X509_dealloc,
785 NULL, /* print */
Jean-Paul Calderoneae479ad2010-08-10 20:04:28 -0400786 NULL, /* getattr */
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400787 NULL, /* setattr */
788 NULL, /* compare */
789 NULL, /* repr */
790 NULL, /* as_number */
791 NULL, /* as_sequence */
792 NULL, /* as_mapping */
793 NULL, /* hash */
794 NULL, /* call */
795 NULL, /* str */
796 NULL, /* getattro */
797 NULL, /* setattro */
798 NULL, /* as_buffer */
799 Py_TPFLAGS_DEFAULT,
800 crypto_X509_doc, /* doc */
801 NULL, /* traverse */
802 NULL, /* clear */
803 NULL, /* tp_richcompare */
804 0, /* tp_weaklistoffset */
805 NULL, /* tp_iter */
806 NULL, /* tp_iternext */
807 crypto_X509_methods, /* tp_methods */
808 NULL, /* tp_members */
809 NULL, /* tp_getset */
810 NULL, /* tp_base */
811 NULL, /* tp_dict */
812 NULL, /* tp_descr_get */
813 NULL, /* tp_descr_set */
814 0, /* tp_dictoffset */
815 NULL, /* tp_init */
816 NULL, /* tp_alloc */
817 crypto_X509_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500818};
819
820/*
821 * Initialize the X509 part of the crypto sub module
822 *
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400823 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500824 * Returns: None
825 */
826int
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400827init_crypto_x509(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500828{
Jean-Paul Calderonea4230d92009-06-27 10:54:04 -0400829 if (PyType_Ready(&crypto_X509_Type) < 0) {
830 return 0;
831 }
832
833 if (PyModule_AddObject(module, "X509", (PyObject *)&crypto_X509_Type) != 0) {
834 return 0;
835 }
836
837 if (PyModule_AddObject(module, "X509Type", (PyObject *)&crypto_X509_Type) != 0) {
838 return 0;
839 }
840
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500841 return 1;
842}
843