blob: a81773d4937346ebb86ccbad05c45ea2ccff1bf0 [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
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -040027int crypto_byte_converter(PyObject *input, void* output) {
28 char **message = output;
29 if (input == Py_None) {
30 *message = NULL;
31 } else if (PyBytes_CheckExact(input)) {
32 *message = PyBytes_AsString(input);
33 } else {
34 return 0;
35 }
36 return 1;
37}
38
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050039static int
40global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
41{
42 PyObject *func, *argv, *ret;
43 int nchars;
44
45 func = (PyObject *)cb_arg;
46 argv = Py_BuildValue("(i)", rwflag);
47 ret = PyEval_CallObject(func, argv);
48 Py_DECREF(argv);
49 if (ret == NULL)
50 return 0;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040051 if (!PyBytes_Check(ret))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050052 {
53 PyErr_SetString(PyExc_ValueError, "String expected");
54 return 0;
55 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040056 nchars = PyBytes_Size(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050057 if (nchars > len)
58 nchars = len;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040059 strncpy(buf, PyBytes_AsString(ret), nchars);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050060 return nchars;
61}
62
63static char crypto_load_privatekey_doc[] = "\n\
64Load a private key from a buffer\n\
65\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040066@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
67@param buffer: The buffer the key is stored in\n\
68@param passphrase: (optional) if encrypted PEM format, this can be\n\
69 either the passphrase to use, or a callback for\n\
70 providing the passphrase.\n\
71\n\
72@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050073";
74
75static PyObject *
76crypto_load_privatekey(PyObject *spam, PyObject *args)
77{
78 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
79 int type, len;
80 char *buffer;
81 PyObject *pw = NULL;
82 pem_password_cb *cb = NULL;
83 void *cb_arg = NULL;
84 BIO *bio;
85 EVP_PKEY *pkey;
86
87 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
88 return NULL;
89
90 if (pw != NULL)
91 {
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040092 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050093 {
94 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040095 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050096 }
97 else if (PyCallable_Check(pw))
98 {
99 cb = global_passphrase_callback;
100 cb_arg = pw;
101 }
102 else
103 {
104 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
105 return NULL;
106 }
107 }
108
109 bio = BIO_new_mem_buf(buffer, len);
110 switch (type)
111 {
112 case X509_FILETYPE_PEM:
113 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
114 break;
115
116 case X509_FILETYPE_ASN1:
117 pkey = d2i_PrivateKey_bio(bio, NULL);
118 break;
119
120 default:
121 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
122 BIO_free(bio);
123 return NULL;
124 }
125 BIO_free(bio);
126
127 if (pkey == NULL)
128 {
Rick Deand369c932009-07-08 11:48:33 -0500129 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500130 return NULL;
131 }
132
133 return (PyObject *)crypto_PKey_New(pkey, 1);
134}
135
136static char crypto_dump_privatekey_doc[] = "\n\
137Dump a private key to a buffer\n\
138\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400139@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
140@param pkey: The PKey to dump\n\
141@param cipher: (optional) if encrypted PEM format, the cipher to\n\
142 use\n\
143@param passphrase - (optional) if encrypted PEM format, this can be either\n\
144 the passphrase to use, or a callback for providing the\n\
145 passphrase.\n\
146@return: The buffer with the dumped key in\n\
147@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500148";
149
150static PyObject *
151crypto_dump_privatekey(PyObject *spam, PyObject *args)
152{
153 int type, ret, buf_len;
154 char *temp;
155 PyObject *buffer;
156 char *cipher_name = NULL;
157 const EVP_CIPHER *cipher = NULL;
158 PyObject *pw = NULL;
159 pem_password_cb *cb = NULL;
160 void *cb_arg = NULL;
161 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500162 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500163 crypto_PKeyObj *pkey;
164
165 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
166 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
167 return NULL;
168
169 if (cipher_name != NULL && pw == NULL)
170 {
171 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
172 return NULL;
173 }
174 if (cipher_name != NULL)
175 {
176 cipher = EVP_get_cipherbyname(cipher_name);
177 if (cipher == NULL)
178 {
179 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
180 return NULL;
181 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400182 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500183 {
184 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400185 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500186 }
187 else if (PyCallable_Check(pw))
188 {
189 cb = global_passphrase_callback;
190 cb_arg = pw;
191 }
192 else
193 {
194 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
195 return NULL;
196 }
197 }
198
199 bio = BIO_new(BIO_s_mem());
200 switch (type)
201 {
202 case X509_FILETYPE_PEM:
203 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
204 if (PyErr_Occurred())
205 {
206 BIO_free(bio);
207 return NULL;
208 }
209 break;
210
211 case X509_FILETYPE_ASN1:
212 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
213 break;
214
Rick Dean5b7b6372009-04-01 11:34:06 -0500215 case X509_FILETYPE_TEXT:
216 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
217 ret = RSA_print(bio, rsa, 0);
218 RSA_free(rsa);
219 break;
220
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500221 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500222 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500223 BIO_free(bio);
224 return NULL;
225 }
226
227 if (ret == 0)
228 {
229 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500230 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500231 return NULL;
232 }
233
234 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400235 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500236 BIO_free(bio);
237
238 return buffer;
239}
240
241static char crypto_load_certificate_doc[] = "\n\
242Load a certificate from a buffer\n\
243\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400244@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500245 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400246@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500247";
248
249static PyObject *
250crypto_load_certificate(PyObject *spam, PyObject *args)
251{
252 crypto_X509Obj *crypto_X509_New(X509 *, int);
253 int type, len;
254 char *buffer;
255 BIO *bio;
256 X509 *cert;
257
258 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
259 return NULL;
260
261 bio = BIO_new_mem_buf(buffer, len);
262 switch (type)
263 {
264 case X509_FILETYPE_PEM:
265 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
266 break;
267
268 case X509_FILETYPE_ASN1:
269 cert = d2i_X509_bio(bio, NULL);
270 break;
271
272 default:
273 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
274 BIO_free(bio);
275 return NULL;
276 }
277 BIO_free(bio);
278
279 if (cert == NULL)
280 {
Rick Deand369c932009-07-08 11:48:33 -0500281 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500282 return NULL;
283 }
284
285 return (PyObject *)crypto_X509_New(cert, 1);
286}
287
288static char crypto_dump_certificate_doc[] = "\n\
289Dump a certificate to a buffer\n\
290\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400291@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
292@param cert: The certificate to dump\n\
293@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500294";
295
296static PyObject *
297crypto_dump_certificate(PyObject *spam, PyObject *args)
298{
299 int type, ret, buf_len;
300 char *temp;
301 PyObject *buffer;
302 BIO *bio;
303 crypto_X509Obj *cert;
304
305 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
306 &crypto_X509_Type, &cert))
307 return NULL;
308
309 bio = BIO_new(BIO_s_mem());
310 switch (type)
311 {
312 case X509_FILETYPE_PEM:
313 ret = PEM_write_bio_X509(bio, cert->x509);
314 break;
315
316 case X509_FILETYPE_ASN1:
317 ret = i2d_X509_bio(bio, cert->x509);
318 break;
319
Rick Dean5b7b6372009-04-01 11:34:06 -0500320 case X509_FILETYPE_TEXT:
321 ret = X509_print_ex(bio, cert->x509, 0, 0);
322 break;
323
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500324 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500325 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500326 BIO_free(bio);
327 return NULL;
328 }
329
330 if (ret == 0)
331 {
332 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500333 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500334 return NULL;
335 }
336
337 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400338 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500339 BIO_free(bio);
340
341 return buffer;
342}
343
344static char crypto_load_certificate_request_doc[] = "\n\
345Load a certificate request from a buffer\n\
346\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400347@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500348 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400349@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500350";
351
352static PyObject *
353crypto_load_certificate_request(PyObject *spam, PyObject *args)
354{
355 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
356 int type, len;
357 char *buffer;
358 BIO *bio;
359 X509_REQ *req;
360
361 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
362 return NULL;
363
364 bio = BIO_new_mem_buf(buffer, len);
365 switch (type)
366 {
367 case X509_FILETYPE_PEM:
368 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
369 break;
370
371 case X509_FILETYPE_ASN1:
372 req = d2i_X509_REQ_bio(bio, NULL);
373 break;
374
375 default:
376 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
377 BIO_free(bio);
378 return NULL;
379 }
380 BIO_free(bio);
381
382 if (req == NULL)
383 {
Rick Deand369c932009-07-08 11:48:33 -0500384 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500385 return NULL;
386 }
387
388 return (PyObject *)crypto_X509Req_New(req, 1);
389}
390
391static char crypto_dump_certificate_request_doc[] = "\n\
392Dump a certificate request to a buffer\n\
393\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400394@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500395 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400396@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500397";
398
399static PyObject *
400crypto_dump_certificate_request(PyObject *spam, PyObject *args)
401{
402 int type, ret, buf_len;
403 char *temp;
404 PyObject *buffer;
405 BIO *bio;
406 crypto_X509ReqObj *req;
407
408 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
409 &crypto_X509Req_Type, &req))
410 return NULL;
411
412 bio = BIO_new(BIO_s_mem());
413 switch (type)
414 {
415 case X509_FILETYPE_PEM:
416 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
417 break;
418
419 case X509_FILETYPE_ASN1:
420 ret = i2d_X509_REQ_bio(bio, req->x509_req);
421 break;
422
Rick Dean5b7b6372009-04-01 11:34:06 -0500423 case X509_FILETYPE_TEXT:
424 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
425 break;
426
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500427 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500428 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500429 BIO_free(bio);
430 return NULL;
431 }
432
433 if (ret == 0)
434 {
435 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500436 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500437 return NULL;
438 }
439
440 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400441 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500442 BIO_free(bio);
443
444 return buffer;
445}
446
Rick Dean536ba022009-07-24 23:57:27 -0500447static char crypto_load_crl_doc[] = "\n\
448Load a certificate revocation list from a buffer\n\
449\n\
450@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
451@param buffer: The buffer the CRL is stored in\n\
452\n\
453@return: The PKey object\n\
454";
455
456static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400457crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500458 int type, len;
459 char *buffer;
460 BIO *bio;
461 X509_CRL *crl;
462
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400463 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500464 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400465 }
Rick Dean536ba022009-07-24 23:57:27 -0500466
467 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400468 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500469 case X509_FILETYPE_PEM:
470 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
471 break;
472
473 case X509_FILETYPE_ASN1:
474 crl = d2i_X509_CRL_bio(bio, NULL);
475 break;
476
477 default:
478 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
479 BIO_free(bio);
480 return NULL;
481 }
482 BIO_free(bio);
483
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400484 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500485 exception_from_error_queue(crypto_Error);
486 return NULL;
487 }
488
489 return (PyObject *)crypto_CRL_New(crl);
490}
491
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500492static char crypto_load_pkcs7_data_doc[] = "\n\
493Load pkcs7 data from a buffer\n\
494\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400495@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500496 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400497@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500498";
499
500static PyObject *
501crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
502{
503 int type, len;
504 char *buffer;
505 BIO *bio;
506 PKCS7 *pkcs7 = NULL;
507
508 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
509 return NULL;
510
511 /*
512 * Try to read the pkcs7 data from the bio
513 */
514 bio = BIO_new_mem_buf(buffer, len);
515 switch (type)
516 {
517 case X509_FILETYPE_PEM:
518 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
519 break;
520
521 case X509_FILETYPE_ASN1:
522 pkcs7 = d2i_PKCS7_bio(bio, NULL);
523 break;
524
525 default:
526 PyErr_SetString(PyExc_ValueError,
527 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
528 return NULL;
529 }
530 BIO_free(bio);
531
532 /*
533 * Check if we got a PKCS7 structure
534 */
535 if (pkcs7 == NULL)
536 {
Rick Deand369c932009-07-08 11:48:33 -0500537 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500538 return NULL;
539 }
540
541 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
542}
543
544static char crypto_load_pkcs12_doc[] = "\n\
545Load a PKCS12 object from a buffer\n\
546\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400547@param buffer: The buffer the certificate is stored in\n\
548 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
549@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500550";
551
552static PyObject *
553crypto_load_pkcs12(PyObject *spam, PyObject *args)
554{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500555 int len;
556 char *buffer, *passphrase = NULL;
557 BIO *bio;
558 PKCS12 *p12;
559
560 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
561 return NULL;
562
563 bio = BIO_new_mem_buf(buffer, len);
564 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
565 {
566 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500567 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500568 return NULL;
569 }
570 BIO_free(bio);
571
572 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
573}
574
575
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500576static char crypto_X509_verify_cert_error_string_doc[] = "\n\
577Get X509 verify certificate error string.\n\
578\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400579@param errnum: The error number.\n\
580@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500581";
582
583static PyObject *
584crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
585{
586 int errnum;
587 const char *str;
588
589 if (!PyArg_ParseTuple(args, "i", &errnum))
590 return NULL;
591
592 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400593 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500594}
595
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400596static char crypto_exception_from_error_queue_doc[] = "\n\
597Raise an exception from the current OpenSSL error queue.\n\
598";
599
600static PyObject *
601crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
602 exception_from_error_queue(crypto_Error);
603 return NULL;
604}
605
James Yonan7c2e5d32010-02-27 05:45:50 -0700606static char crypto_sign_doc[] = "\n\
607Sign data with a digest\n\
608\n\
609@param pkey: Pkey to sign with\n\
610@param data: data to be signed\n\
611@param digest: message digest to use\n\
612@return: signature\n\
613";
614
615static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400616crypto_sign(PyObject *spam, PyObject *args) {
617 PyObject *buffer;
618 crypto_PKeyObj *pkey;
619 char *data = NULL;
620 char *digest_name;
621 int err;
622 unsigned int sig_len;
623 const EVP_MD *digest;
624 EVP_MD_CTX md_ctx;
625 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700626
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400627 if (!PyArg_ParseTuple(
628 args, "O!" BYTESTRING_FMT BYTESTRING_FMT ":sign", &crypto_PKey_Type,
629 &pkey, &data, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400630 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700631 }
632
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400633 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
634 PyErr_SetString(PyExc_ValueError, "No such digest method");
635 return NULL;
636 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700637
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400638 EVP_SignInit(&md_ctx, digest);
639 EVP_SignUpdate(&md_ctx, data, strlen(data));
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400640 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400641 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700642
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400643 if (err != 1) {
644 exception_from_error_queue(crypto_Error);
645 return NULL;
646 }
647
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400648 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400649 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700650}
651
652static char crypto_verify_doc[] = "\n\
653Verify a signature\n\
654\n\
655@param cert: signing certificate (X509 object)\n\
656@param signature: signature returned by sign function\n\
657@param data: data to be verified\n\
658@param digest: message digest to use\n\
659@return: None if the signature is correct, raise exception otherwise\n\
660";
661
662static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400663crypto_verify(PyObject *spam, PyObject *args) {
664 crypto_X509Obj *cert;
665 unsigned char *signature;
666 int sig_len;
667 char *data, *digest_name;
668 int err;
669 const EVP_MD *digest;
670 EVP_MD_CTX md_ctx;
671 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700672
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400673#ifdef PY3
674 if (!PyArg_ParseTuple(args, "O!y#yy:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
675#else
676 if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
677#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400678 return NULL;
679 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700680
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400681 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
682 PyErr_SetString(PyExc_ValueError, "No such digest method");
683 return NULL;
684 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700685
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400686 pkey = X509_get_pubkey(cert->x509);
687 if (pkey == NULL) {
688 PyErr_SetString(PyExc_ValueError, "No public key");
689 return NULL;
690 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700691
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400692 EVP_VerifyInit(&md_ctx, digest);
693 EVP_VerifyUpdate(&md_ctx, data, strlen((char*)data));
694 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
695 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700696
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400697 if (err != 1) {
698 exception_from_error_queue(crypto_Error);
699 return NULL;
700 }
701
702 Py_INCREF(Py_None);
703 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700704}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400705
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500706/* Methods in the OpenSSL.crypto module (i.e. none) */
707static PyMethodDef crypto_methods[] = {
708 /* Module functions */
709 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
710 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
711 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
712 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
713 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
714 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500715 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500716 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
717 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700718 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
719 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500720 { "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 -0400721 { "_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 -0500722 { NULL, NULL }
723};
724
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400725
726#ifdef WITH_THREAD
727
728#include <pythread.h>
729
730/**
731 * This array will store all of the mutexes available to OpenSSL.
732 */
733static PyThread_type_lock *mutex_buf = NULL;
734
735
736/**
737 * Callback function supplied to OpenSSL to acquire or release a lock.
738 *
739 */
740static void locking_function(int mode, int n, const char * file, int line) {
741 if (mode & CRYPTO_LOCK) {
742 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
743 } else {
744 PyThread_release_lock(mutex_buf[n]);
745 }
746}
747
748
749/**
750 * Initialize OpenSSL for use from multiple threads.
751 *
752 * Returns: 0 if initialization fails, 1 otherwise.
753 */
754static int init_openssl_threads(void) {
755 int i;
756
757 mutex_buf = (PyThread_type_lock *)malloc(
758 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
759 if (!mutex_buf) {
760 return 0;
761 }
762 for (i = 0; i < CRYPTO_num_locks(); ++i) {
763 mutex_buf[i] = PyThread_allocate_lock();
764 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500765 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400766 CRYPTO_set_locking_callback(locking_function);
767 return 1;
768}
769
770/* /\** */
771/* * Clean up after OpenSSL thread initialization. */
772/* *\/ */
773/* static int deinit_openssl_threads() { */
774/* int i; */
775
776/* if (!mutex_buf) { */
777/* return 0; */
778/* } */
779/* CRYPTO_set_id_callback(NULL); */
780/* CRYPTO_set_locking_callback(NULL); */
781/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
782/* PyThread_free_lock(mutex_buf[i]); */
783/* } */
784/* free(mutex_buf); */
785/* mutex_buf = NULL; */
786/* return 1; */
787/* } */
788
789#endif
790
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400791#ifdef PY3
792static struct PyModuleDef cryptomodule = {
793 PyModuleDef_HEAD_INIT,
794 "crypto",
795 crypto_doc,
796 -1,
797 crypto_methods
798};
799#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400800
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500801/*
802 * Initialize crypto sub module
803 *
804 * Arguments: None
805 * Returns: None
806 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400807PyOpenSSL_MODINIT(crypto) {
808#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500809 static void *crypto_API[crypto_API_pointers];
810 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400811#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400812 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500813
814 ERR_load_crypto_strings();
815 OpenSSL_add_all_algorithms();
816
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400817#ifdef PY3
818 module = PyModule_Create(&cryptomodule);
819#else
820 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
821#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500822
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400823 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400824 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400825 }
826
827#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500828 /* Initialize the C API pointer array */
829 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
830 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
831 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
832 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
833 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
834 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
835 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
836 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
837 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
838 if (c_api_object != NULL)
839 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400840#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500841
842 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
843 if (crypto_Error == NULL)
844 goto error;
845 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
846 goto error;
847
848 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
849 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500850 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500851
852 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
853 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
854
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400855#ifdef WITH_THREAD
856 if (!init_openssl_threads())
857 goto error;
858#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400859 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500860 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400861 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500862 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400863 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500864 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400865 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500866 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400867 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500868 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400869 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500870 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400871 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500872 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400873 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500874 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400875 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500876 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500877 if (!init_crypto_crl(module))
878 goto error;
879 if (!init_crypto_revoked(module))
880 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400881
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400882 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400883
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500884error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400885 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500886 ;
887}