blob: 981d47803a28ebebfd1d5d97ec91f6ab283c7d87 [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 *
444crypto_load_crl(PyObject *spam, PyObject *args)
445{
446 int type, len;
447 char *buffer;
448 BIO *bio;
449 X509_CRL *crl;
450
451 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len))
452 return NULL;
453
454 bio = BIO_new_mem_buf(buffer, len);
455 switch (type)
456 {
457 case X509_FILETYPE_PEM:
458 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
459 break;
460
461 case X509_FILETYPE_ASN1:
462 crl = d2i_X509_CRL_bio(bio, NULL);
463 break;
464
465 default:
466 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
467 BIO_free(bio);
468 return NULL;
469 }
470 BIO_free(bio);
471
472 if (crl == NULL)
473 {
474 exception_from_error_queue(crypto_Error);
475 return NULL;
476 }
477
478 return (PyObject *)crypto_CRL_New(crl);
479}
480
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500481static char crypto_load_pkcs7_data_doc[] = "\n\
482Load pkcs7 data from a buffer\n\
483\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400484@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500485 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400486@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500487";
488
489static PyObject *
490crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
491{
492 int type, len;
493 char *buffer;
494 BIO *bio;
495 PKCS7 *pkcs7 = NULL;
496
497 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
498 return NULL;
499
500 /*
501 * Try to read the pkcs7 data from the bio
502 */
503 bio = BIO_new_mem_buf(buffer, len);
504 switch (type)
505 {
506 case X509_FILETYPE_PEM:
507 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
508 break;
509
510 case X509_FILETYPE_ASN1:
511 pkcs7 = d2i_PKCS7_bio(bio, NULL);
512 break;
513
514 default:
515 PyErr_SetString(PyExc_ValueError,
516 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
517 return NULL;
518 }
519 BIO_free(bio);
520
521 /*
522 * Check if we got a PKCS7 structure
523 */
524 if (pkcs7 == NULL)
525 {
Rick Deand369c932009-07-08 11:48:33 -0500526 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500527 return NULL;
528 }
529
530 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
531}
532
533static char crypto_load_pkcs12_doc[] = "\n\
534Load a PKCS12 object from a buffer\n\
535\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400536@param buffer: The buffer the certificate is stored in\n\
537 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
538@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500539";
540
541static PyObject *
542crypto_load_pkcs12(PyObject *spam, PyObject *args)
543{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500544 int len;
545 char *buffer, *passphrase = NULL;
546 BIO *bio;
547 PKCS12 *p12;
548
549 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
550 return NULL;
551
552 bio = BIO_new_mem_buf(buffer, len);
553 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
554 {
555 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500556 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500557 return NULL;
558 }
559 BIO_free(bio);
560
561 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
562}
563
564
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500565static char crypto_X509_verify_cert_error_string_doc[] = "\n\
566Get X509 verify certificate error string.\n\
567\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400568@param errnum: The error number.\n\
569@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500570";
571
572static PyObject *
573crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
574{
575 int errnum;
576 const char *str;
577
578 if (!PyArg_ParseTuple(args, "i", &errnum))
579 return NULL;
580
581 str = X509_verify_cert_error_string(errnum);
582 return PyString_FromString(str);
583}
584
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400585static char crypto_exception_from_error_queue_doc[] = "\n\
586Raise an exception from the current OpenSSL error queue.\n\
587";
588
589static PyObject *
590crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
591 exception_from_error_queue(crypto_Error);
592 return NULL;
593}
594
595
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500596/* Methods in the OpenSSL.crypto module (i.e. none) */
597static PyMethodDef crypto_methods[] = {
598 /* Module functions */
599 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
600 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
601 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
602 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
603 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
604 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500605 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500606 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
607 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500608 { "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 -0400609 { "_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 -0500610 { NULL, NULL }
611};
612
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400613
614#ifdef WITH_THREAD
615
616#include <pythread.h>
617
618/**
619 * This array will store all of the mutexes available to OpenSSL.
620 */
621static PyThread_type_lock *mutex_buf = NULL;
622
623
624/**
625 * Callback function supplied to OpenSSL to acquire or release a lock.
626 *
627 */
628static void locking_function(int mode, int n, const char * file, int line) {
629 if (mode & CRYPTO_LOCK) {
630 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
631 } else {
632 PyThread_release_lock(mutex_buf[n]);
633 }
634}
635
636
637/**
638 * Initialize OpenSSL for use from multiple threads.
639 *
640 * Returns: 0 if initialization fails, 1 otherwise.
641 */
642static int init_openssl_threads(void) {
643 int i;
644
645 mutex_buf = (PyThread_type_lock *)malloc(
646 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
647 if (!mutex_buf) {
648 return 0;
649 }
650 for (i = 0; i < CRYPTO_num_locks(); ++i) {
651 mutex_buf[i] = PyThread_allocate_lock();
652 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500653 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400654 CRYPTO_set_locking_callback(locking_function);
655 return 1;
656}
657
658/* /\** */
659/* * Clean up after OpenSSL thread initialization. */
660/* *\/ */
661/* static int deinit_openssl_threads() { */
662/* int i; */
663
664/* if (!mutex_buf) { */
665/* return 0; */
666/* } */
667/* CRYPTO_set_id_callback(NULL); */
668/* CRYPTO_set_locking_callback(NULL); */
669/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
670/* PyThread_free_lock(mutex_buf[i]); */
671/* } */
672/* free(mutex_buf); */
673/* mutex_buf = NULL; */
674/* return 1; */
675/* } */
676
677#endif
678
679
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500680/*
681 * Initialize crypto sub module
682 *
683 * Arguments: None
684 * Returns: None
685 */
686void
687initcrypto(void)
688{
689 static void *crypto_API[crypto_API_pointers];
690 PyObject *c_api_object;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400691 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500692
693 ERR_load_crypto_strings();
694 OpenSSL_add_all_algorithms();
695
696 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
697 return;
698
699 /* Initialize the C API pointer array */
700 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
701 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
702 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
703 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
704 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
705 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
706 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
707 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
708 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
709 if (c_api_object != NULL)
710 PyModule_AddObject(module, "_C_API", c_api_object);
711
712 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
713 if (crypto_Error == NULL)
714 goto error;
715 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
716 goto error;
717
718 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
719 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500720 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500721
722 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
723 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
724
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400725#ifdef WITH_THREAD
726 if (!init_openssl_threads())
727 goto error;
728#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400729 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500730 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400731 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500732 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400733 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500734 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400735 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500736 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400737 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500738 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400739 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500740 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400741 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500742 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400743 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500744 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400745 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500746 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500747 if (!init_crypto_crl(module))
748 goto error;
749 if (!init_crypto_revoked(module))
750 goto error;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500751error:
752 ;
753}