blob: e12c72ac00e7628e30d353e86eff7f085dc0619b [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\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040052@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
53@param buffer: The buffer the key is stored in\n\
54@param passphrase: (optional) if encrypted PEM format, this can be\n\
55 either the passphrase to use, or a callback for\n\
56 providing the passphrase.\n\
57\n\
58@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050059";
60
61static PyObject *
62crypto_load_privatekey(PyObject *spam, PyObject *args)
63{
64 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
65 int type, len;
66 char *buffer;
67 PyObject *pw = NULL;
68 pem_password_cb *cb = NULL;
69 void *cb_arg = NULL;
70 BIO *bio;
71 EVP_PKEY *pkey;
72
73 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
74 return NULL;
75
76 if (pw != NULL)
77 {
78 if (PyString_Check(pw))
79 {
80 cb = NULL;
81 cb_arg = PyString_AsString(pw);
82 }
83 else if (PyCallable_Check(pw))
84 {
85 cb = global_passphrase_callback;
86 cb_arg = pw;
87 }
88 else
89 {
90 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
91 return NULL;
92 }
93 }
94
95 bio = BIO_new_mem_buf(buffer, len);
96 switch (type)
97 {
98 case X509_FILETYPE_PEM:
99 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
100 break;
101
102 case X509_FILETYPE_ASN1:
103 pkey = d2i_PrivateKey_bio(bio, NULL);
104 break;
105
106 default:
107 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
108 BIO_free(bio);
109 return NULL;
110 }
111 BIO_free(bio);
112
113 if (pkey == NULL)
114 {
115 exception_from_error_queue();
116 return NULL;
117 }
118
119 return (PyObject *)crypto_PKey_New(pkey, 1);
120}
121
122static char crypto_dump_privatekey_doc[] = "\n\
123Dump a private key to a buffer\n\
124\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400125@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
126@param pkey: The PKey to dump\n\
127@param cipher: (optional) if encrypted PEM format, the cipher to\n\
128 use\n\
129@param passphrase - (optional) if encrypted PEM format, this can be either\n\
130 the passphrase to use, or a callback for providing the\n\
131 passphrase.\n\
132@return: The buffer with the dumped key in\n\
133@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500134";
135
136static PyObject *
137crypto_dump_privatekey(PyObject *spam, PyObject *args)
138{
139 int type, ret, buf_len;
140 char *temp;
141 PyObject *buffer;
142 char *cipher_name = NULL;
143 const EVP_CIPHER *cipher = NULL;
144 PyObject *pw = NULL;
145 pem_password_cb *cb = NULL;
146 void *cb_arg = NULL;
147 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500148 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500149 crypto_PKeyObj *pkey;
150
151 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
152 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
153 return NULL;
154
155 if (cipher_name != NULL && pw == NULL)
156 {
157 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
158 return NULL;
159 }
160 if (cipher_name != NULL)
161 {
162 cipher = EVP_get_cipherbyname(cipher_name);
163 if (cipher == NULL)
164 {
165 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
166 return NULL;
167 }
168 if (PyString_Check(pw))
169 {
170 cb = NULL;
171 cb_arg = PyString_AsString(pw);
172 }
173 else if (PyCallable_Check(pw))
174 {
175 cb = global_passphrase_callback;
176 cb_arg = pw;
177 }
178 else
179 {
180 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
181 return NULL;
182 }
183 }
184
185 bio = BIO_new(BIO_s_mem());
186 switch (type)
187 {
188 case X509_FILETYPE_PEM:
189 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
190 if (PyErr_Occurred())
191 {
192 BIO_free(bio);
193 return NULL;
194 }
195 break;
196
197 case X509_FILETYPE_ASN1:
198 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
199 break;
200
Rick Dean5b7b6372009-04-01 11:34:06 -0500201 case X509_FILETYPE_TEXT:
202 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
203 ret = RSA_print(bio, rsa, 0);
204 RSA_free(rsa);
205 break;
206
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500207 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500208 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500209 BIO_free(bio);
210 return NULL;
211 }
212
213 if (ret == 0)
214 {
215 BIO_free(bio);
216 exception_from_error_queue();
217 return NULL;
218 }
219
220 buf_len = BIO_get_mem_data(bio, &temp);
221 buffer = PyString_FromStringAndSize(temp, buf_len);
222 BIO_free(bio);
223
224 return buffer;
225}
226
227static char crypto_load_certificate_doc[] = "\n\
228Load a certificate from a buffer\n\
229\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400230@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500231 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400232@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500233";
234
235static PyObject *
236crypto_load_certificate(PyObject *spam, PyObject *args)
237{
238 crypto_X509Obj *crypto_X509_New(X509 *, int);
239 int type, len;
240 char *buffer;
241 BIO *bio;
242 X509 *cert;
243
244 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
245 return NULL;
246
247 bio = BIO_new_mem_buf(buffer, len);
248 switch (type)
249 {
250 case X509_FILETYPE_PEM:
251 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
252 break;
253
254 case X509_FILETYPE_ASN1:
255 cert = d2i_X509_bio(bio, NULL);
256 break;
257
258 default:
259 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
260 BIO_free(bio);
261 return NULL;
262 }
263 BIO_free(bio);
264
265 if (cert == NULL)
266 {
267 exception_from_error_queue();
268 return NULL;
269 }
270
271 return (PyObject *)crypto_X509_New(cert, 1);
272}
273
274static char crypto_dump_certificate_doc[] = "\n\
275Dump a certificate to a buffer\n\
276\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400277@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
278@param cert: The certificate to dump\n\
279@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500280";
281
282static PyObject *
283crypto_dump_certificate(PyObject *spam, PyObject *args)
284{
285 int type, ret, buf_len;
286 char *temp;
287 PyObject *buffer;
288 BIO *bio;
289 crypto_X509Obj *cert;
290
291 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
292 &crypto_X509_Type, &cert))
293 return NULL;
294
295 bio = BIO_new(BIO_s_mem());
296 switch (type)
297 {
298 case X509_FILETYPE_PEM:
299 ret = PEM_write_bio_X509(bio, cert->x509);
300 break;
301
302 case X509_FILETYPE_ASN1:
303 ret = i2d_X509_bio(bio, cert->x509);
304 break;
305
Rick Dean5b7b6372009-04-01 11:34:06 -0500306 case X509_FILETYPE_TEXT:
307 ret = X509_print_ex(bio, cert->x509, 0, 0);
308 break;
309
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500310 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500311 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500312 BIO_free(bio);
313 return NULL;
314 }
315
316 if (ret == 0)
317 {
318 BIO_free(bio);
319 exception_from_error_queue();
320 return NULL;
321 }
322
323 buf_len = BIO_get_mem_data(bio, &temp);
324 buffer = PyString_FromStringAndSize(temp, buf_len);
325 BIO_free(bio);
326
327 return buffer;
328}
329
330static char crypto_load_certificate_request_doc[] = "\n\
331Load a certificate request from a buffer\n\
332\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400333@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500334 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400335@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500336";
337
338static PyObject *
339crypto_load_certificate_request(PyObject *spam, PyObject *args)
340{
341 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
342 int type, len;
343 char *buffer;
344 BIO *bio;
345 X509_REQ *req;
346
347 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
348 return NULL;
349
350 bio = BIO_new_mem_buf(buffer, len);
351 switch (type)
352 {
353 case X509_FILETYPE_PEM:
354 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
355 break;
356
357 case X509_FILETYPE_ASN1:
358 req = d2i_X509_REQ_bio(bio, NULL);
359 break;
360
361 default:
362 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
363 BIO_free(bio);
364 return NULL;
365 }
366 BIO_free(bio);
367
368 if (req == NULL)
369 {
370 exception_from_error_queue();
371 return NULL;
372 }
373
374 return (PyObject *)crypto_X509Req_New(req, 1);
375}
376
377static char crypto_dump_certificate_request_doc[] = "\n\
378Dump a certificate request to a buffer\n\
379\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400380@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500381 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400382@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500383";
384
385static PyObject *
386crypto_dump_certificate_request(PyObject *spam, PyObject *args)
387{
388 int type, ret, buf_len;
389 char *temp;
390 PyObject *buffer;
391 BIO *bio;
392 crypto_X509ReqObj *req;
393
394 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
395 &crypto_X509Req_Type, &req))
396 return NULL;
397
398 bio = BIO_new(BIO_s_mem());
399 switch (type)
400 {
401 case X509_FILETYPE_PEM:
402 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
403 break;
404
405 case X509_FILETYPE_ASN1:
406 ret = i2d_X509_REQ_bio(bio, req->x509_req);
407 break;
408
Rick Dean5b7b6372009-04-01 11:34:06 -0500409 case X509_FILETYPE_TEXT:
410 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
411 break;
412
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500413 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500414 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500415 BIO_free(bio);
416 return NULL;
417 }
418
419 if (ret == 0)
420 {
421 BIO_free(bio);
422 exception_from_error_queue();
423 return NULL;
424 }
425
426 buf_len = BIO_get_mem_data(bio, &temp);
427 buffer = PyString_FromStringAndSize(temp, buf_len);
428 BIO_free(bio);
429
430 return buffer;
431}
432
433static char crypto_load_pkcs7_data_doc[] = "\n\
434Load pkcs7 data from a buffer\n\
435\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400436@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500437 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400438@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500439";
440
441static PyObject *
442crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
443{
444 int type, len;
445 char *buffer;
446 BIO *bio;
447 PKCS7 *pkcs7 = NULL;
448
449 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
450 return NULL;
451
452 /*
453 * Try to read the pkcs7 data from the bio
454 */
455 bio = BIO_new_mem_buf(buffer, len);
456 switch (type)
457 {
458 case X509_FILETYPE_PEM:
459 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
460 break;
461
462 case X509_FILETYPE_ASN1:
463 pkcs7 = d2i_PKCS7_bio(bio, NULL);
464 break;
465
466 default:
467 PyErr_SetString(PyExc_ValueError,
468 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
469 return NULL;
470 }
471 BIO_free(bio);
472
473 /*
474 * Check if we got a PKCS7 structure
475 */
476 if (pkcs7 == NULL)
477 {
478 exception_from_error_queue();
479 return NULL;
480 }
481
482 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
483}
484
485static char crypto_load_pkcs12_doc[] = "\n\
486Load a PKCS12 object from a buffer\n\
487\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400488@param buffer: The buffer the certificate is stored in\n\
489 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
490@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500491";
492
493static PyObject *
494crypto_load_pkcs12(PyObject *spam, PyObject *args)
495{
496 crypto_PKCS12Obj *crypto_PKCS12_New(PKCS12 *, char *);
497 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);
509 exception_from_error_queue();
510 return NULL;
511 }
512 BIO_free(bio);
513
514 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
515}
516
517
518static char crypto_X509_doc[] = "\n\
519The factory function inserted in the module dictionary to create X509\n\
520objects\n\
521\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400522@returns: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500523";
524
525static PyObject *
526crypto_X509(PyObject *spam, PyObject *args)
527{
528 if (!PyArg_ParseTuple(args, ":X509"))
529 return NULL;
530
531 return (PyObject *)crypto_X509_New(X509_new(), 1);
532}
533
534static char crypto_X509Name_doc[] = "\n\
535The factory function inserted in the module dictionary as a copy\n\
536constructor for X509Name objects.\n\
537\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400538@param name: An X509Name object to copy\n\
539@return: The X509Name object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500540";
541
542static PyObject *
543crypto_X509Name(PyObject *spam, PyObject *args)
544{
545 crypto_X509NameObj *name;
546
547 if (!PyArg_ParseTuple(args, "O!:X509Name", &crypto_X509Name_Type, &name))
548 return NULL;
549
550 return (PyObject *)crypto_X509Name_New(X509_NAME_dup(name->x509_name), 1);
551}
552
553static char crypto_X509Req_doc[] = "\n\
554The factory function inserted in the module dictionary to create X509Req\n\
555objects\n\
556\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400557@returns: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500558";
559
560static PyObject *
561crypto_X509Req(PyObject *spam, PyObject *args)
562{
563 if (!PyArg_ParseTuple(args, ":X509Req"))
564 return NULL;
565
566 return (PyObject *)crypto_X509Req_New(X509_REQ_new(), 1);
567}
568
569static char crypto_PKey_doc[] = "\n\
570The factory function inserted in the module dictionary to create PKey\n\
571objects\n\
572\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400573@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500574";
575
576static PyObject *
577crypto_PKey(PyObject *spam, PyObject *args)
578{
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400579 crypto_PKeyObj *py_pkey;
580
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500581 if (!PyArg_ParseTuple(args, ":PKey"))
582 return NULL;
583
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400584 py_pkey = crypto_PKey_New(EVP_PKEY_new(), 1);
585 if (py_pkey) {
586 py_pkey->initialized = 0;
587 }
Jean-Paul Calderonef60beec2008-07-22 21:19:02 -0400588 return (PyObject *)py_pkey;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500589}
590
591static char crypto_X509Extension_doc[] = "\n\
592The factory function inserted in the module dictionary to create\n\
593X509Extension objects.\n\
594\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400595@param typename: The name of the extension to create.\n\
596@type typename: C{str}\n\
597@param critical: A flag indicating whether this is a critical extension.\n\
598@param value: The value of the extension.\n\
599@type value: C{str}\n\
600@return: The X509Extension object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500601";
602
603static PyObject *
604crypto_X509Extension(PyObject *spam, PyObject *args)
605{
606 char *type_name, *value;
607 int critical;
608
609 if (!PyArg_ParseTuple(args, "sis:X509Extension", &type_name, &critical,
610 &value))
611 return NULL;
612
613 return (PyObject *)crypto_X509Extension_New(type_name, critical, value);
614}
615
616static char crypto_NetscapeSPKI_doc[] = "\n\
617The factory function inserted in the module dictionary to create NetscapeSPKI\n\
618objects\n\
619\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400620@param enc: Base64 encoded NetscapeSPKI object.\n\
621@type enc: C{str}\n\
622@return: The NetscapeSPKI object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500623";
624
625static PyObject *
626crypto_NetscapeSPKI(PyObject *spam, PyObject *args)
627{
628 char *enc = NULL;
629 int enc_len = -1;
630 NETSCAPE_SPKI *spki;
631
632 if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
633 return NULL;
634
635 if (enc_len >= 0)
636 spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
637 else
638 spki = NETSCAPE_SPKI_new();
639 if (spki == NULL)
640 {
641 exception_from_error_queue();
642 return NULL;
643 }
644 return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
645}
646
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500647static char crypto_X509_verify_cert_error_string_doc[] = "\n\
648Get X509 verify certificate error string.\n\
649\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400650@param errnum: The error number.\n\
651@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500652";
653
654static PyObject *
655crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
656{
657 int errnum;
658 const char *str;
659
660 if (!PyArg_ParseTuple(args, "i", &errnum))
661 return NULL;
662
663 str = X509_verify_cert_error_string(errnum);
664 return PyString_FromString(str);
665}
666
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500667/* Methods in the OpenSSL.crypto module (i.e. none) */
668static PyMethodDef crypto_methods[] = {
669 /* Module functions */
670 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
671 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
672 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
673 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
674 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
675 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
676 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
677 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
678 /* Factory functions */
679 { "X509", (PyCFunction)crypto_X509, METH_VARARGS, crypto_X509_doc },
680 { "X509Name",(PyCFunction)crypto_X509Name,METH_VARARGS, crypto_X509Name_doc },
681 { "X509Req", (PyCFunction)crypto_X509Req, METH_VARARGS, crypto_X509Req_doc },
682 { "PKey", (PyCFunction)crypto_PKey, METH_VARARGS, crypto_PKey_doc },
683 { "X509Extension", (PyCFunction)crypto_X509Extension, METH_VARARGS, crypto_X509Extension_doc },
684 { "NetscapeSPKI", (PyCFunction)crypto_NetscapeSPKI, METH_VARARGS, crypto_NetscapeSPKI_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500685 { "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 -0500686 { NULL, NULL }
687};
688
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400689
690#ifdef WITH_THREAD
691
692#include <pythread.h>
693
694/**
695 * This array will store all of the mutexes available to OpenSSL.
696 */
697static PyThread_type_lock *mutex_buf = NULL;
698
699
700/**
701 * Callback function supplied to OpenSSL to acquire or release a lock.
702 *
703 */
704static void locking_function(int mode, int n, const char * file, int line) {
705 if (mode & CRYPTO_LOCK) {
706 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
707 } else {
708 PyThread_release_lock(mutex_buf[n]);
709 }
710}
711
712
713/**
714 * Initialize OpenSSL for use from multiple threads.
715 *
716 * Returns: 0 if initialization fails, 1 otherwise.
717 */
718static int init_openssl_threads(void) {
719 int i;
720
721 mutex_buf = (PyThread_type_lock *)malloc(
722 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
723 if (!mutex_buf) {
724 return 0;
725 }
726 for (i = 0; i < CRYPTO_num_locks(); ++i) {
727 mutex_buf[i] = PyThread_allocate_lock();
728 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500729 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400730 CRYPTO_set_locking_callback(locking_function);
731 return 1;
732}
733
734/* /\** */
735/* * Clean up after OpenSSL thread initialization. */
736/* *\/ */
737/* static int deinit_openssl_threads() { */
738/* int i; */
739
740/* if (!mutex_buf) { */
741/* return 0; */
742/* } */
743/* CRYPTO_set_id_callback(NULL); */
744/* CRYPTO_set_locking_callback(NULL); */
745/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
746/* PyThread_free_lock(mutex_buf[i]); */
747/* } */
748/* free(mutex_buf); */
749/* mutex_buf = NULL; */
750/* return 1; */
751/* } */
752
753#endif
754
755
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500756/*
757 * Initialize crypto sub module
758 *
759 * Arguments: None
760 * Returns: None
761 */
762void
763initcrypto(void)
764{
765 static void *crypto_API[crypto_API_pointers];
766 PyObject *c_api_object;
767 PyObject *module, *dict;
768
769 ERR_load_crypto_strings();
770 OpenSSL_add_all_algorithms();
771
772 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
773 return;
774
775 /* Initialize the C API pointer array */
776 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
777 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
778 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
779 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
780 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
781 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
782 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
783 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
784 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
785 if (c_api_object != NULL)
786 PyModule_AddObject(module, "_C_API", c_api_object);
787
788 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
789 if (crypto_Error == NULL)
790 goto error;
791 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
792 goto error;
793
794 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
795 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500796 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500797
798 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
799 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
800
801 dict = PyModule_GetDict(module);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400802#ifdef WITH_THREAD
803 if (!init_openssl_threads())
804 goto error;
805#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500806 if (!init_crypto_x509(dict))
807 goto error;
808 if (!init_crypto_x509name(dict))
809 goto error;
810 if (!init_crypto_x509store(dict))
811 goto error;
812 if (!init_crypto_x509req(dict))
813 goto error;
814 if (!init_crypto_pkey(dict))
815 goto error;
816 if (!init_crypto_x509extension(dict))
817 goto error;
818 if (!init_crypto_pkcs7(dict))
819 goto error;
820 if (!init_crypto_pkcs12(dict))
821 goto error;
822 if (!init_crypto_netscape_spki(dict))
823 goto error;
824
825error:
826 ;
827}
828