blob: b0e0d2f5b9a08e4fa3bd77b1da1b6e68a2e16fbc [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * crypto.c
3 *
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05004 * Copyright (C) AB Strakt
5 * Copyright (C) Keyphrene
6 * Copyright (C) Jean-Paul Calderone
7 * See LICENSE for details.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05008 *
9 * Main file of crypto sub module.
10 * See the file RATIONALE for a short explanation of why this module was written.
11 *
12 * Reviewed 2001-07-23
13 */
14#include <Python.h>
15#define crypto_MODULE
16#include "crypto.h"
Rick Dean623ee362009-07-17 12:22:16 -050017#include "pkcs12.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050018
19static char crypto_doc[] = "\n\
20Main file of crypto sub module.\n\
21See the file RATIONALE for a short explanation of why this module was written.\n\
22";
23
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050024void **ssl_API;
25
26PyObject *crypto_Error;
27
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -040028int crypto_byte_converter(PyObject *input, void* output) {
29 char **message = output;
30 if (input == Py_None) {
31 *message = NULL;
32 } else if (PyBytes_CheckExact(input)) {
33 *message = PyBytes_AsString(input);
34 } else {
35 return 0;
36 }
37 return 1;
38}
39
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050040static int
41global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
42{
43 PyObject *func, *argv, *ret;
44 int nchars;
45
46 func = (PyObject *)cb_arg;
47 argv = Py_BuildValue("(i)", rwflag);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010048 if (argv == NULL) {
49 return 0;
50 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050051 ret = PyEval_CallObject(func, argv);
52 Py_DECREF(argv);
53 if (ret == NULL)
54 return 0;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040055 if (!PyBytes_Check(ret))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050056 {
Ziga Seilnacht781295a2009-12-22 14:58:01 +010057 Py_DECREF(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050058 PyErr_SetString(PyExc_ValueError, "String expected");
59 return 0;
60 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040061 nchars = PyBytes_Size(ret);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010062 if (nchars > len) {
63 Py_DECREF(ret);
64 PyErr_SetString(PyExc_ValueError,
65 "passphrase returned by callback is too long");
66 return 0;
67 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040068 strncpy(buf, PyBytes_AsString(ret), nchars);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010069 Py_DECREF(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050070 return nchars;
71}
72
Ziga Seilnacht6b90a402009-12-22 14:33:47 +010073static PyObject *
74raise_current_error(void)
75{
76 if (PyErr_Occurred()) {
77 /*
78 * The python exception from callback is more informative than
79 * OpenSSL's error.
80 */
81 flush_error_queue();
82 return NULL;
83 }
84 exception_from_error_queue(crypto_Error);
85 return NULL;
86}
87
Ziga Seilnacht376cf972009-12-22 16:04:10 +010088static int
89setup_callback(int type, PyObject *pw, pem_password_cb **cb, void **cb_arg) {
90 if (pw == NULL) {
91 *cb = NULL;
92 *cb_arg = NULL;
93 return 1;
94 }
95 if (type != X509_FILETYPE_PEM) {
96 PyErr_SetString(PyExc_ValueError,
97 "only FILETYPE_PEM key format supports encryption");
98 return 0;
99 }
100 if (PyBytes_Check(pw)) {
101 *cb = NULL;
102 *cb_arg = PyBytes_AsString(pw);
103 } else if (PyCallable_Check(pw)) {
104 *cb = global_passphrase_callback;
105 *cb_arg = pw;
106 } else {
107 PyErr_SetString(PyExc_TypeError,
108 "Last argument must be string or callable");
109 return 0;
110 }
111 return 1;
112}
113
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500114static char crypto_load_privatekey_doc[] = "\n\
115Load a private key from a buffer\n\
116\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900117:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
118:param buffer: The buffer the key is stored in\n\
119:param passphrase: (optional) if encrypted PEM format, this can be\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400120 either the passphrase to use, or a callback for\n\
121 providing the passphrase.\n\
122\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900123:return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500124";
125
126static PyObject *
127crypto_load_privatekey(PyObject *spam, PyObject *args)
128{
129 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
130 int type, len;
131 char *buffer;
132 PyObject *pw = NULL;
133 pem_password_cb *cb = NULL;
134 void *cb_arg = NULL;
135 BIO *bio;
136 EVP_PKEY *pkey;
137
138 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
139 return NULL;
140
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100141 if (!setup_callback(type, pw, &cb, &cb_arg)) {
142 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500143 }
144
145 bio = BIO_new_mem_buf(buffer, len);
146 switch (type)
147 {
148 case X509_FILETYPE_PEM:
149 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
150 break;
151
152 case X509_FILETYPE_ASN1:
153 pkey = d2i_PrivateKey_bio(bio, NULL);
154 break;
155
156 default:
157 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
158 BIO_free(bio);
159 return NULL;
160 }
161 BIO_free(bio);
162
163 if (pkey == NULL)
164 {
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100165 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500166 }
167
168 return (PyObject *)crypto_PKey_New(pkey, 1);
169}
170
171static char crypto_dump_privatekey_doc[] = "\n\
172Dump a private key to a buffer\n\
173\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900174:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
175:param pkey: The PKey to dump\n\
176:param cipher: (optional) if encrypted PEM format, the cipher to\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400177 use\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900178:param passphrase: (optional) if encrypted PEM format, this can be either\n\
179 the passphrase to use, or a callback for providing the\n\
180 passphrase.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900181:return: The buffer with the dumped key in\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900182:rtype: :py:data:`str`\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500183";
184
185static PyObject *
186crypto_dump_privatekey(PyObject *spam, PyObject *args)
187{
188 int type, ret, buf_len;
189 char *temp;
190 PyObject *buffer;
191 char *cipher_name = NULL;
192 const EVP_CIPHER *cipher = NULL;
193 PyObject *pw = NULL;
194 pem_password_cb *cb = NULL;
195 void *cb_arg = NULL;
196 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500197 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500198 crypto_PKeyObj *pkey;
199
200 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
201 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
202 return NULL;
203
204 if (cipher_name != NULL && pw == NULL)
205 {
206 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
207 return NULL;
208 }
209 if (cipher_name != NULL)
210 {
211 cipher = EVP_get_cipherbyname(cipher_name);
212 if (cipher == NULL)
213 {
214 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
215 return NULL;
216 }
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100217 if (!setup_callback(type, pw, &cb, &cb_arg)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500218 return NULL;
219 }
220 }
221
222 bio = BIO_new(BIO_s_mem());
223 switch (type)
224 {
225 case X509_FILETYPE_PEM:
226 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500227 break;
228
229 case X509_FILETYPE_ASN1:
230 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
231 break;
232
Rick Dean5b7b6372009-04-01 11:34:06 -0500233 case X509_FILETYPE_TEXT:
234 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
235 ret = RSA_print(bio, rsa, 0);
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100236 RSA_free(rsa);
Rick Dean5b7b6372009-04-01 11:34:06 -0500237 break;
238
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500239 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500240 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500241 BIO_free(bio);
242 return NULL;
243 }
244
245 if (ret == 0)
246 {
247 BIO_free(bio);
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100248 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500249 }
250
251 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400252 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500253 BIO_free(bio);
254
255 return buffer;
256}
257
258static char crypto_load_certificate_doc[] = "\n\
259Load a certificate from a buffer\n\
260\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900261:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500262 buffer - The buffer the certificate is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900263:return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500264";
265
266static PyObject *
267crypto_load_certificate(PyObject *spam, PyObject *args)
268{
269 crypto_X509Obj *crypto_X509_New(X509 *, int);
270 int type, len;
271 char *buffer;
272 BIO *bio;
273 X509 *cert;
274
275 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
276 return NULL;
277
278 bio = BIO_new_mem_buf(buffer, len);
279 switch (type)
280 {
281 case X509_FILETYPE_PEM:
282 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
283 break;
284
285 case X509_FILETYPE_ASN1:
286 cert = d2i_X509_bio(bio, NULL);
287 break;
288
289 default:
290 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
291 BIO_free(bio);
292 return NULL;
293 }
294 BIO_free(bio);
295
296 if (cert == NULL)
297 {
Rick Deand369c932009-07-08 11:48:33 -0500298 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500299 return NULL;
300 }
301
302 return (PyObject *)crypto_X509_New(cert, 1);
303}
304
305static char crypto_dump_certificate_doc[] = "\n\
306Dump a certificate to a buffer\n\
307\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900308:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
309:param cert: The certificate to dump\n\
310:return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500311";
312
313static PyObject *
314crypto_dump_certificate(PyObject *spam, PyObject *args)
315{
316 int type, ret, buf_len;
317 char *temp;
318 PyObject *buffer;
319 BIO *bio;
320 crypto_X509Obj *cert;
321
322 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
323 &crypto_X509_Type, &cert))
324 return NULL;
325
326 bio = BIO_new(BIO_s_mem());
327 switch (type)
328 {
329 case X509_FILETYPE_PEM:
330 ret = PEM_write_bio_X509(bio, cert->x509);
331 break;
332
333 case X509_FILETYPE_ASN1:
334 ret = i2d_X509_bio(bio, cert->x509);
335 break;
336
Rick Dean5b7b6372009-04-01 11:34:06 -0500337 case X509_FILETYPE_TEXT:
338 ret = X509_print_ex(bio, cert->x509, 0, 0);
339 break;
340
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500341 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500342 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500343 BIO_free(bio);
344 return NULL;
345 }
346
347 if (ret == 0)
348 {
349 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500350 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500351 return NULL;
352 }
353
354 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400355 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500356 BIO_free(bio);
357
358 return buffer;
359}
360
361static char crypto_load_certificate_request_doc[] = "\n\
362Load a certificate request from a buffer\n\
363\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900364:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500365 buffer - The buffer the certificate request is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900366:return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500367";
368
369static PyObject *
370crypto_load_certificate_request(PyObject *spam, PyObject *args)
371{
372 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
373 int type, len;
374 char *buffer;
375 BIO *bio;
376 X509_REQ *req;
377
378 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
379 return NULL;
380
381 bio = BIO_new_mem_buf(buffer, len);
382 switch (type)
383 {
384 case X509_FILETYPE_PEM:
385 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
386 break;
387
388 case X509_FILETYPE_ASN1:
389 req = d2i_X509_REQ_bio(bio, NULL);
390 break;
391
392 default:
393 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
394 BIO_free(bio);
395 return NULL;
396 }
397 BIO_free(bio);
398
399 if (req == NULL)
400 {
Rick Deand369c932009-07-08 11:48:33 -0500401 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500402 return NULL;
403 }
404
405 return (PyObject *)crypto_X509Req_New(req, 1);
406}
407
408static char crypto_dump_certificate_request_doc[] = "\n\
409Dump a certificate request to a buffer\n\
410\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900411:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500412 req - The certificate request to dump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900413:return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500414";
415
416static PyObject *
417crypto_dump_certificate_request(PyObject *spam, PyObject *args)
418{
419 int type, ret, buf_len;
420 char *temp;
421 PyObject *buffer;
422 BIO *bio;
423 crypto_X509ReqObj *req;
424
425 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
426 &crypto_X509Req_Type, &req))
427 return NULL;
428
429 bio = BIO_new(BIO_s_mem());
430 switch (type)
431 {
432 case X509_FILETYPE_PEM:
433 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
434 break;
435
436 case X509_FILETYPE_ASN1:
437 ret = i2d_X509_REQ_bio(bio, req->x509_req);
438 break;
439
Rick Dean5b7b6372009-04-01 11:34:06 -0500440 case X509_FILETYPE_TEXT:
441 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
442 break;
443
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500444 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500445 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500446 BIO_free(bio);
447 return NULL;
448 }
449
450 if (ret == 0)
451 {
452 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500453 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500454 return NULL;
455 }
456
457 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400458 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500459 BIO_free(bio);
460
461 return buffer;
462}
463
Rick Dean536ba022009-07-24 23:57:27 -0500464static char crypto_load_crl_doc[] = "\n\
465Load a certificate revocation list from a buffer\n\
466\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900467:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
468:param buffer: The buffer the CRL is stored in\n\
Rick Dean536ba022009-07-24 23:57:27 -0500469\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900470:return: The PKey object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500471";
472
473static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400474crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500475 int type, len;
476 char *buffer;
477 BIO *bio;
478 X509_CRL *crl;
479
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400480 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500481 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400482 }
Rick Dean536ba022009-07-24 23:57:27 -0500483
484 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400485 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500486 case X509_FILETYPE_PEM:
487 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
488 break;
489
490 case X509_FILETYPE_ASN1:
491 crl = d2i_X509_CRL_bio(bio, NULL);
492 break;
493
494 default:
495 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
496 BIO_free(bio);
497 return NULL;
498 }
499 BIO_free(bio);
500
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400501 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500502 exception_from_error_queue(crypto_Error);
503 return NULL;
504 }
505
506 return (PyObject *)crypto_CRL_New(crl);
507}
508
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500509static char crypto_load_pkcs7_data_doc[] = "\n\
510Load pkcs7 data from a buffer\n\
511\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900512:param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500513 buffer - The buffer with the pkcs7 data.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900514:return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500515";
516
517static PyObject *
518crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
519{
520 int type, len;
521 char *buffer;
522 BIO *bio;
523 PKCS7 *pkcs7 = NULL;
524
525 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
526 return NULL;
527
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100528 /*
529 * Try to read the pkcs7 data from the bio
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500530 */
531 bio = BIO_new_mem_buf(buffer, len);
532 switch (type)
533 {
534 case X509_FILETYPE_PEM:
535 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
536 break;
537
538 case X509_FILETYPE_ASN1:
539 pkcs7 = d2i_PKCS7_bio(bio, NULL);
540 break;
541
542 default:
543 PyErr_SetString(PyExc_ValueError,
544 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
545 return NULL;
546 }
547 BIO_free(bio);
548
549 /*
550 * Check if we got a PKCS7 structure
551 */
552 if (pkcs7 == NULL)
553 {
Rick Deand369c932009-07-08 11:48:33 -0500554 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500555 return NULL;
556 }
557
558 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
559}
560
561static char crypto_load_pkcs12_doc[] = "\n\
562Load a PKCS12 object from a buffer\n\
563\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900564:param buffer: The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400565 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900566:returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500567";
568
569static PyObject *
570crypto_load_pkcs12(PyObject *spam, PyObject *args)
571{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500572 int len;
573 char *buffer, *passphrase = NULL;
574 BIO *bio;
575 PKCS12 *p12;
576
577 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
578 return NULL;
579
580 bio = BIO_new_mem_buf(buffer, len);
581 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
582 {
583 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500584 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500585 return NULL;
586 }
587 BIO_free(bio);
588
589 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
590}
591
592
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500593static char crypto_X509_verify_cert_error_string_doc[] = "\n\
594Get X509 verify certificate error string.\n\
595\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900596:param errnum: The error number.\n\
597:return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500598";
599
600static PyObject *
601crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
602{
603 int errnum;
604 const char *str;
605
606 if (!PyArg_ParseTuple(args, "i", &errnum))
607 return NULL;
608
609 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400610 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500611}
612
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400613static char crypto_exception_from_error_queue_doc[] = "\n\
614Raise an exception from the current OpenSSL error queue.\n\
615";
616
617static PyObject *
618crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
619 exception_from_error_queue(crypto_Error);
620 return NULL;
621}
622
James Yonan7c2e5d32010-02-27 05:45:50 -0700623static char crypto_sign_doc[] = "\n\
624Sign data with a digest\n\
625\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900626:param pkey: Pkey to sign with\n\
627:param data: data to be signed\n\
628:param digest: message digest to use\n\
629:return: signature\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700630";
631
632static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400633crypto_sign(PyObject *spam, PyObject *args) {
634 PyObject *buffer;
635 crypto_PKeyObj *pkey;
636 char *data = NULL;
David Brodsky5c019772010-12-07 20:08:50 +0100637 int data_len;
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400638 char *digest_name;
639 int err;
640 unsigned int sig_len;
641 const EVP_MD *digest;
642 EVP_MD_CTX md_ctx;
643 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700644
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400645 if (!PyArg_ParseTuple(
David Brodsky5c019772010-12-07 20:08:50 +0100646 args, "O!" BYTESTRING_FMT "#s:sign", &crypto_PKey_Type,
647 &pkey, &data, &data_len, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400648 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700649 }
650
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400651 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
652 PyErr_SetString(PyExc_ValueError, "No such digest method");
653 return NULL;
654 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700655
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400656 EVP_SignInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100657 EVP_SignUpdate(&md_ctx, data, data_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400658 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400659 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700660
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400661 if (err != 1) {
662 exception_from_error_queue(crypto_Error);
663 return NULL;
664 }
665
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400666 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400667 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700668}
669
670static char crypto_verify_doc[] = "\n\
671Verify a signature\n\
672\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900673:param cert: signing certificate (X509 object)\n\
674:param signature: signature returned by sign function\n\
675:param data: data to be verified\n\
676:param digest: message digest to use\n\
677:return: None if the signature is correct, raise exception otherwise\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700678";
679
680static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400681crypto_verify(PyObject *spam, PyObject *args) {
682 crypto_X509Obj *cert;
683 unsigned char *signature;
684 int sig_len;
685 char *data, *digest_name;
David Brodsky5c019772010-12-07 20:08:50 +0100686 int data_len;
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400687 int err;
688 const EVP_MD *digest;
689 EVP_MD_CTX md_ctx;
690 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700691
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400692#ifdef PY3
David Brodsky5c019772010-12-07 20:08:50 +0100693 if (!PyArg_ParseTuple(args, "O!" BYTESTRING_FMT "#" BYTESTRING_FMT "#s:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &data_len, &digest_name)) {
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400694#else
David Brodsky5c019772010-12-07 20:08:50 +0100695 if (!PyArg_ParseTuple(args, "O!t#s#s:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &data_len, &digest_name)) {
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400696#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400697 return NULL;
698 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700699
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400700 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
701 PyErr_SetString(PyExc_ValueError, "No such digest method");
702 return NULL;
703 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700704
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400705 pkey = X509_get_pubkey(cert->x509);
706 if (pkey == NULL) {
707 PyErr_SetString(PyExc_ValueError, "No public key");
708 return NULL;
709 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700710
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400711 EVP_VerifyInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100712 EVP_VerifyUpdate(&md_ctx, data, data_len);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400713 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
714 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700715
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400716 if (err != 1) {
717 exception_from_error_queue(crypto_Error);
718 return NULL;
719 }
720
721 Py_INCREF(Py_None);
722 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700723}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400724
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500725/* Methods in the OpenSSL.crypto module (i.e. none) */
726static PyMethodDef crypto_methods[] = {
727 /* Module functions */
728 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
729 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
730 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
731 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
732 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
733 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500734 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500735 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
736 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700737 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
738 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500739 { "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 -0400740 { "_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 -0500741 { NULL, NULL }
742};
743
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400744
745#ifdef WITH_THREAD
746
747#include <pythread.h>
748
749/**
750 * This array will store all of the mutexes available to OpenSSL.
751 */
752static PyThread_type_lock *mutex_buf = NULL;
753
754
755/**
756 * Callback function supplied to OpenSSL to acquire or release a lock.
757 *
758 */
759static void locking_function(int mode, int n, const char * file, int line) {
760 if (mode & CRYPTO_LOCK) {
761 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
762 } else {
763 PyThread_release_lock(mutex_buf[n]);
764 }
765}
766
767
768/**
769 * Initialize OpenSSL for use from multiple threads.
770 *
771 * Returns: 0 if initialization fails, 1 otherwise.
772 */
773static int init_openssl_threads(void) {
774 int i;
775
776 mutex_buf = (PyThread_type_lock *)malloc(
777 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
778 if (!mutex_buf) {
779 return 0;
780 }
781 for (i = 0; i < CRYPTO_num_locks(); ++i) {
782 mutex_buf[i] = PyThread_allocate_lock();
783 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500784 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400785 CRYPTO_set_locking_callback(locking_function);
786 return 1;
787}
788
789/* /\** */
790/* * Clean up after OpenSSL thread initialization. */
791/* *\/ */
792/* static int deinit_openssl_threads() { */
793/* int i; */
794
795/* if (!mutex_buf) { */
796/* return 0; */
797/* } */
798/* CRYPTO_set_id_callback(NULL); */
799/* CRYPTO_set_locking_callback(NULL); */
800/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
801/* PyThread_free_lock(mutex_buf[i]); */
802/* } */
803/* free(mutex_buf); */
804/* mutex_buf = NULL; */
805/* return 1; */
806/* } */
807
808#endif
809
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400810#ifdef PY3
811static struct PyModuleDef cryptomodule = {
812 PyModuleDef_HEAD_INIT,
813 "crypto",
814 crypto_doc,
815 -1,
816 crypto_methods
817};
818#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400819
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500820/*
821 * Initialize crypto sub module
822 *
823 * Arguments: None
824 * Returns: None
825 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400826PyOpenSSL_MODINIT(crypto) {
827#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500828 static void *crypto_API[crypto_API_pointers];
829 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400830#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400831 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500832
833 ERR_load_crypto_strings();
834 OpenSSL_add_all_algorithms();
835
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400836#ifdef PY3
837 module = PyModule_Create(&cryptomodule);
838#else
839 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
840#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500841
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400842 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400843 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400844 }
845
846#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500847 /* Initialize the C API pointer array */
848 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
849 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
850 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
851 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
852 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
853 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
854 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
855 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
856 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500857 if (c_api_object != NULL) {
858 /* PyModule_AddObject steals a reference.
859 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400860 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500861 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500862 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400863#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500864
865 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
866 if (crypto_Error == NULL)
867 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500868
869 /* PyModule_AddObject steals a reference.
870 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400871 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500872 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
873 goto error;
874
875 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
876 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500877 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500878
879 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
880 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
881
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400882#ifdef WITH_THREAD
883 if (!init_openssl_threads())
884 goto error;
885#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400886 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500887 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400888 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500889 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400890 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500891 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400892 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500893 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400894 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500895 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400896 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500897 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400898 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500899 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400900 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500901 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400902 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500903 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500904 if (!init_crypto_crl(module))
905 goto error;
906 if (!init_crypto_revoked(module))
907 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400908
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400909 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400910
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500911error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400912 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500913 ;
914}