blob: 257c01660c76745997d461c6c2a519e7375336f6 [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;
Rick Dean5b7b6372009-04-01 11:34:06 -0500150 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500151 crypto_PKeyObj *pkey;
152
153 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
154 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
155 return NULL;
156
157 if (cipher_name != NULL && pw == NULL)
158 {
159 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
160 return NULL;
161 }
162 if (cipher_name != NULL)
163 {
164 cipher = EVP_get_cipherbyname(cipher_name);
165 if (cipher == NULL)
166 {
167 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
168 return NULL;
169 }
170 if (PyString_Check(pw))
171 {
172 cb = NULL;
173 cb_arg = PyString_AsString(pw);
174 }
175 else if (PyCallable_Check(pw))
176 {
177 cb = global_passphrase_callback;
178 cb_arg = pw;
179 }
180 else
181 {
182 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
183 return NULL;
184 }
185 }
186
187 bio = BIO_new(BIO_s_mem());
188 switch (type)
189 {
190 case X509_FILETYPE_PEM:
191 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
192 if (PyErr_Occurred())
193 {
194 BIO_free(bio);
195 return NULL;
196 }
197 break;
198
199 case X509_FILETYPE_ASN1:
200 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
201 break;
202
Rick Dean5b7b6372009-04-01 11:34:06 -0500203 case X509_FILETYPE_TEXT:
204 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
205 ret = RSA_print(bio, rsa, 0);
206 RSA_free(rsa);
207 break;
208
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500209 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500210 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500211 BIO_free(bio);
212 return NULL;
213 }
214
215 if (ret == 0)
216 {
217 BIO_free(bio);
218 exception_from_error_queue();
219 return NULL;
220 }
221
222 buf_len = BIO_get_mem_data(bio, &temp);
223 buffer = PyString_FromStringAndSize(temp, buf_len);
224 BIO_free(bio);
225
226 return buffer;
227}
228
229static char crypto_load_certificate_doc[] = "\n\
230Load a certificate from a buffer\n\
231\n\
232Arguments: spam - Always NULL\n\
233 args - The Python argument tuple, should be:\n\
234 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
235 buffer - The buffer the certificate is stored in\n\
236Returns: The X509 object\n\
237";
238
239static PyObject *
240crypto_load_certificate(PyObject *spam, PyObject *args)
241{
242 crypto_X509Obj *crypto_X509_New(X509 *, int);
243 int type, len;
244 char *buffer;
245 BIO *bio;
246 X509 *cert;
247
248 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
249 return NULL;
250
251 bio = BIO_new_mem_buf(buffer, len);
252 switch (type)
253 {
254 case X509_FILETYPE_PEM:
255 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
256 break;
257
258 case X509_FILETYPE_ASN1:
259 cert = d2i_X509_bio(bio, NULL);
260 break;
261
262 default:
263 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
264 BIO_free(bio);
265 return NULL;
266 }
267 BIO_free(bio);
268
269 if (cert == NULL)
270 {
271 exception_from_error_queue();
272 return NULL;
273 }
274
275 return (PyObject *)crypto_X509_New(cert, 1);
276}
277
278static char crypto_dump_certificate_doc[] = "\n\
279Dump a certificate to a buffer\n\
280\n\
281Arguments: spam - Always NULL\n\
282 args - The Python argument tuple, should be:\n\
283 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
284 cert - The certificate to dump\n\
285Returns: The buffer with the dumped certificate in\n\
286";
287
288static PyObject *
289crypto_dump_certificate(PyObject *spam, PyObject *args)
290{
291 int type, ret, buf_len;
292 char *temp;
293 PyObject *buffer;
294 BIO *bio;
295 crypto_X509Obj *cert;
296
297 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
298 &crypto_X509_Type, &cert))
299 return NULL;
300
301 bio = BIO_new(BIO_s_mem());
302 switch (type)
303 {
304 case X509_FILETYPE_PEM:
305 ret = PEM_write_bio_X509(bio, cert->x509);
306 break;
307
308 case X509_FILETYPE_ASN1:
309 ret = i2d_X509_bio(bio, cert->x509);
310 break;
311
Rick Dean5b7b6372009-04-01 11:34:06 -0500312 case X509_FILETYPE_TEXT:
313 ret = X509_print_ex(bio, cert->x509, 0, 0);
314 break;
315
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500316 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500317 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500318 BIO_free(bio);
319 return NULL;
320 }
321
322 if (ret == 0)
323 {
324 BIO_free(bio);
325 exception_from_error_queue();
326 return NULL;
327 }
328
329 buf_len = BIO_get_mem_data(bio, &temp);
330 buffer = PyString_FromStringAndSize(temp, buf_len);
331 BIO_free(bio);
332
333 return buffer;
334}
335
336static char crypto_load_certificate_request_doc[] = "\n\
337Load a certificate request from a buffer\n\
338\n\
339Arguments: spam - Always NULL\n\
340 args - The Python argument tuple, should be:\n\
341 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
342 buffer - The buffer the certificate request is stored in\n\
343Returns: The X509Req object\n\
344";
345
346static PyObject *
347crypto_load_certificate_request(PyObject *spam, PyObject *args)
348{
349 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
350 int type, len;
351 char *buffer;
352 BIO *bio;
353 X509_REQ *req;
354
355 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
356 return NULL;
357
358 bio = BIO_new_mem_buf(buffer, len);
359 switch (type)
360 {
361 case X509_FILETYPE_PEM:
362 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
363 break;
364
365 case X509_FILETYPE_ASN1:
366 req = d2i_X509_REQ_bio(bio, NULL);
367 break;
368
369 default:
370 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
371 BIO_free(bio);
372 return NULL;
373 }
374 BIO_free(bio);
375
376 if (req == NULL)
377 {
378 exception_from_error_queue();
379 return NULL;
380 }
381
382 return (PyObject *)crypto_X509Req_New(req, 1);
383}
384
385static char crypto_dump_certificate_request_doc[] = "\n\
386Dump a certificate request to a buffer\n\
387\n\
388Arguments: spam - Always NULL\n\
389 args - The Python argument tuple, should be:\n\
390 type - The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
391 req - The certificate request to dump\n\
392Returns: The buffer with the dumped certificate request in\n\
393";
394
395static PyObject *
396crypto_dump_certificate_request(PyObject *spam, PyObject *args)
397{
398 int type, ret, buf_len;
399 char *temp;
400 PyObject *buffer;
401 BIO *bio;
402 crypto_X509ReqObj *req;
403
404 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
405 &crypto_X509Req_Type, &req))
406 return NULL;
407
408 bio = BIO_new(BIO_s_mem());
409 switch (type)
410 {
411 case X509_FILETYPE_PEM:
412 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
413 break;
414
415 case X509_FILETYPE_ASN1:
416 ret = i2d_X509_REQ_bio(bio, req->x509_req);
417 break;
418
Rick Dean5b7b6372009-04-01 11:34:06 -0500419 case X509_FILETYPE_TEXT:
420 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
421 break;
422
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500423 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500424 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500425 BIO_free(bio);
426 return NULL;
427 }
428
429 if (ret == 0)
430 {
431 BIO_free(bio);
432 exception_from_error_queue();
433 return NULL;
434 }
435
436 buf_len = BIO_get_mem_data(bio, &temp);
437 buffer = PyString_FromStringAndSize(temp, buf_len);
438 BIO_free(bio);
439
440 return buffer;
441}
442
443static char crypto_load_pkcs7_data_doc[] = "\n\
444Load pkcs7 data from a buffer\n\
445\n\
446Arguments: spam - Always NULL\n\
447 args - The argument tuple, should be:\n\
448 type - The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
449 buffer - The buffer with the pkcs7 data.\n\
450Returns: The PKCS7 object\n\
451";
452
453static PyObject *
454crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
455{
456 int type, len;
457 char *buffer;
458 BIO *bio;
459 PKCS7 *pkcs7 = NULL;
460
461 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
462 return NULL;
463
464 /*
465 * Try to read the pkcs7 data from the bio
466 */
467 bio = BIO_new_mem_buf(buffer, len);
468 switch (type)
469 {
470 case X509_FILETYPE_PEM:
471 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
472 break;
473
474 case X509_FILETYPE_ASN1:
475 pkcs7 = d2i_PKCS7_bio(bio, NULL);
476 break;
477
478 default:
479 PyErr_SetString(PyExc_ValueError,
480 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
481 return NULL;
482 }
483 BIO_free(bio);
484
485 /*
486 * Check if we got a PKCS7 structure
487 */
488 if (pkcs7 == NULL)
489 {
490 exception_from_error_queue();
491 return NULL;
492 }
493
494 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
495}
496
497static char crypto_load_pkcs12_doc[] = "\n\
498Load a PKCS12 object from a buffer\n\
499\n\
500Arguments: spam - Always NULL\n\
501 args - The Python argument tuple, should be:\n\
502 buffer - The buffer the certificate is stored in\n\
503 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
504Returns: The PKCS12 object\n\
505";
506
507static PyObject *
508crypto_load_pkcs12(PyObject *spam, PyObject *args)
509{
510 crypto_PKCS12Obj *crypto_PKCS12_New(PKCS12 *, char *);
511 int len;
512 char *buffer, *passphrase = NULL;
513 BIO *bio;
514 PKCS12 *p12;
515
516 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
517 return NULL;
518
519 bio = BIO_new_mem_buf(buffer, len);
520 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
521 {
522 BIO_free(bio);
523 exception_from_error_queue();
524 return NULL;
525 }
526 BIO_free(bio);
527
528 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
529}
530
531
532static char crypto_X509_doc[] = "\n\
533The factory function inserted in the module dictionary to create X509\n\
534objects\n\
535\n\
536Arguments: spam - Always NULL\n\
537 args - The Python argument tuple, should be empty\n\
538Returns: The X509 object\n\
539";
540
541static PyObject *
542crypto_X509(PyObject *spam, PyObject *args)
543{
544 if (!PyArg_ParseTuple(args, ":X509"))
545 return NULL;
546
547 return (PyObject *)crypto_X509_New(X509_new(), 1);
548}
549
550static char crypto_X509Name_doc[] = "\n\
551The factory function inserted in the module dictionary as a copy\n\
552constructor for X509Name objects.\n\
553\n\
554Arguments: spam - Always NULL\n\
555 args - The Python argument tuple, should be:\n\
556 name - An X509Name object to copy\n\
557Returns: The X509Name object\n\
558";
559
560static PyObject *
561crypto_X509Name(PyObject *spam, PyObject *args)
562{
563 crypto_X509NameObj *name;
564
565 if (!PyArg_ParseTuple(args, "O!:X509Name", &crypto_X509Name_Type, &name))
566 return NULL;
567
568 return (PyObject *)crypto_X509Name_New(X509_NAME_dup(name->x509_name), 1);
569}
570
571static char crypto_X509Req_doc[] = "\n\
572The factory function inserted in the module dictionary to create X509Req\n\
573objects\n\
574\n\
575Arguments: spam - Always NULL\n\
576 args - The Python argument tuple, should be empty\n\
577Returns: The X509Req object\n\
578";
579
580static PyObject *
581crypto_X509Req(PyObject *spam, PyObject *args)
582{
583 if (!PyArg_ParseTuple(args, ":X509Req"))
584 return NULL;
585
586 return (PyObject *)crypto_X509Req_New(X509_REQ_new(), 1);
587}
588
589static char crypto_PKey_doc[] = "\n\
590The factory function inserted in the module dictionary to create PKey\n\
591objects\n\
592\n\
593Arguments: spam - Always NULL\n\
594 args - The Python argument tuple, should be empty\n\
595Returns: The PKey object\n\
596";
597
598static PyObject *
599crypto_PKey(PyObject *spam, PyObject *args)
600{
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400601 crypto_PKeyObj *py_pkey;
602
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500603 if (!PyArg_ParseTuple(args, ":PKey"))
604 return NULL;
605
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400606 py_pkey = crypto_PKey_New(EVP_PKEY_new(), 1);
607 if (py_pkey) {
608 py_pkey->initialized = 0;
609 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400610 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500611}
612
613static char crypto_X509Extension_doc[] = "\n\
614The factory function inserted in the module dictionary to create\n\
615X509Extension objects.\n\
616\n\
617Arguments: spam - Always NULL\n\
618 args - The Python argument tuple, should be\n\
619 typename - ???\n\
620 critical - ???\n\
621 value - ???\n\
622Returns: The X509Extension object\n\
623";
624
625static PyObject *
626crypto_X509Extension(PyObject *spam, PyObject *args)
627{
628 char *type_name, *value;
629 int critical;
630
631 if (!PyArg_ParseTuple(args, "sis:X509Extension", &type_name, &critical,
632 &value))
633 return NULL;
634
635 return (PyObject *)crypto_X509Extension_New(type_name, critical, value);
636}
637
638static char crypto_NetscapeSPKI_doc[] = "\n\
639The factory function inserted in the module dictionary to create NetscapeSPKI\n\
640objects\n\
641\n\
642Arguments: spam - Always NULL\n\
643 args - The Python argument tuple, should be empty or, optionally\n\
644 enc - Base64 encoded NetscapeSPKI object.\n\
645Returns: The NetscapeSPKI object\n\
646";
647
648static PyObject *
649crypto_NetscapeSPKI(PyObject *spam, PyObject *args)
650{
651 char *enc = NULL;
652 int enc_len = -1;
653 NETSCAPE_SPKI *spki;
654
655 if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
656 return NULL;
657
658 if (enc_len >= 0)
659 spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
660 else
661 spki = NETSCAPE_SPKI_new();
662 if (spki == NULL)
663 {
664 exception_from_error_queue();
665 return NULL;
666 }
667 return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
668}
669
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500670static char crypto_X509_verify_cert_error_string_doc[] = "\n\
671Get X509 verify certificate error string.\n\
672\n\
673Arguments: errnum - Error number\n\
674Returns: Error string as a Python string\n\
675";
676
677static PyObject *
678crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
679{
680 int errnum;
681 const char *str;
682
683 if (!PyArg_ParseTuple(args, "i", &errnum))
684 return NULL;
685
686 str = X509_verify_cert_error_string(errnum);
687 return PyString_FromString(str);
688}
689
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500690/* Methods in the OpenSSL.crypto module (i.e. none) */
691static PyMethodDef crypto_methods[] = {
692 /* Module functions */
693 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
694 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
695 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
696 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
697 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
698 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
699 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
700 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
701 /* Factory functions */
702 { "X509", (PyCFunction)crypto_X509, METH_VARARGS, crypto_X509_doc },
703 { "X509Name",(PyCFunction)crypto_X509Name,METH_VARARGS, crypto_X509Name_doc },
704 { "X509Req", (PyCFunction)crypto_X509Req, METH_VARARGS, crypto_X509Req_doc },
705 { "PKey", (PyCFunction)crypto_PKey, METH_VARARGS, crypto_PKey_doc },
706 { "X509Extension", (PyCFunction)crypto_X509Extension, METH_VARARGS, crypto_X509Extension_doc },
707 { "NetscapeSPKI", (PyCFunction)crypto_NetscapeSPKI, METH_VARARGS, crypto_NetscapeSPKI_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500708 { "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 -0500709 { NULL, NULL }
710};
711
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400712
713#ifdef WITH_THREAD
714
715#include <pythread.h>
716
717/**
718 * This array will store all of the mutexes available to OpenSSL.
719 */
720static PyThread_type_lock *mutex_buf = NULL;
721
722
723/**
724 * Callback function supplied to OpenSSL to acquire or release a lock.
725 *
726 */
727static void locking_function(int mode, int n, const char * file, int line) {
728 if (mode & CRYPTO_LOCK) {
729 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
730 } else {
731 PyThread_release_lock(mutex_buf[n]);
732 }
733}
734
735
736/**
737 * Initialize OpenSSL for use from multiple threads.
738 *
739 * Returns: 0 if initialization fails, 1 otherwise.
740 */
741static int init_openssl_threads(void) {
742 int i;
743
744 mutex_buf = (PyThread_type_lock *)malloc(
745 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
746 if (!mutex_buf) {
747 return 0;
748 }
749 for (i = 0; i < CRYPTO_num_locks(); ++i) {
750 mutex_buf[i] = PyThread_allocate_lock();
751 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500752 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400753 CRYPTO_set_locking_callback(locking_function);
754 return 1;
755}
756
757/* /\** */
758/* * Clean up after OpenSSL thread initialization. */
759/* *\/ */
760/* static int deinit_openssl_threads() { */
761/* int i; */
762
763/* if (!mutex_buf) { */
764/* return 0; */
765/* } */
766/* CRYPTO_set_id_callback(NULL); */
767/* CRYPTO_set_locking_callback(NULL); */
768/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
769/* PyThread_free_lock(mutex_buf[i]); */
770/* } */
771/* free(mutex_buf); */
772/* mutex_buf = NULL; */
773/* return 1; */
774/* } */
775
776#endif
777
778
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500779/*
780 * Initialize crypto sub module
781 *
782 * Arguments: None
783 * Returns: None
784 */
785void
786initcrypto(void)
787{
788 static void *crypto_API[crypto_API_pointers];
789 PyObject *c_api_object;
790 PyObject *module, *dict;
791
792 ERR_load_crypto_strings();
793 OpenSSL_add_all_algorithms();
794
795 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
796 return;
797
798 /* Initialize the C API pointer array */
799 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
800 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
801 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
802 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
803 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
804 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
805 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
806 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
807 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
808 if (c_api_object != NULL)
809 PyModule_AddObject(module, "_C_API", c_api_object);
810
811 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
812 if (crypto_Error == NULL)
813 goto error;
814 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
815 goto error;
816
817 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
818 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500819 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500820
821 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
822 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
823
824 dict = PyModule_GetDict(module);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400825#ifdef WITH_THREAD
826 if (!init_openssl_threads())
827 goto error;
828#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500829 if (!init_crypto_x509(dict))
830 goto error;
831 if (!init_crypto_x509name(dict))
832 goto error;
833 if (!init_crypto_x509store(dict))
834 goto error;
835 if (!init_crypto_x509req(dict))
836 goto error;
837 if (!init_crypto_pkey(dict))
838 goto error;
839 if (!init_crypto_x509extension(dict))
840 goto error;
841 if (!init_crypto_pkcs7(dict))
842 goto error;
843 if (!init_crypto_pkcs12(dict))
844 goto error;
845 if (!init_crypto_netscape_spki(dict))
846 goto error;
847
848error:
849 ;
850}
851