Initial import to Tizen
[profile/ivi/python-pyOpenSSL.git] / OpenSSL / crypto / crypto.c
1 /*
2  * crypto.c
3  *
4  * Copyright (C) AB Strakt
5  * Copyright (C) Keyphrene
6  * Copyright (C) Jean-Paul Calderone
7  * See LICENSE for details.
8  *
9  * Main file of crypto sub module.
10  * See the file RATIONALE for a short explanation of why this module was written.
11  *
12  * Reviewed 2001-07-23
13  */
14 #include <Python.h>
15 #define crypto_MODULE
16 #include "crypto.h"
17 #include "pkcs12.h"
18
19 static char crypto_doc[] = "\n\
20 Main file of crypto sub module.\n\
21 See the file RATIONALE for a short explanation of why this module was written.\n\
22 ";
23
24 void **ssl_API;
25
26 PyObject *crypto_Error;
27
28 int crypto_byte_converter(PyObject *input, void* output) {
29     char **message = output;
30     if (input == Py_None) {
31         *message = NULL;
32     } else if (PyBytes_CheckExact(input)) {
33         *message = PyBytes_AsString(input);
34     } else {
35         return 0;
36     }
37     return 1;
38 }
39
40 static int
41 global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
42 {
43     PyObject *func, *argv, *ret;
44     int nchars;
45
46     func = (PyObject *)cb_arg;
47     argv = Py_BuildValue("(i)", rwflag);
48     ret = PyEval_CallObject(func, argv);
49     Py_DECREF(argv);
50     if (ret == NULL)
51         return 0;
52     if (!PyBytes_Check(ret))
53     {
54         PyErr_SetString(PyExc_ValueError, "String expected");
55         return 0;
56     }
57     nchars = PyBytes_Size(ret);
58     if (nchars > len)
59         nchars = len;
60     strncpy(buf, PyBytes_AsString(ret), nchars);
61     return nchars;
62 }
63
64 static char crypto_load_privatekey_doc[] = "\n\
65 Load a private key from a buffer\n\
66 \n\
67 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
68 @param buffer: The buffer the key is stored in\n\
69 @param passphrase: (optional) if encrypted PEM format, this can be\n\
70                    either the passphrase to use, or a callback for\n\
71                    providing the passphrase.\n\
72 \n\
73 @return: The PKey object\n\
74 ";
75
76 static PyObject *
77 crypto_load_privatekey(PyObject *spam, PyObject *args)
78 {
79     crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
80     int type, len;
81     char *buffer;
82     PyObject *pw = NULL;
83     pem_password_cb *cb = NULL;
84     void *cb_arg = NULL;
85     BIO *bio;
86     EVP_PKEY *pkey;
87
88     if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
89         return NULL;
90
91     if (pw != NULL)
92     {
93         if (PyBytes_Check(pw))
94         {
95             cb = NULL;
96             cb_arg = PyBytes_AsString(pw);
97         }
98         else if (PyCallable_Check(pw))
99         {
100             cb = global_passphrase_callback;
101             cb_arg = pw;
102         }
103         else
104         {
105             PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
106             return NULL;
107         }
108     }
109
110     bio = BIO_new_mem_buf(buffer, len);
111     switch (type)
112     {
113         case X509_FILETYPE_PEM:
114             pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
115             break;
116
117         case X509_FILETYPE_ASN1:
118             pkey = d2i_PrivateKey_bio(bio, NULL);
119             break;
120
121         default:
122             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
123             BIO_free(bio);
124             return NULL;
125     }
126     BIO_free(bio);
127
128     if (pkey == NULL)
129     {
130         exception_from_error_queue(crypto_Error);
131         return NULL;
132     }
133
134     return (PyObject *)crypto_PKey_New(pkey, 1);
135 }
136
137 static char crypto_dump_privatekey_doc[] = "\n\
138 Dump a private key to a buffer\n\
139 \n\
140 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
141 @param pkey: The PKey to dump\n\
142 @param cipher: (optional) if encrypted PEM format, the cipher to\n\
143                use\n\
144 @param passphrase - (optional) if encrypted PEM format, this can be either\n\
145                     the passphrase to use, or a callback for providing the\n\
146                     passphrase.\n\
147 @return: The buffer with the dumped key in\n\
148 @rtype: C{str}\n\
149 ";
150
151 static PyObject *
152 crypto_dump_privatekey(PyObject *spam, PyObject *args)
153 {
154     int type, ret, buf_len;
155     char *temp;
156     PyObject *buffer;
157     char *cipher_name = NULL;
158     const EVP_CIPHER *cipher = NULL;
159     PyObject *pw = NULL;
160     pem_password_cb *cb = NULL;
161     void *cb_arg = NULL;
162     BIO *bio;
163     RSA *rsa;
164     crypto_PKeyObj *pkey;
165
166     if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
167                           &crypto_PKey_Type, &pkey, &cipher_name, &pw))
168         return NULL;
169
170     if (cipher_name != NULL && pw == NULL)
171     {
172         PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
173         return NULL;
174     }
175     if (cipher_name != NULL)
176     {
177         cipher = EVP_get_cipherbyname(cipher_name);
178         if (cipher == NULL)
179         {
180             PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
181             return NULL;
182         }
183         if (PyBytes_Check(pw))
184         {
185             cb = NULL;
186             cb_arg = PyBytes_AsString(pw);
187         }
188         else if (PyCallable_Check(pw))
189         {
190             cb = global_passphrase_callback;
191             cb_arg = pw;
192         }
193         else
194         {
195             PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
196             return NULL;
197         }
198     }
199
200     bio = BIO_new(BIO_s_mem());
201     switch (type)
202     {
203         case X509_FILETYPE_PEM:
204             ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
205             if (PyErr_Occurred())
206             {
207                 BIO_free(bio);
208                 return NULL;
209             }
210             break;
211
212         case X509_FILETYPE_ASN1:
213             ret = i2d_PrivateKey_bio(bio, pkey->pkey);
214             break;
215
216         case X509_FILETYPE_TEXT:
217             rsa = EVP_PKEY_get1_RSA(pkey->pkey);
218             ret = RSA_print(bio, rsa, 0);
219             RSA_free(rsa); 
220             break;
221
222         default:
223             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
224             BIO_free(bio);
225             return NULL;
226     }
227
228     if (ret == 0)
229     {
230         BIO_free(bio);
231         exception_from_error_queue(crypto_Error);
232         return NULL;
233     }
234
235     buf_len = BIO_get_mem_data(bio, &temp);
236     buffer = PyBytes_FromStringAndSize(temp, buf_len);
237     BIO_free(bio);
238
239     return buffer;
240 }
241
242 static char crypto_load_certificate_doc[] = "\n\
243 Load a certificate from a buffer\n\
244 \n\
245 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
246              buffer - The buffer the certificate is stored in\n\
247 @return: The X509 object\n\
248 ";
249
250 static PyObject *
251 crypto_load_certificate(PyObject *spam, PyObject *args)
252 {
253     crypto_X509Obj *crypto_X509_New(X509 *, int);
254     int type, len;
255     char *buffer;
256     BIO *bio;
257     X509 *cert;
258
259     if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
260         return NULL;
261
262     bio = BIO_new_mem_buf(buffer, len);
263     switch (type)
264     {
265         case X509_FILETYPE_PEM:
266             cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
267             break;
268
269         case X509_FILETYPE_ASN1:
270             cert = d2i_X509_bio(bio, NULL);
271             break;
272
273         default:
274             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
275             BIO_free(bio);
276             return NULL;
277     }
278     BIO_free(bio);
279
280     if (cert == NULL)
281     {
282         exception_from_error_queue(crypto_Error);
283         return NULL;
284     }
285
286     return (PyObject *)crypto_X509_New(cert, 1);
287 }
288
289 static char crypto_dump_certificate_doc[] = "\n\
290 Dump a certificate to a buffer\n\
291 \n\
292 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
293 @param cert: The certificate to dump\n\
294 @return: The buffer with the dumped certificate in\n\
295 ";
296
297 static PyObject *
298 crypto_dump_certificate(PyObject *spam, PyObject *args)
299 {
300     int type, ret, buf_len;
301     char *temp;
302     PyObject *buffer;
303     BIO *bio;
304     crypto_X509Obj *cert;
305
306     if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
307                           &crypto_X509_Type, &cert))
308         return NULL;
309
310     bio = BIO_new(BIO_s_mem());
311     switch (type)
312     {
313         case X509_FILETYPE_PEM:
314             ret = PEM_write_bio_X509(bio, cert->x509);
315             break;
316
317         case X509_FILETYPE_ASN1:
318             ret = i2d_X509_bio(bio, cert->x509);
319             break;
320
321         case X509_FILETYPE_TEXT:
322             ret = X509_print_ex(bio, cert->x509, 0, 0);
323             break;
324
325         default:
326             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
327             BIO_free(bio);
328             return NULL;
329     }
330
331     if (ret == 0)
332     {
333         BIO_free(bio);
334         exception_from_error_queue(crypto_Error);
335         return NULL;
336     }
337
338     buf_len = BIO_get_mem_data(bio, &temp);
339     buffer = PyBytes_FromStringAndSize(temp, buf_len);
340     BIO_free(bio);
341
342     return buffer;
343 }
344
345 static char crypto_load_certificate_request_doc[] = "\n\
346 Load a certificate request from a buffer\n\
347 \n\
348 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
349              buffer - The buffer the certificate request is stored in\n\
350 @return: The X509Req object\n\
351 ";
352
353 static PyObject *
354 crypto_load_certificate_request(PyObject *spam, PyObject *args)
355 {
356     crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
357     int type, len;
358     char *buffer;
359     BIO *bio;
360     X509_REQ *req;
361
362     if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
363         return NULL;
364
365     bio = BIO_new_mem_buf(buffer, len);
366     switch (type)
367     {
368         case X509_FILETYPE_PEM:
369             req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
370             break;
371
372         case X509_FILETYPE_ASN1:
373             req = d2i_X509_REQ_bio(bio, NULL);
374             break;
375
376         default:
377             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
378             BIO_free(bio);
379             return NULL;
380     }
381     BIO_free(bio);
382
383     if (req == NULL)
384     {
385         exception_from_error_queue(crypto_Error);
386         return NULL;
387     }
388
389     return (PyObject *)crypto_X509Req_New(req, 1);
390 }
391
392 static char crypto_dump_certificate_request_doc[] = "\n\
393 Dump a certificate request to a buffer\n\
394 \n\
395 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
396              req  - The certificate request to dump\n\
397 @return: The buffer with the dumped certificate request in\n\
398 ";
399
400 static PyObject *
401 crypto_dump_certificate_request(PyObject *spam, PyObject *args)
402 {
403     int type, ret, buf_len;
404     char *temp;
405     PyObject *buffer;
406     BIO *bio;
407     crypto_X509ReqObj *req;
408
409     if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
410                           &crypto_X509Req_Type, &req))
411         return NULL;
412
413     bio = BIO_new(BIO_s_mem());
414     switch (type)
415     {
416         case X509_FILETYPE_PEM:
417             ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
418             break;
419
420         case X509_FILETYPE_ASN1:
421             ret = i2d_X509_REQ_bio(bio, req->x509_req);
422             break;
423
424         case X509_FILETYPE_TEXT:
425             ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
426             break;
427
428         default:
429             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
430             BIO_free(bio);
431             return NULL;
432     }
433
434     if (ret == 0)
435     {
436         BIO_free(bio);
437         exception_from_error_queue(crypto_Error);
438         return NULL;
439     }
440
441     buf_len = BIO_get_mem_data(bio, &temp);
442     buffer = PyBytes_FromStringAndSize(temp, buf_len);
443     BIO_free(bio);
444
445     return buffer;
446 }
447
448 static char crypto_load_crl_doc[] = "\n\
449 Load a certificate revocation list from a buffer\n\
450 \n\
451 @param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
452 @param buffer: The buffer the CRL is stored in\n\
453 \n\
454 @return: The PKey object\n\
455 ";
456
457 static PyObject *
458 crypto_load_crl(PyObject *spam, PyObject *args) {
459     int type, len;
460     char *buffer;
461     BIO *bio;
462     X509_CRL *crl;
463
464     if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
465         return NULL;
466     }
467
468     bio = BIO_new_mem_buf(buffer, len);
469     switch (type) {
470         case X509_FILETYPE_PEM:
471             crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
472             break;
473
474         case X509_FILETYPE_ASN1:
475             crl = d2i_X509_CRL_bio(bio, NULL);
476             break;
477
478         default:
479             PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
480             BIO_free(bio);
481             return NULL;
482     }
483     BIO_free(bio);
484
485     if (crl == NULL) {
486         exception_from_error_queue(crypto_Error);
487         return NULL;
488     }
489
490     return (PyObject *)crypto_CRL_New(crl);
491 }
492
493 static char crypto_load_pkcs7_data_doc[] = "\n\
494 Load pkcs7 data from a buffer\n\
495 \n\
496 @param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
497              buffer - The buffer with the pkcs7 data.\n\
498 @return: The PKCS7 object\n\
499 ";
500
501 static PyObject *
502 crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
503 {
504     int type, len;
505     char *buffer;
506     BIO *bio;
507     PKCS7 *pkcs7 = NULL;
508
509     if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
510         return NULL;
511
512     /* 
513      * Try to read the pkcs7 data from the bio 
514      */
515     bio = BIO_new_mem_buf(buffer, len);
516     switch (type)
517     {
518         case X509_FILETYPE_PEM:
519             pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
520             break;
521
522         case X509_FILETYPE_ASN1:
523             pkcs7 = d2i_PKCS7_bio(bio, NULL);
524             break;
525
526         default:
527             PyErr_SetString(PyExc_ValueError,
528                     "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
529             return NULL;
530     }
531     BIO_free(bio);
532
533     /*
534      * Check if we got a PKCS7 structure
535      */
536     if (pkcs7 == NULL)
537     {
538         exception_from_error_queue(crypto_Error);
539         return NULL;
540     }
541
542     return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
543 }
544
545 static char crypto_load_pkcs12_doc[] = "\n\
546 Load a PKCS12 object from a buffer\n\
547 \n\
548 @param buffer: The buffer the certificate is stored in\n\
549                passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
550 @returns: The PKCS12 object\n\
551 ";
552
553 static PyObject *
554 crypto_load_pkcs12(PyObject *spam, PyObject *args)
555 {
556     int len;
557     char *buffer, *passphrase = NULL;
558     BIO *bio;
559     PKCS12 *p12;
560
561     if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
562         return NULL;
563
564     bio = BIO_new_mem_buf(buffer, len);
565     if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
566     {
567       BIO_free(bio);
568       exception_from_error_queue(crypto_Error);
569       return NULL;
570     }
571     BIO_free(bio);
572
573     return (PyObject *)crypto_PKCS12_New(p12, passphrase);
574 }
575
576
577 static char crypto_X509_verify_cert_error_string_doc[] = "\n\
578 Get X509 verify certificate error string.\n\
579 \n\
580 @param errnum: The error number.\n\
581 @return: Error string as a Python string\n\
582 ";
583
584 static PyObject *
585 crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
586 {
587     int errnum;
588     const char *str;
589
590     if (!PyArg_ParseTuple(args, "i", &errnum))
591         return NULL;
592
593     str = X509_verify_cert_error_string(errnum);
594     return PyText_FromString(str);
595 }
596
597 static char crypto_exception_from_error_queue_doc[] = "\n\
598 Raise an exception from the current OpenSSL error queue.\n\
599 ";
600
601 static PyObject *
602 crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
603     exception_from_error_queue(crypto_Error);
604     return NULL;
605 }
606
607 static char crypto_sign_doc[] = "\n\
608 Sign data with a digest\n\
609 \n\
610 @param pkey: Pkey to sign with\n\
611 @param data: data to be signed\n\
612 @param digest: message digest to use\n\
613 @return: signature\n\
614 ";
615
616 static PyObject *
617 crypto_sign(PyObject *spam, PyObject *args) {
618     PyObject *buffer;
619     crypto_PKeyObj *pkey;
620     char *data = NULL;
621     char *digest_name;
622     int err;
623     unsigned int sig_len;
624     const EVP_MD *digest;
625     EVP_MD_CTX md_ctx;
626     unsigned char sig_buf[512];
627
628     if (!PyArg_ParseTuple(
629             args, "O!" BYTESTRING_FMT "s:sign", &crypto_PKey_Type,
630             &pkey, &data, &digest_name)) {
631         return NULL;
632     }
633
634     if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
635         PyErr_SetString(PyExc_ValueError, "No such digest method");
636         return NULL;
637     }
638
639     EVP_SignInit(&md_ctx, digest);
640     EVP_SignUpdate(&md_ctx, data, strlen(data));
641     sig_len = sizeof(sig_buf);
642     err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
643
644     if (err != 1) {
645         exception_from_error_queue(crypto_Error);
646         return NULL;
647     }
648
649     buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
650     return buffer;
651 }
652
653 static char crypto_verify_doc[] = "\n\
654 Verify a signature\n\
655 \n\
656 @param cert: signing certificate (X509 object)\n\
657 @param signature: signature returned by sign function\n\
658 @param data: data to be verified\n\
659 @param digest: message digest to use\n\
660 @return: None if the signature is correct, raise exception otherwise\n\
661 ";
662
663 static PyObject *
664 crypto_verify(PyObject *spam, PyObject *args) {
665     crypto_X509Obj *cert;
666     unsigned char *signature;
667     int sig_len;
668     char *data, *digest_name;
669     int err;
670     const EVP_MD *digest;
671     EVP_MD_CTX md_ctx;
672     EVP_PKEY *pkey;
673
674 #ifdef PY3
675     if (!PyArg_ParseTuple(args, "O!" BYTESTRING_FMT "#" BYTESTRING_FMT "s:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
676 #else
677     if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
678 #endif
679         return NULL;
680     }
681
682     if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
683         PyErr_SetString(PyExc_ValueError, "No such digest method");
684         return NULL;
685     }
686
687     pkey = X509_get_pubkey(cert->x509);
688     if (pkey == NULL) {
689         PyErr_SetString(PyExc_ValueError, "No public key");
690         return NULL;
691     }
692
693     EVP_VerifyInit(&md_ctx, digest);
694     EVP_VerifyUpdate(&md_ctx, data, strlen((char*)data));
695     err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
696     EVP_PKEY_free(pkey);
697
698     if (err != 1) {
699         exception_from_error_queue(crypto_Error);
700         return NULL;
701     }
702
703     Py_INCREF(Py_None);
704     return Py_None;
705 }
706
707 /* Methods in the OpenSSL.crypto module (i.e. none) */
708 static PyMethodDef crypto_methods[] = {
709     /* Module functions */
710     { "load_privatekey",  (PyCFunction)crypto_load_privatekey,  METH_VARARGS, crypto_load_privatekey_doc },
711     { "dump_privatekey",  (PyCFunction)crypto_dump_privatekey,  METH_VARARGS, crypto_dump_privatekey_doc },
712     { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
713     { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
714     { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
715     { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
716     { "load_crl",         (PyCFunction)crypto_load_crl,         METH_VARARGS, crypto_load_crl_doc },
717     { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
718     { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
719     { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
720     { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
721     { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
722     { "_exception_from_error_queue", (PyCFunction)crypto_exception_from_error_queue, METH_NOARGS, crypto_exception_from_error_queue_doc },
723     { NULL, NULL }
724 };
725
726
727 #ifdef WITH_THREAD
728
729 #include <pythread.h>
730
731 /**
732  * This array will store all of the mutexes available to OpenSSL.
733  */
734 static PyThread_type_lock *mutex_buf = NULL;
735
736
737 /**
738  * Callback function supplied to OpenSSL to acquire or release a lock.
739  *
740  */
741 static void locking_function(int mode, int n, const char * file, int line) {
742     if (mode & CRYPTO_LOCK) {
743         PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
744     } else {
745         PyThread_release_lock(mutex_buf[n]);
746     }
747 }
748
749
750 /**
751  * Initialize OpenSSL for use from multiple threads.
752  *
753  * Returns: 0 if initialization fails, 1 otherwise.
754  */
755 static int init_openssl_threads(void) {
756     int i;
757
758     mutex_buf = (PyThread_type_lock *)malloc(
759         CRYPTO_num_locks() * sizeof(PyThread_type_lock));
760     if (!mutex_buf) {
761         return 0;
762     }
763     for (i = 0; i < CRYPTO_num_locks(); ++i) {
764         mutex_buf[i] = PyThread_allocate_lock();
765     }
766     CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
767     CRYPTO_set_locking_callback(locking_function);
768     return 1;
769 }
770
771 /* /\** */
772 /*  * Clean up after OpenSSL thread initialization. */
773 /*  *\/ */
774 /* static int deinit_openssl_threads() { */
775 /*     int i; */
776
777 /*     if (!mutex_buf) { */
778 /*         return 0; */
779 /*     } */
780 /*     CRYPTO_set_id_callback(NULL); */
781 /*     CRYPTO_set_locking_callback(NULL); */
782 /*     for (i = 0; i < CRYPTO_num_locks(); i++) { */
783 /*         PyThread_free_lock(mutex_buf[i]); */
784 /*     } */
785 /*     free(mutex_buf); */
786 /*     mutex_buf = NULL; */
787 /*     return 1; */
788 /* } */
789
790 #endif
791
792 #ifdef PY3
793 static struct PyModuleDef cryptomodule = {
794     PyModuleDef_HEAD_INIT,
795     "crypto",
796     crypto_doc,
797     -1,
798     crypto_methods
799 };
800 #endif
801
802 /*
803  * Initialize crypto sub module
804  *
805  * Arguments: None
806  * Returns:   None
807  */
808 PyOpenSSL_MODINIT(crypto) {
809 #ifndef PY3
810     static void *crypto_API[crypto_API_pointers];
811     PyObject *c_api_object;
812 #endif
813     PyObject *module;
814
815     ERR_load_crypto_strings();
816     OpenSSL_add_all_algorithms();
817
818 #ifdef PY3
819     module = PyModule_Create(&cryptomodule);
820 #else
821     module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
822 #endif
823
824     if (module == NULL) {
825         PyOpenSSL_MODRETURN(NULL);
826     }
827
828 #ifndef PY3
829     /* Initialize the C API pointer array */
830     crypto_API[crypto_X509_New_NUM]      = (void *)crypto_X509_New;
831     crypto_API[crypto_X509Name_New_NUM]  = (void *)crypto_X509Name_New;
832     crypto_API[crypto_X509Req_New_NUM]   = (void *)crypto_X509Req_New;
833     crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
834     crypto_API[crypto_PKey_New_NUM]      = (void *)crypto_PKey_New;
835     crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
836     crypto_API[crypto_PKCS7_New_NUM]     = (void *)crypto_PKCS7_New;
837     crypto_API[crypto_NetscapeSPKI_New_NUM]     = (void *)crypto_NetscapeSPKI_New;
838     c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
839     if (c_api_object != NULL)
840         PyModule_AddObject(module, "_C_API", c_api_object);
841 #endif
842
843     crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
844     if (crypto_Error == NULL)
845         goto error;
846     if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
847         goto error;
848
849     PyModule_AddIntConstant(module, "FILETYPE_PEM",  X509_FILETYPE_PEM);
850     PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
851     PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
852
853     PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
854     PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
855
856 #ifdef WITH_THREAD
857     if (!init_openssl_threads())
858         goto error;
859 #endif
860     if (!init_crypto_x509(module))
861         goto error;
862     if (!init_crypto_x509name(module))
863         goto error;
864     if (!init_crypto_x509store(module))
865         goto error;
866     if (!init_crypto_x509req(module))
867         goto error;
868     if (!init_crypto_pkey(module))
869         goto error;
870     if (!init_crypto_x509extension(module))
871         goto error;
872     if (!init_crypto_pkcs7(module))
873         goto error;
874     if (!init_crypto_pkcs12(module))
875         goto error;
876     if (!init_crypto_netscape_spki(module))
877         goto error;
878     if (!init_crypto_crl(module))
879         goto error;
880     if (!init_crypto_revoked(module))
881         goto error;
882
883     PyOpenSSL_MODRETURN(module);
884
885 error:
886     PyOpenSSL_MODRETURN(NULL);
887     ;
888 }