blob: decf722fa06341cde62cad3286b53c2e6a4f1a1d [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
434static char crypto_load_pkcs7_data_doc[] = "\n\
435Load pkcs7 data from a buffer\n\
436\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400437@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500438 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400439@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500440";
441
442static PyObject *
443crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
444{
445 int type, len;
446 char *buffer;
447 BIO *bio;
448 PKCS7 *pkcs7 = NULL;
449
450 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
451 return NULL;
452
453 /*
454 * Try to read the pkcs7 data from the bio
455 */
456 bio = BIO_new_mem_buf(buffer, len);
457 switch (type)
458 {
459 case X509_FILETYPE_PEM:
460 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
461 break;
462
463 case X509_FILETYPE_ASN1:
464 pkcs7 = d2i_PKCS7_bio(bio, NULL);
465 break;
466
467 default:
468 PyErr_SetString(PyExc_ValueError,
469 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
470 return NULL;
471 }
472 BIO_free(bio);
473
474 /*
475 * Check if we got a PKCS7 structure
476 */
477 if (pkcs7 == NULL)
478 {
Rick Deand369c932009-07-08 11:48:33 -0500479 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500480 return NULL;
481 }
482
483 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
484}
485
486static char crypto_load_pkcs12_doc[] = "\n\
487Load a PKCS12 object from a buffer\n\
488\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400489@param buffer: The buffer the certificate is stored in\n\
490 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
491@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492";
493
494static PyObject *
495crypto_load_pkcs12(PyObject *spam, PyObject *args)
496{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500497 int len;
498 char *buffer, *passphrase = NULL;
499 BIO *bio;
500 PKCS12 *p12;
501
502 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
503 return NULL;
504
505 bio = BIO_new_mem_buf(buffer, len);
506 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
507 {
508 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500509 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500510 return NULL;
511 }
512 BIO_free(bio);
513
514 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
515}
516
517
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500518static char crypto_X509_verify_cert_error_string_doc[] = "\n\
519Get X509 verify certificate error string.\n\
520\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400521@param errnum: The error number.\n\
522@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500523";
524
525static PyObject *
526crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
527{
528 int errnum;
529 const char *str;
530
531 if (!PyArg_ParseTuple(args, "i", &errnum))
532 return NULL;
533
534 str = X509_verify_cert_error_string(errnum);
535 return PyString_FromString(str);
536}
537
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400538static char crypto_exception_from_error_queue_doc[] = "\n\
539Raise an exception from the current OpenSSL error queue.\n\
540";
541
542static PyObject *
543crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
544 exception_from_error_queue(crypto_Error);
545 return NULL;
546}
547
548
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500549/* Methods in the OpenSSL.crypto module (i.e. none) */
550static PyMethodDef crypto_methods[] = {
551 /* Module functions */
552 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
553 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
554 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
555 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
556 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
557 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
558 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
559 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500560 { "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 -0400561 { "_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 -0500562 { NULL, NULL }
563};
564
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400565
566#ifdef WITH_THREAD
567
568#include <pythread.h>
569
570/**
571 * This array will store all of the mutexes available to OpenSSL.
572 */
573static PyThread_type_lock *mutex_buf = NULL;
574
575
576/**
577 * Callback function supplied to OpenSSL to acquire or release a lock.
578 *
579 */
580static void locking_function(int mode, int n, const char * file, int line) {
581 if (mode & CRYPTO_LOCK) {
582 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
583 } else {
584 PyThread_release_lock(mutex_buf[n]);
585 }
586}
587
588
589/**
590 * Initialize OpenSSL for use from multiple threads.
591 *
592 * Returns: 0 if initialization fails, 1 otherwise.
593 */
594static int init_openssl_threads(void) {
595 int i;
596
597 mutex_buf = (PyThread_type_lock *)malloc(
598 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
599 if (!mutex_buf) {
600 return 0;
601 }
602 for (i = 0; i < CRYPTO_num_locks(); ++i) {
603 mutex_buf[i] = PyThread_allocate_lock();
604 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500605 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400606 CRYPTO_set_locking_callback(locking_function);
607 return 1;
608}
609
610/* /\** */
611/* * Clean up after OpenSSL thread initialization. */
612/* *\/ */
613/* static int deinit_openssl_threads() { */
614/* int i; */
615
616/* if (!mutex_buf) { */
617/* return 0; */
618/* } */
619/* CRYPTO_set_id_callback(NULL); */
620/* CRYPTO_set_locking_callback(NULL); */
621/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
622/* PyThread_free_lock(mutex_buf[i]); */
623/* } */
624/* free(mutex_buf); */
625/* mutex_buf = NULL; */
626/* return 1; */
627/* } */
628
629#endif
630
631
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500632/*
633 * Initialize crypto sub module
634 *
635 * Arguments: None
636 * Returns: None
637 */
638void
639initcrypto(void)
640{
641 static void *crypto_API[crypto_API_pointers];
642 PyObject *c_api_object;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400643 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500644
645 ERR_load_crypto_strings();
646 OpenSSL_add_all_algorithms();
647
648 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
649 return;
650
651 /* Initialize the C API pointer array */
652 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
653 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
654 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
655 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
656 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
657 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
658 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
659 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
660 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
661 if (c_api_object != NULL)
662 PyModule_AddObject(module, "_C_API", c_api_object);
663
664 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
665 if (crypto_Error == NULL)
666 goto error;
667 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
668 goto error;
669
670 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
671 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500672 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500673
674 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
675 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
676
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400677#ifdef WITH_THREAD
678 if (!init_openssl_threads())
679 goto error;
680#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400681 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500682 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400683 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500684 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400685 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500686 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400687 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500688 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400689 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500690 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400691 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500692 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400693 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500694 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400695 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500696 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400697 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500698 goto error;
699
700error:
701 ;
702}