blob: d239a3b39310c3541523a40a986ca5619b559d8e [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 Calderone8b63d452008-03-21 18:31:12 -04005 * Copyright (C) Jean-Paul Calderone 2008, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05006 *
7 * 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"
15
16static char crypto_doc[] = "\n\
17Main file of crypto sub module.\n\
18See the file RATIONALE for a short explanation of why this module was written.\n\
19";
20
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050021void **ssl_API;
22
23PyObject *crypto_Error;
24
25static int
26global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
27{
28 PyObject *func, *argv, *ret;
29 int nchars;
30
31 func = (PyObject *)cb_arg;
32 argv = Py_BuildValue("(i)", rwflag);
33 ret = PyEval_CallObject(func, argv);
34 Py_DECREF(argv);
35 if (ret == NULL)
36 return 0;
37 if (!PyString_Check(ret))
38 {
39 PyErr_SetString(PyExc_ValueError, "String expected");
40 return 0;
41 }
42 nchars = PyString_Size(ret);
43 if (nchars > len)
44 nchars = len;
45 strncpy(buf, PyString_AsString(ret), nchars);
46 return nchars;
47}
48
49static char crypto_load_privatekey_doc[] = "\n\
50Load a private key from a buffer\n\
51\n\
52Arguments: spam - Always NULL\n\
53 args - The Python argument tuple, should be:\n\
54 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
55 buffer - The buffer the key is stored in\n\
56 passphrase - (optional) if encrypted PEM format, this can be\n\
57 either the passphrase to use, or a callback for\n\
58 providing the passphrase.\n\
59Returns: The PKey object\n\
60";
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 {
116 exception_from_error_queue();
117 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\
126Arguments: spam - Always NULL\n\
127 args - The Python argument tuple, should be:\n\
128 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
129 pkey - The PKey to dump\n\
130 cipher - (optional) if encrypted PEM format, the cipher to\n\
131 use\n\
132 passphrase - (optional) if encrypted PEM format, this can be either\n\
133 the passphrase to use, or a callback for providing the\n\
134 passphrase.\n\
135Returns: The buffer with the dumped key in\n\
136";
137
138static PyObject *
139crypto_dump_privatekey(PyObject *spam, PyObject *args)
140{
141 int type, ret, buf_len;
142 char *temp;
143 PyObject *buffer;
144 char *cipher_name = NULL;
145 const EVP_CIPHER *cipher = NULL;
146 PyObject *pw = NULL;
147 pem_password_cb *cb = NULL;
148 void *cb_arg = NULL;
149 BIO *bio;
150 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
202 default:
203 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
204 BIO_free(bio);
205 return NULL;
206 }
207
208 if (ret == 0)
209 {
210 BIO_free(bio);
211 exception_from_error_queue();
212 return NULL;
213 }
214
215 buf_len = BIO_get_mem_data(bio, &temp);
216 buffer = PyString_FromStringAndSize(temp, buf_len);
217 BIO_free(bio);
218
219 return buffer;
220}
221
222static char crypto_load_certificate_doc[] = "\n\
223Load a certificate from a buffer\n\
224\n\
225Arguments: spam - Always NULL\n\
226 args - The Python argument tuple, should be:\n\
227 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
228 buffer - The buffer the certificate is stored in\n\
229Returns: The X509 object\n\
230";
231
232static PyObject *
233crypto_load_certificate(PyObject *spam, PyObject *args)
234{
235 crypto_X509Obj *crypto_X509_New(X509 *, int);
236 int type, len;
237 char *buffer;
238 BIO *bio;
239 X509 *cert;
240
241 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
242 return NULL;
243
244 bio = BIO_new_mem_buf(buffer, len);
245 switch (type)
246 {
247 case X509_FILETYPE_PEM:
248 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
249 break;
250
251 case X509_FILETYPE_ASN1:
252 cert = d2i_X509_bio(bio, NULL);
253 break;
254
255 default:
256 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
257 BIO_free(bio);
258 return NULL;
259 }
260 BIO_free(bio);
261
262 if (cert == NULL)
263 {
264 exception_from_error_queue();
265 return NULL;
266 }
267
268 return (PyObject *)crypto_X509_New(cert, 1);
269}
270
271static char crypto_dump_certificate_doc[] = "\n\
272Dump a certificate to a buffer\n\
273\n\
274Arguments: spam - Always NULL\n\
275 args - The Python argument tuple, should be:\n\
276 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
277 cert - The certificate to dump\n\
278Returns: The buffer with the dumped certificate in\n\
279";
280
281static PyObject *
282crypto_dump_certificate(PyObject *spam, PyObject *args)
283{
284 int type, ret, buf_len;
285 char *temp;
286 PyObject *buffer;
287 BIO *bio;
288 crypto_X509Obj *cert;
289
290 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
291 &crypto_X509_Type, &cert))
292 return NULL;
293
294 bio = BIO_new(BIO_s_mem());
295 switch (type)
296 {
297 case X509_FILETYPE_PEM:
298 ret = PEM_write_bio_X509(bio, cert->x509);
299 break;
300
301 case X509_FILETYPE_ASN1:
302 ret = i2d_X509_bio(bio, cert->x509);
303 break;
304
305 default:
306 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
307 BIO_free(bio);
308 return NULL;
309 }
310
311 if (ret == 0)
312 {
313 BIO_free(bio);
314 exception_from_error_queue();
315 return NULL;
316 }
317
318 buf_len = BIO_get_mem_data(bio, &temp);
319 buffer = PyString_FromStringAndSize(temp, buf_len);
320 BIO_free(bio);
321
322 return buffer;
323}
324
325static char crypto_load_certificate_request_doc[] = "\n\
326Load a certificate request from a buffer\n\
327\n\
328Arguments: spam - Always NULL\n\
329 args - The Python argument tuple, should be:\n\
330 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
331 buffer - The buffer the certificate request is stored in\n\
332Returns: The X509Req object\n\
333";
334
335static PyObject *
336crypto_load_certificate_request(PyObject *spam, PyObject *args)
337{
338 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
339 int type, len;
340 char *buffer;
341 BIO *bio;
342 X509_REQ *req;
343
344 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
345 return NULL;
346
347 bio = BIO_new_mem_buf(buffer, len);
348 switch (type)
349 {
350 case X509_FILETYPE_PEM:
351 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
352 break;
353
354 case X509_FILETYPE_ASN1:
355 req = d2i_X509_REQ_bio(bio, NULL);
356 break;
357
358 default:
359 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
360 BIO_free(bio);
361 return NULL;
362 }
363 BIO_free(bio);
364
365 if (req == NULL)
366 {
367 exception_from_error_queue();
368 return NULL;
369 }
370
371 return (PyObject *)crypto_X509Req_New(req, 1);
372}
373
374static char crypto_dump_certificate_request_doc[] = "\n\
375Dump a certificate request to a buffer\n\
376\n\
377Arguments: spam - Always NULL\n\
378 args - The Python argument tuple, should be:\n\
379 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
380 req - The certificate request to dump\n\
381Returns: The buffer with the dumped certificate request in\n\
382";
383
384static PyObject *
385crypto_dump_certificate_request(PyObject *spam, PyObject *args)
386{
387 int type, ret, buf_len;
388 char *temp;
389 PyObject *buffer;
390 BIO *bio;
391 crypto_X509ReqObj *req;
392
393 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
394 &crypto_X509Req_Type, &req))
395 return NULL;
396
397 bio = BIO_new(BIO_s_mem());
398 switch (type)
399 {
400 case X509_FILETYPE_PEM:
401 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
402 break;
403
404 case X509_FILETYPE_ASN1:
405 ret = i2d_X509_REQ_bio(bio, req->x509_req);
406 break;
407
408 default:
409 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
410 BIO_free(bio);
411 return NULL;
412 }
413
414 if (ret == 0)
415 {
416 BIO_free(bio);
417 exception_from_error_queue();
418 return NULL;
419 }
420
421 buf_len = BIO_get_mem_data(bio, &temp);
422 buffer = PyString_FromStringAndSize(temp, buf_len);
423 BIO_free(bio);
424
425 return buffer;
426}
427
428static char crypto_load_pkcs7_data_doc[] = "\n\
429Load pkcs7 data from a buffer\n\
430\n\
431Arguments: spam - Always NULL\n\
432 args - The argument tuple, should be:\n\
433 type - The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
434 buffer - The buffer with the pkcs7 data.\n\
435Returns: The PKCS7 object\n\
436";
437
438static PyObject *
439crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
440{
441 int type, len;
442 char *buffer;
443 BIO *bio;
444 PKCS7 *pkcs7 = NULL;
445
446 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
447 return NULL;
448
449 /*
450 * Try to read the pkcs7 data from the bio
451 */
452 bio = BIO_new_mem_buf(buffer, len);
453 switch (type)
454 {
455 case X509_FILETYPE_PEM:
456 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
457 break;
458
459 case X509_FILETYPE_ASN1:
460 pkcs7 = d2i_PKCS7_bio(bio, NULL);
461 break;
462
463 default:
464 PyErr_SetString(PyExc_ValueError,
465 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
466 return NULL;
467 }
468 BIO_free(bio);
469
470 /*
471 * Check if we got a PKCS7 structure
472 */
473 if (pkcs7 == NULL)
474 {
475 exception_from_error_queue();
476 return NULL;
477 }
478
479 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
480}
481
482static char crypto_load_pkcs12_doc[] = "\n\
483Load a PKCS12 object from a buffer\n\
484\n\
485Arguments: spam - Always NULL\n\
486 args - The Python argument tuple, should be:\n\
487 buffer - The buffer the certificate is stored in\n\
488 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
489Returns: The PKCS12 object\n\
490";
491
492static PyObject *
493crypto_load_pkcs12(PyObject *spam, PyObject *args)
494{
495 crypto_PKCS12Obj *crypto_PKCS12_New(PKCS12 *, char *);
496 int len;
497 char *buffer, *passphrase = NULL;
498 BIO *bio;
499 PKCS12 *p12;
500
501 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
502 return NULL;
503
504 bio = BIO_new_mem_buf(buffer, len);
505 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
506 {
507 BIO_free(bio);
508 exception_from_error_queue();
509 return NULL;
510 }
511 BIO_free(bio);
512
513 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
514}
515
516
517static char crypto_X509_doc[] = "\n\
518The factory function inserted in the module dictionary to create X509\n\
519objects\n\
520\n\
521Arguments: spam - Always NULL\n\
522 args - The Python argument tuple, should be empty\n\
523Returns: The X509 object\n\
524";
525
526static PyObject *
527crypto_X509(PyObject *spam, PyObject *args)
528{
529 if (!PyArg_ParseTuple(args, ":X509"))
530 return NULL;
531
532 return (PyObject *)crypto_X509_New(X509_new(), 1);
533}
534
535static char crypto_X509Name_doc[] = "\n\
536The factory function inserted in the module dictionary as a copy\n\
537constructor for X509Name objects.\n\
538\n\
539Arguments: spam - Always NULL\n\
540 args - The Python argument tuple, should be:\n\
541 name - An X509Name object to copy\n\
542Returns: The X509Name object\n\
543";
544
545static PyObject *
546crypto_X509Name(PyObject *spam, PyObject *args)
547{
548 crypto_X509NameObj *name;
549
550 if (!PyArg_ParseTuple(args, "O!:X509Name", &crypto_X509Name_Type, &name))
551 return NULL;
552
553 return (PyObject *)crypto_X509Name_New(X509_NAME_dup(name->x509_name), 1);
554}
555
556static char crypto_X509Req_doc[] = "\n\
557The factory function inserted in the module dictionary to create X509Req\n\
558objects\n\
559\n\
560Arguments: spam - Always NULL\n\
561 args - The Python argument tuple, should be empty\n\
562Returns: The X509Req object\n\
563";
564
565static PyObject *
566crypto_X509Req(PyObject *spam, PyObject *args)
567{
568 if (!PyArg_ParseTuple(args, ":X509Req"))
569 return NULL;
570
571 return (PyObject *)crypto_X509Req_New(X509_REQ_new(), 1);
572}
573
574static char crypto_PKey_doc[] = "\n\
575The factory function inserted in the module dictionary to create PKey\n\
576objects\n\
577\n\
578Arguments: spam - Always NULL\n\
579 args - The Python argument tuple, should be empty\n\
580Returns: The PKey object\n\
581";
582
583static PyObject *
584crypto_PKey(PyObject *spam, PyObject *args)
585{
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400586 crypto_PKeyObj *py_pkey;
587
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500588 if (!PyArg_ParseTuple(args, ":PKey"))
589 return NULL;
590
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400591 py_pkey = crypto_PKey_New(EVP_PKEY_new(), 1);
592 if (py_pkey) {
593 py_pkey->initialized = 0;
594 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400595 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500596}
597
598static char crypto_X509Extension_doc[] = "\n\
599The factory function inserted in the module dictionary to create\n\
600X509Extension objects.\n\
601\n\
602Arguments: spam - Always NULL\n\
603 args - The Python argument tuple, should be\n\
604 typename - ???\n\
605 critical - ???\n\
606 value - ???\n\
607Returns: The X509Extension object\n\
608";
609
610static PyObject *
611crypto_X509Extension(PyObject *spam, PyObject *args)
612{
613 char *type_name, *value;
614 int critical;
615
616 if (!PyArg_ParseTuple(args, "sis:X509Extension", &type_name, &critical,
617 &value))
618 return NULL;
619
620 return (PyObject *)crypto_X509Extension_New(type_name, critical, value);
621}
622
623static char crypto_NetscapeSPKI_doc[] = "\n\
624The factory function inserted in the module dictionary to create NetscapeSPKI\n\
625objects\n\
626\n\
627Arguments: spam - Always NULL\n\
628 args - The Python argument tuple, should be empty or, optionally\n\
629 enc - Base64 encoded NetscapeSPKI object.\n\
630Returns: The NetscapeSPKI object\n\
631";
632
633static PyObject *
634crypto_NetscapeSPKI(PyObject *spam, PyObject *args)
635{
636 char *enc = NULL;
637 int enc_len = -1;
638 NETSCAPE_SPKI *spki;
639
640 if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
641 return NULL;
642
643 if (enc_len >= 0)
644 spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
645 else
646 spki = NETSCAPE_SPKI_new();
647 if (spki == NULL)
648 {
649 exception_from_error_queue();
650 return NULL;
651 }
652 return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
653}
654
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500655static char crypto_X509_verify_cert_error_string_doc[] = "\n\
656Get X509 verify certificate error string.\n\
657\n\
658Arguments: errnum - Error number\n\
659Returns: Error string as a Python string\n\
660";
661
662static PyObject *
663crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
664{
665 int errnum;
666 const char *str;
667
668 if (!PyArg_ParseTuple(args, "i", &errnum))
669 return NULL;
670
671 str = X509_verify_cert_error_string(errnum);
672 return PyString_FromString(str);
673}
674
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500675/* Methods in the OpenSSL.crypto module (i.e. none) */
676static PyMethodDef crypto_methods[] = {
677 /* Module functions */
678 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
679 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
680 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
681 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
682 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
683 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
684 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
685 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
686 /* Factory functions */
687 { "X509", (PyCFunction)crypto_X509, METH_VARARGS, crypto_X509_doc },
688 { "X509Name",(PyCFunction)crypto_X509Name,METH_VARARGS, crypto_X509Name_doc },
689 { "X509Req", (PyCFunction)crypto_X509Req, METH_VARARGS, crypto_X509Req_doc },
690 { "PKey", (PyCFunction)crypto_PKey, METH_VARARGS, crypto_PKey_doc },
691 { "X509Extension", (PyCFunction)crypto_X509Extension, METH_VARARGS, crypto_X509Extension_doc },
692 { "NetscapeSPKI", (PyCFunction)crypto_NetscapeSPKI, METH_VARARGS, crypto_NetscapeSPKI_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500693 { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500694 { NULL, NULL }
695};
696
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400697
698#ifdef WITH_THREAD
699
700#include <pythread.h>
701
702/**
703 * This array will store all of the mutexes available to OpenSSL.
704 */
705static PyThread_type_lock *mutex_buf = NULL;
706
707
708/**
709 * Callback function supplied to OpenSSL to acquire or release a lock.
710 *
711 */
712static void locking_function(int mode, int n, const char * file, int line) {
713 if (mode & CRYPTO_LOCK) {
714 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
715 } else {
716 PyThread_release_lock(mutex_buf[n]);
717 }
718}
719
720
721/**
722 * Initialize OpenSSL for use from multiple threads.
723 *
724 * Returns: 0 if initialization fails, 1 otherwise.
725 */
726static int init_openssl_threads(void) {
727 int i;
728
729 mutex_buf = (PyThread_type_lock *)malloc(
730 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
731 if (!mutex_buf) {
732 return 0;
733 }
734 for (i = 0; i < CRYPTO_num_locks(); ++i) {
735 mutex_buf[i] = PyThread_allocate_lock();
736 }
737 CRYPTO_set_id_callback(PyThread_get_thread_ident);
738 CRYPTO_set_locking_callback(locking_function);
739 return 1;
740}
741
742/* /\** */
743/* * Clean up after OpenSSL thread initialization. */
744/* *\/ */
745/* static int deinit_openssl_threads() { */
746/* int i; */
747
748/* if (!mutex_buf) { */
749/* return 0; */
750/* } */
751/* CRYPTO_set_id_callback(NULL); */
752/* CRYPTO_set_locking_callback(NULL); */
753/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
754/* PyThread_free_lock(mutex_buf[i]); */
755/* } */
756/* free(mutex_buf); */
757/* mutex_buf = NULL; */
758/* return 1; */
759/* } */
760
761#endif
762
763
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500764/*
765 * Initialize crypto sub module
766 *
767 * Arguments: None
768 * Returns: None
769 */
770void
771initcrypto(void)
772{
773 static void *crypto_API[crypto_API_pointers];
774 PyObject *c_api_object;
775 PyObject *module, *dict;
776
777 ERR_load_crypto_strings();
778 OpenSSL_add_all_algorithms();
779
780 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
781 return;
782
783 /* Initialize the C API pointer array */
784 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
785 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
786 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
787 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
788 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
789 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
790 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
791 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
792 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
793 if (c_api_object != NULL)
794 PyModule_AddObject(module, "_C_API", c_api_object);
795
796 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
797 if (crypto_Error == NULL)
798 goto error;
799 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
800 goto error;
801
802 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
803 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
804
805 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
806 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
807
808 dict = PyModule_GetDict(module);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400809#ifdef WITH_THREAD
810 if (!init_openssl_threads())
811 goto error;
812#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500813 if (!init_crypto_x509(dict))
814 goto error;
815 if (!init_crypto_x509name(dict))
816 goto error;
817 if (!init_crypto_x509store(dict))
818 goto error;
819 if (!init_crypto_x509req(dict))
820 goto error;
821 if (!init_crypto_pkey(dict))
822 goto error;
823 if (!init_crypto_x509extension(dict))
824 goto error;
825 if (!init_crypto_pkcs7(dict))
826 goto error;
827 if (!init_crypto_pkcs12(dict))
828 goto error;
829 if (!init_crypto_netscape_spki(dict))
830 goto error;
831
832error:
833 ;
834}
835