blob: dd279cf6ca20ef54d9bca5e765284ed67206c102 [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
James Yonan7c2e5d32010-02-27 05:45:50 -07005 * Copyright (C) Keyphrene 2004, All rights reserved
Jean-Paul Calderone88f38b22009-07-16 16:25:19 -04006 * Copyright (C) Jean-Paul Calderone 2008-2009, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 *
8 * Main file of crypto sub module.
9 * See the file RATIONALE for a short explanation of why this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
Rick Dean623ee362009-07-17 12:22:16 -050016#include "pkcs12.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017
18static char crypto_doc[] = "\n\
19Main file of crypto sub module.\n\
20See the file RATIONALE for a short explanation of why this module was written.\n\
21";
22
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050023void **ssl_API;
24
25PyObject *crypto_Error;
26
27static int
28global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
29{
30 PyObject *func, *argv, *ret;
31 int nchars;
32
33 func = (PyObject *)cb_arg;
34 argv = Py_BuildValue("(i)", rwflag);
35 ret = PyEval_CallObject(func, argv);
36 Py_DECREF(argv);
37 if (ret == NULL)
38 return 0;
39 if (!PyString_Check(ret))
40 {
41 PyErr_SetString(PyExc_ValueError, "String expected");
42 return 0;
43 }
44 nchars = PyString_Size(ret);
45 if (nchars > len)
46 nchars = len;
47 strncpy(buf, PyString_AsString(ret), nchars);
48 return nchars;
49}
50
51static char crypto_load_privatekey_doc[] = "\n\
52Load a private key from a buffer\n\
53\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040054@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
55@param buffer: The buffer the key is stored in\n\
56@param 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\
59\n\
60@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061";
62
63static PyObject *
64crypto_load_privatekey(PyObject *spam, PyObject *args)
65{
66 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
67 int type, len;
68 char *buffer;
69 PyObject *pw = NULL;
70 pem_password_cb *cb = NULL;
71 void *cb_arg = NULL;
72 BIO *bio;
73 EVP_PKEY *pkey;
74
75 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
76 return NULL;
77
78 if (pw != NULL)
79 {
80 if (PyString_Check(pw))
81 {
82 cb = NULL;
83 cb_arg = PyString_AsString(pw);
84 }
85 else if (PyCallable_Check(pw))
86 {
87 cb = global_passphrase_callback;
88 cb_arg = pw;
89 }
90 else
91 {
92 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
93 return NULL;
94 }
95 }
96
97 bio = BIO_new_mem_buf(buffer, len);
98 switch (type)
99 {
100 case X509_FILETYPE_PEM:
101 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
102 break;
103
104 case X509_FILETYPE_ASN1:
105 pkey = d2i_PrivateKey_bio(bio, NULL);
106 break;
107
108 default:
109 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
110 BIO_free(bio);
111 return NULL;
112 }
113 BIO_free(bio);
114
115 if (pkey == NULL)
116 {
Rick Deand369c932009-07-08 11:48:33 -0500117 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118 return NULL;
119 }
120
121 return (PyObject *)crypto_PKey_New(pkey, 1);
122}
123
124static char crypto_dump_privatekey_doc[] = "\n\
125Dump a private key to a buffer\n\
126\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400127@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
128@param pkey: The PKey to dump\n\
129@param cipher: (optional) if encrypted PEM format, the cipher to\n\
130 use\n\
131@param passphrase - (optional) if encrypted PEM format, this can be either\n\
132 the passphrase to use, or a callback for providing the\n\
133 passphrase.\n\
134@return: The buffer with the dumped key in\n\
135@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500136";
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);
Rick Deand369c932009-07-08 11:48:33 -0500218 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500219 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\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400232@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500233 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400234@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500235";
236
237static PyObject *
238crypto_load_certificate(PyObject *spam, PyObject *args)
239{
240 crypto_X509Obj *crypto_X509_New(X509 *, int);
241 int type, len;
242 char *buffer;
243 BIO *bio;
244 X509 *cert;
245
246 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
247 return NULL;
248
249 bio = BIO_new_mem_buf(buffer, len);
250 switch (type)
251 {
252 case X509_FILETYPE_PEM:
253 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
254 break;
255
256 case X509_FILETYPE_ASN1:
257 cert = d2i_X509_bio(bio, NULL);
258 break;
259
260 default:
261 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
262 BIO_free(bio);
263 return NULL;
264 }
265 BIO_free(bio);
266
267 if (cert == NULL)
268 {
Rick Deand369c932009-07-08 11:48:33 -0500269 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500270 return NULL;
271 }
272
273 return (PyObject *)crypto_X509_New(cert, 1);
274}
275
276static char crypto_dump_certificate_doc[] = "\n\
277Dump a certificate to a buffer\n\
278\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400279@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
280@param cert: The certificate to dump\n\
281@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500282";
283
284static PyObject *
285crypto_dump_certificate(PyObject *spam, PyObject *args)
286{
287 int type, ret, buf_len;
288 char *temp;
289 PyObject *buffer;
290 BIO *bio;
291 crypto_X509Obj *cert;
292
293 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
294 &crypto_X509_Type, &cert))
295 return NULL;
296
297 bio = BIO_new(BIO_s_mem());
298 switch (type)
299 {
300 case X509_FILETYPE_PEM:
301 ret = PEM_write_bio_X509(bio, cert->x509);
302 break;
303
304 case X509_FILETYPE_ASN1:
305 ret = i2d_X509_bio(bio, cert->x509);
306 break;
307
Rick Dean5b7b6372009-04-01 11:34:06 -0500308 case X509_FILETYPE_TEXT:
309 ret = X509_print_ex(bio, cert->x509, 0, 0);
310 break;
311
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500312 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500313 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500314 BIO_free(bio);
315 return NULL;
316 }
317
318 if (ret == 0)
319 {
320 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500321 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500322 return NULL;
323 }
324
325 buf_len = BIO_get_mem_data(bio, &temp);
326 buffer = PyString_FromStringAndSize(temp, buf_len);
327 BIO_free(bio);
328
329 return buffer;
330}
331
332static char crypto_load_certificate_request_doc[] = "\n\
333Load a certificate request from a buffer\n\
334\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400335@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500336 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400337@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500338";
339
340static PyObject *
341crypto_load_certificate_request(PyObject *spam, PyObject *args)
342{
343 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
344 int type, len;
345 char *buffer;
346 BIO *bio;
347 X509_REQ *req;
348
349 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
350 return NULL;
351
352 bio = BIO_new_mem_buf(buffer, len);
353 switch (type)
354 {
355 case X509_FILETYPE_PEM:
356 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
357 break;
358
359 case X509_FILETYPE_ASN1:
360 req = d2i_X509_REQ_bio(bio, NULL);
361 break;
362
363 default:
364 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
365 BIO_free(bio);
366 return NULL;
367 }
368 BIO_free(bio);
369
370 if (req == NULL)
371 {
Rick Deand369c932009-07-08 11:48:33 -0500372 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500373 return NULL;
374 }
375
376 return (PyObject *)crypto_X509Req_New(req, 1);
377}
378
379static char crypto_dump_certificate_request_doc[] = "\n\
380Dump a certificate request to a buffer\n\
381\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400382@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500383 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400384@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500385";
386
387static PyObject *
388crypto_dump_certificate_request(PyObject *spam, PyObject *args)
389{
390 int type, ret, buf_len;
391 char *temp;
392 PyObject *buffer;
393 BIO *bio;
394 crypto_X509ReqObj *req;
395
396 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
397 &crypto_X509Req_Type, &req))
398 return NULL;
399
400 bio = BIO_new(BIO_s_mem());
401 switch (type)
402 {
403 case X509_FILETYPE_PEM:
404 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
405 break;
406
407 case X509_FILETYPE_ASN1:
408 ret = i2d_X509_REQ_bio(bio, req->x509_req);
409 break;
410
Rick Dean5b7b6372009-04-01 11:34:06 -0500411 case X509_FILETYPE_TEXT:
412 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
413 break;
414
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500415 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500416 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500417 BIO_free(bio);
418 return NULL;
419 }
420
421 if (ret == 0)
422 {
423 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500424 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500425 return NULL;
426 }
427
428 buf_len = BIO_get_mem_data(bio, &temp);
429 buffer = PyString_FromStringAndSize(temp, buf_len);
430 BIO_free(bio);
431
432 return buffer;
433}
434
435static char crypto_load_pkcs7_data_doc[] = "\n\
436Load pkcs7 data from a buffer\n\
437\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400438@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500439 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400440@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500441";
442
443static PyObject *
444crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
445{
446 int type, len;
447 char *buffer;
448 BIO *bio;
449 PKCS7 *pkcs7 = NULL;
450
451 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
452 return NULL;
453
454 /*
455 * Try to read the pkcs7 data from the bio
456 */
457 bio = BIO_new_mem_buf(buffer, len);
458 switch (type)
459 {
460 case X509_FILETYPE_PEM:
461 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
462 break;
463
464 case X509_FILETYPE_ASN1:
465 pkcs7 = d2i_PKCS7_bio(bio, NULL);
466 break;
467
468 default:
469 PyErr_SetString(PyExc_ValueError,
470 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
471 return NULL;
472 }
473 BIO_free(bio);
474
475 /*
476 * Check if we got a PKCS7 structure
477 */
478 if (pkcs7 == NULL)
479 {
Rick Deand369c932009-07-08 11:48:33 -0500480 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500481 return NULL;
482 }
483
484 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
485}
486
487static char crypto_load_pkcs12_doc[] = "\n\
488Load a PKCS12 object from a buffer\n\
489\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400490@param buffer: The buffer the certificate is stored in\n\
491 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
492@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500493";
494
495static PyObject *
496crypto_load_pkcs12(PyObject *spam, PyObject *args)
497{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500498 int len;
499 char *buffer, *passphrase = NULL;
500 BIO *bio;
501 PKCS12 *p12;
502
503 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
504 return NULL;
505
506 bio = BIO_new_mem_buf(buffer, len);
507 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
508 {
509 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500510 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500511 return NULL;
512 }
513 BIO_free(bio);
514
515 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
516}
517
518
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500519static char crypto_X509_verify_cert_error_string_doc[] = "\n\
520Get X509 verify certificate error string.\n\
521\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400522@param errnum: The error number.\n\
523@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500524";
525
526static PyObject *
527crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
528{
529 int errnum;
530 const char *str;
531
532 if (!PyArg_ParseTuple(args, "i", &errnum))
533 return NULL;
534
535 str = X509_verify_cert_error_string(errnum);
536 return PyString_FromString(str);
537}
538
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400539static char crypto_exception_from_error_queue_doc[] = "\n\
540Raise an exception from the current OpenSSL error queue.\n\
541";
542
543static PyObject *
544crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
545 exception_from_error_queue(crypto_Error);
546 return NULL;
547}
548
James Yonan7c2e5d32010-02-27 05:45:50 -0700549static char crypto_sign_doc[] = "\n\
550Sign data with a digest\n\
551\n\
552@param pkey: Pkey to sign with\n\
553@param data: data to be signed\n\
554@param digest: message digest to use\n\
555@return: signature\n\
556";
557
558static PyObject *
559crypto_sign(PyObject *spam, PyObject *args)
560{
561 PyObject *buffer;
562 crypto_PKeyObj *pkey;
563 char *data = NULL;
564 char *digest_name;
565 int err;
566 unsigned int sig_len;
567 const EVP_MD *digest;
568 EVP_MD_CTX md_ctx;
569 unsigned char sig_buf[512];
570
571 if (!PyArg_ParseTuple(args, "O!ss:sign", &crypto_PKey_Type,
572 &pkey, &data, &digest_name))
573 return NULL;
574
575 if ((digest = EVP_get_digestbyname(digest_name)) == NULL)
576 {
577 PyErr_SetString(PyExc_ValueError, "No such digest method");
578 return NULL;
579 }
580
581 EVP_SignInit (&md_ctx, digest);
582 EVP_SignUpdate (&md_ctx, data, strlen(data));
583 sig_len = sizeof(sig_buf);
584 err = EVP_SignFinal (&md_ctx, sig_buf, &sig_len, pkey->pkey);
585
586 if (err != 1) {
587 exception_from_error_queue(crypto_Error);
588 return NULL;
589 }
590
591 buffer = PyString_FromStringAndSize(sig_buf, sig_len);
592 return buffer;
593}
594
595static char crypto_verify_doc[] = "\n\
596Verify a signature\n\
597\n\
598@param cert: signing certificate (X509 object)\n\
599@param signature: signature returned by sign function\n\
600@param data: data to be verified\n\
601@param digest: message digest to use\n\
602@return: None if the signature is correct, raise exception otherwise\n\
603";
604
605static PyObject *
606crypto_verify(PyObject *spam, PyObject *args)
607{
608 crypto_X509Obj *cert;
609 unsigned char *signature;
610 int sig_len;
611 char *data, *digest_name;
612 int err;
613 const EVP_MD *digest;
614 EVP_MD_CTX md_ctx;
615 EVP_PKEY *pkey;
616
617 if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len,
618 &data, &digest_name))
619 return NULL;
620
621 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
622 PyErr_SetString(PyExc_ValueError, "No such digest method");
623 return NULL;
624 }
625 pkey=X509_get_pubkey(cert->x509);
626 if (pkey == NULL) {
627 PyErr_SetString(PyExc_ValueError, "No public key");
628 return NULL;
629 }
630
631 EVP_VerifyInit (&md_ctx, digest);
632 EVP_VerifyUpdate (&md_ctx, data, strlen((char*)data));
633 err = EVP_VerifyFinal (&md_ctx, signature, sig_len, pkey);
634 EVP_PKEY_free (pkey);
635
636 if (err != 1) {
637 exception_from_error_queue(crypto_Error);
638 return NULL;
639 }
640
641 Py_INCREF(Py_None);
642 return Py_None;
643}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400644
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500645/* Methods in the OpenSSL.crypto module (i.e. none) */
646static PyMethodDef crypto_methods[] = {
647 /* Module functions */
648 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
649 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
650 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
651 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
652 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
653 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
654 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
655 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700656 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
657 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500658 { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400659 { "_exception_from_error_queue", (PyCFunction)crypto_exception_from_error_queue, METH_NOARGS, crypto_exception_from_error_queue_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500660 { NULL, NULL }
661};
662
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400663
664#ifdef WITH_THREAD
665
666#include <pythread.h>
667
668/**
669 * This array will store all of the mutexes available to OpenSSL.
670 */
671static PyThread_type_lock *mutex_buf = NULL;
672
673
674/**
675 * Callback function supplied to OpenSSL to acquire or release a lock.
676 *
677 */
678static void locking_function(int mode, int n, const char * file, int line) {
679 if (mode & CRYPTO_LOCK) {
680 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
681 } else {
682 PyThread_release_lock(mutex_buf[n]);
683 }
684}
685
686
687/**
688 * Initialize OpenSSL for use from multiple threads.
689 *
690 * Returns: 0 if initialization fails, 1 otherwise.
691 */
692static int init_openssl_threads(void) {
693 int i;
694
695 mutex_buf = (PyThread_type_lock *)malloc(
696 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
697 if (!mutex_buf) {
698 return 0;
699 }
700 for (i = 0; i < CRYPTO_num_locks(); ++i) {
701 mutex_buf[i] = PyThread_allocate_lock();
702 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500703 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400704 CRYPTO_set_locking_callback(locking_function);
705 return 1;
706}
707
708/* /\** */
709/* * Clean up after OpenSSL thread initialization. */
710/* *\/ */
711/* static int deinit_openssl_threads() { */
712/* int i; */
713
714/* if (!mutex_buf) { */
715/* return 0; */
716/* } */
717/* CRYPTO_set_id_callback(NULL); */
718/* CRYPTO_set_locking_callback(NULL); */
719/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
720/* PyThread_free_lock(mutex_buf[i]); */
721/* } */
722/* free(mutex_buf); */
723/* mutex_buf = NULL; */
724/* return 1; */
725/* } */
726
727#endif
728
729
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500730/*
731 * Initialize crypto sub module
732 *
733 * Arguments: None
734 * Returns: None
735 */
736void
737initcrypto(void)
738{
739 static void *crypto_API[crypto_API_pointers];
740 PyObject *c_api_object;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400741 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500742
743 ERR_load_crypto_strings();
744 OpenSSL_add_all_algorithms();
745
746 if ((module = Py_InitModule3("crypto", crypto_methods, crypto_doc)) == NULL)
747 return;
748
749 /* Initialize the C API pointer array */
750 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
751 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
752 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
753 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
754 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
755 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
756 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
757 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
758 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
759 if (c_api_object != NULL)
760 PyModule_AddObject(module, "_C_API", c_api_object);
761
762 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
763 if (crypto_Error == NULL)
764 goto error;
765 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
766 goto error;
767
768 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
769 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500770 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500771
772 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
773 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
774
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400775#ifdef WITH_THREAD
776 if (!init_openssl_threads())
777 goto error;
778#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400779 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500780 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400781 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500782 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400783 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500784 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400785 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500786 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400787 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500788 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400789 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500790 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400791 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500792 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400793 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500794 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400795 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500796 goto error;
797
798error:
799 ;
800}