blob: cc97887795d488bbc9f17aa4016fc9140b1fbb3a [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * crypto.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
Jean-Paul Calderone88f38b22009-07-16 16:25:19 -04005 * Copyright (C) Jean-Paul Calderone 2008-2009, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 *
7 * Main file of crypto sub module.
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"
Rick Dean623ee362009-07-17 12:22:16 -050015#include "pkcs12.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050016
17static char crypto_doc[] = "\n\
18Main file of crypto sub module.\n\
19See the file RATIONALE for a short explanation of why this module was written.\n\
20";
21
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050022void **ssl_API;
23
24PyObject *crypto_Error;
25
26static int
27global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
28{
29 PyObject *func, *argv, *ret;
30 int nchars;
31
32 func = (PyObject *)cb_arg;
33 argv = Py_BuildValue("(i)", rwflag);
34 ret = PyEval_CallObject(func, argv);
35 Py_DECREF(argv);
36 if (ret == NULL)
37 return 0;
38 if (!PyString_Check(ret))
39 {
40 PyErr_SetString(PyExc_ValueError, "String expected");
41 return 0;
42 }
43 nchars = PyString_Size(ret);
44 if (nchars > len)
45 nchars = len;
46 strncpy(buf, PyString_AsString(ret), nchars);
47 return nchars;
48}
49
50static char crypto_load_privatekey_doc[] = "\n\
51Load a private key from a buffer\n\
52\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040053@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
54@param buffer: The buffer the key is stored in\n\
55@param passphrase: (optional) if encrypted PEM format, this can be\n\
56 either the passphrase to use, or a callback for\n\
57 providing the passphrase.\n\
58\n\
59@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050060";
61
62static PyObject *
63crypto_load_privatekey(PyObject *spam, PyObject *args)
64{
65 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
66 int type, len;
67 char *buffer;
68 PyObject *pw = NULL;
69 pem_password_cb *cb = NULL;
70 void *cb_arg = NULL;
71 BIO *bio;
72 EVP_PKEY *pkey;
73
74 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
75 return NULL;
76
77 if (pw != NULL)
78 {
79 if (PyString_Check(pw))
80 {
81 cb = NULL;
82 cb_arg = PyString_AsString(pw);
83 }
84 else if (PyCallable_Check(pw))
85 {
86 cb = global_passphrase_callback;
87 cb_arg = pw;
88 }
89 else
90 {
91 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
92 return NULL;
93 }
94 }
95
96 bio = BIO_new_mem_buf(buffer, len);
97 switch (type)
98 {
99 case X509_FILETYPE_PEM:
100 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
101 break;
102
103 case X509_FILETYPE_ASN1:
104 pkey = d2i_PrivateKey_bio(bio, NULL);
105 break;
106
107 default:
108 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
109 BIO_free(bio);
110 return NULL;
111 }
112 BIO_free(bio);
113
114 if (pkey == NULL)
115 {
Rick Deand369c932009-07-08 11:48:33 -0500116 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500117 return NULL;
118 }
119
120 return (PyObject *)crypto_PKey_New(pkey, 1);
121}
122
123static char crypto_dump_privatekey_doc[] = "\n\
124Dump a private key to a buffer\n\
125\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400126@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
127@param pkey: The PKey to dump\n\
128@param cipher: (optional) if encrypted PEM format, the cipher to\n\
129 use\n\
130@param passphrase - (optional) if encrypted PEM format, this can be either\n\
131 the passphrase to use, or a callback for providing the\n\
132 passphrase.\n\
133@return: The buffer with the dumped key in\n\
134@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500135";
136
137static PyObject *
138crypto_dump_privatekey(PyObject *spam, PyObject *args)
139{
140 int type, ret, buf_len;
141 char *temp;
142 PyObject *buffer;
143 char *cipher_name = NULL;
144 const EVP_CIPHER *cipher = NULL;
145 PyObject *pw = NULL;
146 pem_password_cb *cb = NULL;
147 void *cb_arg = NULL;
148 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500149 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500150 crypto_PKeyObj *pkey;
151
152 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
153 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
154 return NULL;
155
156 if (cipher_name != NULL && pw == NULL)
157 {
158 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
159 return NULL;
160 }
161 if (cipher_name != NULL)
162 {
163 cipher = EVP_get_cipherbyname(cipher_name);
164 if (cipher == NULL)
165 {
166 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
167 return NULL;
168 }
169 if (PyString_Check(pw))
170 {
171 cb = NULL;
172 cb_arg = PyString_AsString(pw);
173 }
174 else if (PyCallable_Check(pw))
175 {
176 cb = global_passphrase_callback;
177 cb_arg = pw;
178 }
179 else
180 {
181 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
182 return NULL;
183 }
184 }
185
186 bio = BIO_new(BIO_s_mem());
187 switch (type)
188 {
189 case X509_FILETYPE_PEM:
190 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
191 if (PyErr_Occurred())
192 {
193 BIO_free(bio);
194 return NULL;
195 }
196 break;
197
198 case X509_FILETYPE_ASN1:
199 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
200 break;
201
Rick Dean5b7b6372009-04-01 11:34:06 -0500202 case X509_FILETYPE_TEXT:
203 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
204 ret = RSA_print(bio, rsa, 0);
205 RSA_free(rsa);
206 break;
207
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500208 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500209 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500210 BIO_free(bio);
211 return NULL;
212 }
213
214 if (ret == 0)
215 {
216 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500217 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500218 return NULL;
219 }
220
221 buf_len = BIO_get_mem_data(bio, &temp);
222 buffer = PyString_FromStringAndSize(temp, buf_len);
223 BIO_free(bio);
224
225 return buffer;
226}
227
228static char crypto_load_certificate_doc[] = "\n\
229Load a certificate from a buffer\n\
230\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400231@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500232 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400233@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500234";
235
236static PyObject *
237crypto_load_certificate(PyObject *spam, PyObject *args)
238{
239 crypto_X509Obj *crypto_X509_New(X509 *, int);
240 int type, len;
241 char *buffer;
242 BIO *bio;
243 X509 *cert;
244
245 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
246 return NULL;
247
248 bio = BIO_new_mem_buf(buffer, len);
249 switch (type)
250 {
251 case X509_FILETYPE_PEM:
252 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
253 break;
254
255 case X509_FILETYPE_ASN1:
256 cert = d2i_X509_bio(bio, NULL);
257 break;
258
259 default:
260 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
261 BIO_free(bio);
262 return NULL;
263 }
264 BIO_free(bio);
265
266 if (cert == NULL)
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 return (PyObject *)crypto_X509_New(cert, 1);
273}
274
275static char crypto_dump_certificate_doc[] = "\n\
276Dump a certificate to a buffer\n\
277\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400278@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
279@param cert: The certificate to dump\n\
280@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500281";
282
283static PyObject *
284crypto_dump_certificate(PyObject *spam, PyObject *args)
285{
286 int type, ret, buf_len;
287 char *temp;
288 PyObject *buffer;
289 BIO *bio;
290 crypto_X509Obj *cert;
291
292 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
293 &crypto_X509_Type, &cert))
294 return NULL;
295
296 bio = BIO_new(BIO_s_mem());
297 switch (type)
298 {
299 case X509_FILETYPE_PEM:
300 ret = PEM_write_bio_X509(bio, cert->x509);
301 break;
302
303 case X509_FILETYPE_ASN1:
304 ret = i2d_X509_bio(bio, cert->x509);
305 break;
306
Rick Dean5b7b6372009-04-01 11:34:06 -0500307 case X509_FILETYPE_TEXT:
308 ret = X509_print_ex(bio, cert->x509, 0, 0);
309 break;
310
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500311 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500312 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500313 BIO_free(bio);
314 return NULL;
315 }
316
317 if (ret == 0)
318 {
319 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500320 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500321 return NULL;
322 }
323
324 buf_len = BIO_get_mem_data(bio, &temp);
325 buffer = PyString_FromStringAndSize(temp, buf_len);
326 BIO_free(bio);
327
328 return buffer;
329}
330
331static char crypto_load_certificate_request_doc[] = "\n\
332Load a certificate request from a buffer\n\
333\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400334@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500335 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400336@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500337";
338
339static PyObject *
340crypto_load_certificate_request(PyObject *spam, PyObject *args)
341{
342 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
343 int type, len;
344 char *buffer;
345 BIO *bio;
346 X509_REQ *req;
347
348 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
349 return NULL;
350
351 bio = BIO_new_mem_buf(buffer, len);
352 switch (type)
353 {
354 case X509_FILETYPE_PEM:
355 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
356 break;
357
358 case X509_FILETYPE_ASN1:
359 req = d2i_X509_REQ_bio(bio, NULL);
360 break;
361
362 default:
363 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
364 BIO_free(bio);
365 return NULL;
366 }
367 BIO_free(bio);
368
369 if (req == NULL)
370 {
Rick Deand369c932009-07-08 11:48:33 -0500371 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500372 return NULL;
373 }
374
375 return (PyObject *)crypto_X509Req_New(req, 1);
376}
377
378static char crypto_dump_certificate_request_doc[] = "\n\
379Dump a certificate request to a buffer\n\
380\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400381@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500382 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400383@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500384";
385
386static PyObject *
387crypto_dump_certificate_request(PyObject *spam, PyObject *args)
388{
389 int type, ret, buf_len;
390 char *temp;
391 PyObject *buffer;
392 BIO *bio;
393 crypto_X509ReqObj *req;
394
395 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
396 &crypto_X509Req_Type, &req))
397 return NULL;
398
399 bio = BIO_new(BIO_s_mem());
400 switch (type)
401 {
402 case X509_FILETYPE_PEM:
403 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
404 break;
405
406 case X509_FILETYPE_ASN1:
407 ret = i2d_X509_REQ_bio(bio, req->x509_req);
408 break;
409
Rick Dean5b7b6372009-04-01 11:34:06 -0500410 case X509_FILETYPE_TEXT:
411 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
412 break;
413
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500414 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500415 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500416 BIO_free(bio);
417 return NULL;
418 }
419
420 if (ret == 0)
421 {
422 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500423 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500424 return NULL;
425 }
426
427 buf_len = BIO_get_mem_data(bio, &temp);
428 buffer = PyString_FromStringAndSize(temp, buf_len);
429 BIO_free(bio);
430
431 return buffer;
432}
433
Rick Dean536ba022009-07-24 23:57:27 -0500434static char crypto_load_crl_doc[] = "\n\
435Load a certificate revocation list from a buffer\n\
436\n\
437@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
438@param buffer: The buffer the CRL is stored in\n\
439\n\
440@return: The PKey object\n\
441";
442
443static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400444crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500445 int type, len;
446 char *buffer;
447 BIO *bio;
448 X509_CRL *crl;
449
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400450 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500451 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400452 }
Rick Dean536ba022009-07-24 23:57:27 -0500453
454 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400455 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500456 case X509_FILETYPE_PEM:
457 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
458 break;
459
460 case X509_FILETYPE_ASN1:
461 crl = d2i_X509_CRL_bio(bio, NULL);
462 break;
463
464 default:
465 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
466 BIO_free(bio);
467 return NULL;
468 }
469 BIO_free(bio);
470
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400471 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500472 exception_from_error_queue(crypto_Error);
473 return NULL;
474 }
475
476 return (PyObject *)crypto_CRL_New(crl);
477}
478
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500479static char crypto_load_pkcs7_data_doc[] = "\n\
480Load pkcs7 data from a buffer\n\
481\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400482@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500483 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400484@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500485";
486
487static PyObject *
488crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
489{
490 int type, len;
491 char *buffer;
492 BIO *bio;
493 PKCS7 *pkcs7 = NULL;
494
495 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
496 return NULL;
497
498 /*
499 * Try to read the pkcs7 data from the bio
500 */
501 bio = BIO_new_mem_buf(buffer, len);
502 switch (type)
503 {
504 case X509_FILETYPE_PEM:
505 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
506 break;
507
508 case X509_FILETYPE_ASN1:
509 pkcs7 = d2i_PKCS7_bio(bio, NULL);
510 break;
511
512 default:
513 PyErr_SetString(PyExc_ValueError,
514 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
515 return NULL;
516 }
517 BIO_free(bio);
518
519 /*
520 * Check if we got a PKCS7 structure
521 */
522 if (pkcs7 == NULL)
523 {
Rick Deand369c932009-07-08 11:48:33 -0500524 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500525 return NULL;
526 }
527
528 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
529}
530
531static char crypto_load_pkcs12_doc[] = "\n\
532Load a PKCS12 object from a buffer\n\
533\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400534@param buffer: The buffer the certificate is stored in\n\
535 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
536@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500537";
538
539static PyObject *
540crypto_load_pkcs12(PyObject *spam, PyObject *args)
541{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500542 int len;
543 char *buffer, *passphrase = NULL;
544 BIO *bio;
545 PKCS12 *p12;
546
547 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
548 return NULL;
549
550 bio = BIO_new_mem_buf(buffer, len);
551 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
552 {
553 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500554 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500555 return NULL;
556 }
557 BIO_free(bio);
558
559 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
560}
561
562
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500563static char crypto_X509_verify_cert_error_string_doc[] = "\n\
564Get X509 verify certificate error string.\n\
565\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400566@param errnum: The error number.\n\
567@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500568";
569
570static PyObject *
571crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
572{
573 int errnum;
574 const char *str;
575
576 if (!PyArg_ParseTuple(args, "i", &errnum))
577 return NULL;
578
579 str = X509_verify_cert_error_string(errnum);
580 return PyString_FromString(str);
581}
582
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400583static char crypto_exception_from_error_queue_doc[] = "\n\
584Raise an exception from the current OpenSSL error queue.\n\
585";
586
587static PyObject *
588crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
589 exception_from_error_queue(crypto_Error);
590 return NULL;
591}
592
593
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500594/* Methods in the OpenSSL.crypto module (i.e. none) */
595static PyMethodDef crypto_methods[] = {
596 /* Module functions */
597 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
598 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
599 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
600 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
601 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
602 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500603 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500604 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
605 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500606 { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400607 { "_exception_from_error_queue", (PyCFunction)crypto_exception_from_error_queue, METH_NOARGS, crypto_exception_from_error_queue_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500608 { NULL, NULL }
609};
610
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400611
612#ifdef WITH_THREAD
613
614#include <pythread.h>
615
616/**
617 * This array will store all of the mutexes available to OpenSSL.
618 */
619static PyThread_type_lock *mutex_buf = NULL;
620
621
622/**
623 * Callback function supplied to OpenSSL to acquire or release a lock.
624 *
625 */
626static void locking_function(int mode, int n, const char * file, int line) {
627 if (mode & CRYPTO_LOCK) {
628 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
629 } else {
630 PyThread_release_lock(mutex_buf[n]);
631 }
632}
633
634
635/**
636 * Initialize OpenSSL for use from multiple threads.
637 *
638 * Returns: 0 if initialization fails, 1 otherwise.
639 */
640static int init_openssl_threads(void) {
641 int i;
642
643 mutex_buf = (PyThread_type_lock *)malloc(
644 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
645 if (!mutex_buf) {
646 return 0;
647 }
648 for (i = 0; i < CRYPTO_num_locks(); ++i) {
649 mutex_buf[i] = PyThread_allocate_lock();
650 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500651 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400652 CRYPTO_set_locking_callback(locking_function);
653 return 1;
654}
655
656/* /\** */
657/* * Clean up after OpenSSL thread initialization. */
658/* *\/ */
659/* static int deinit_openssl_threads() { */
660/* int i; */
661
662/* if (!mutex_buf) { */
663/* return 0; */
664/* } */
665/* CRYPTO_set_id_callback(NULL); */
666/* CRYPTO_set_locking_callback(NULL); */
667/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
668/* PyThread_free_lock(mutex_buf[i]); */
669/* } */
670/* free(mutex_buf); */
671/* mutex_buf = NULL; */
672/* return 1; */
673/* } */
674
675#endif
676
677
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500678/*
679 * Initialize crypto sub module
680 *
681 * Arguments: None
682 * Returns: None
683 */
684void
685initcrypto(void)
686{
687 static void *crypto_API[crypto_API_pointers];
688 PyObject *c_api_object;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400689 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500690
691 ERR_load_crypto_strings();
692 OpenSSL_add_all_algorithms();
693
694 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
695 return;
696
697 /* Initialize the C API pointer array */
698 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
699 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
700 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
701 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
702 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
703 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
704 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
705 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
706 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
707 if (c_api_object != NULL)
708 PyModule_AddObject(module, "_C_API", c_api_object);
709
710 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
711 if (crypto_Error == NULL)
712 goto error;
713 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
714 goto error;
715
716 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
717 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500718 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500719
720 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
721 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
722
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400723#ifdef WITH_THREAD
724 if (!init_openssl_threads())
725 goto error;
726#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400727 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500728 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400729 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500730 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400731 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500732 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400733 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500734 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400735 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500736 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400737 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500738 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400739 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500740 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400741 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500742 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400743 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500744 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500745 if (!init_crypto_crl(module))
746 goto error;
747 if (!init_crypto_revoked(module))
748 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500749error:
750 ;
751}