blob: ec4d0b3021aa4c859405f999bd7422e6ff4d074f [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
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050088static char crypto_load_privatekey_doc[] = "\n\
89Load a private key from a buffer\n\
90\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090091:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
92:param buffer: The buffer the key is stored in\n\
93:param passphrase: (optional) if encrypted PEM format, this can be\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040094 either the passphrase to use, or a callback for\n\
95 providing the passphrase.\n\
96\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090097:return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050098";
99
100static PyObject *
101crypto_load_privatekey(PyObject *spam, PyObject *args)
102{
103 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
104 int type, len;
105 char *buffer;
106 PyObject *pw = NULL;
107 pem_password_cb *cb = NULL;
108 void *cb_arg = NULL;
109 BIO *bio;
110 EVP_PKEY *pkey;
111
112 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
113 return NULL;
114
115 if (pw != NULL)
116 {
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400117 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118 {
119 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400120 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500121 }
122 else if (PyCallable_Check(pw))
123 {
124 cb = global_passphrase_callback;
125 cb_arg = pw;
126 }
127 else
128 {
129 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
130 return NULL;
131 }
132 }
133
134 bio = BIO_new_mem_buf(buffer, len);
135 switch (type)
136 {
137 case X509_FILETYPE_PEM:
138 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
139 break;
140
141 case X509_FILETYPE_ASN1:
142 pkey = d2i_PrivateKey_bio(bio, NULL);
143 break;
144
145 default:
146 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
147 BIO_free(bio);
148 return NULL;
149 }
150 BIO_free(bio);
151
152 if (pkey == NULL)
153 {
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100154 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500155 }
156
157 return (PyObject *)crypto_PKey_New(pkey, 1);
158}
159
160static char crypto_dump_privatekey_doc[] = "\n\
161Dump a private key to a buffer\n\
162\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900163:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
164:param pkey: The PKey to dump\n\
165:param cipher: (optional) if encrypted PEM format, the cipher to\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400166 use\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900167:param passphrase: (optional) if encrypted PEM format, this can be either\n\
168 the passphrase to use, or a callback for providing the\n\
169 passphrase.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900170:return: The buffer with the dumped key in\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900171:rtype: :py:data:`str`\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500172";
173
174static PyObject *
175crypto_dump_privatekey(PyObject *spam, PyObject *args)
176{
177 int type, ret, buf_len;
178 char *temp;
179 PyObject *buffer;
180 char *cipher_name = NULL;
181 const EVP_CIPHER *cipher = NULL;
182 PyObject *pw = NULL;
183 pem_password_cb *cb = NULL;
184 void *cb_arg = NULL;
185 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500186 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500187 crypto_PKeyObj *pkey;
188
189 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
190 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
191 return NULL;
192
193 if (cipher_name != NULL && pw == NULL)
194 {
195 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
196 return NULL;
197 }
198 if (cipher_name != NULL)
199 {
200 cipher = EVP_get_cipherbyname(cipher_name);
201 if (cipher == NULL)
202 {
203 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
204 return NULL;
205 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400206 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500207 {
208 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400209 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500210 }
211 else if (PyCallable_Check(pw))
212 {
213 cb = global_passphrase_callback;
214 cb_arg = pw;
215 }
216 else
217 {
218 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
219 return NULL;
220 }
221 }
222
223 bio = BIO_new(BIO_s_mem());
224 switch (type)
225 {
226 case X509_FILETYPE_PEM:
227 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500228 break;
229
230 case X509_FILETYPE_ASN1:
231 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
232 break;
233
Rick Dean5b7b6372009-04-01 11:34:06 -0500234 case X509_FILETYPE_TEXT:
235 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
236 ret = RSA_print(bio, rsa, 0);
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100237 RSA_free(rsa);
Rick Dean5b7b6372009-04-01 11:34:06 -0500238 break;
239
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500240 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500241 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500242 BIO_free(bio);
243 return NULL;
244 }
245
246 if (ret == 0)
247 {
248 BIO_free(bio);
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100249 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500250 }
251
252 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400253 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500254 BIO_free(bio);
255
256 return buffer;
257}
258
259static char crypto_load_certificate_doc[] = "\n\
260Load a certificate from a buffer\n\
261\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900262:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500263 buffer - The buffer the certificate is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900264:return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500265";
266
267static PyObject *
268crypto_load_certificate(PyObject *spam, PyObject *args)
269{
270 crypto_X509Obj *crypto_X509_New(X509 *, int);
271 int type, len;
272 char *buffer;
273 BIO *bio;
274 X509 *cert;
275
276 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
277 return NULL;
278
279 bio = BIO_new_mem_buf(buffer, len);
280 switch (type)
281 {
282 case X509_FILETYPE_PEM:
283 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
284 break;
285
286 case X509_FILETYPE_ASN1:
287 cert = d2i_X509_bio(bio, NULL);
288 break;
289
290 default:
291 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
292 BIO_free(bio);
293 return NULL;
294 }
295 BIO_free(bio);
296
297 if (cert == NULL)
298 {
Rick Deand369c932009-07-08 11:48:33 -0500299 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500300 return NULL;
301 }
302
303 return (PyObject *)crypto_X509_New(cert, 1);
304}
305
306static char crypto_dump_certificate_doc[] = "\n\
307Dump a certificate to a buffer\n\
308\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900309:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
310:param cert: The certificate to dump\n\
311:return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500312";
313
314static PyObject *
315crypto_dump_certificate(PyObject *spam, PyObject *args)
316{
317 int type, ret, buf_len;
318 char *temp;
319 PyObject *buffer;
320 BIO *bio;
321 crypto_X509Obj *cert;
322
323 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
324 &crypto_X509_Type, &cert))
325 return NULL;
326
327 bio = BIO_new(BIO_s_mem());
328 switch (type)
329 {
330 case X509_FILETYPE_PEM:
331 ret = PEM_write_bio_X509(bio, cert->x509);
332 break;
333
334 case X509_FILETYPE_ASN1:
335 ret = i2d_X509_bio(bio, cert->x509);
336 break;
337
Rick Dean5b7b6372009-04-01 11:34:06 -0500338 case X509_FILETYPE_TEXT:
339 ret = X509_print_ex(bio, cert->x509, 0, 0);
340 break;
341
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500342 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500343 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500344 BIO_free(bio);
345 return NULL;
346 }
347
348 if (ret == 0)
349 {
350 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500351 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500352 return NULL;
353 }
354
355 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400356 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500357 BIO_free(bio);
358
359 return buffer;
360}
361
362static char crypto_load_certificate_request_doc[] = "\n\
363Load a certificate request from a buffer\n\
364\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900365:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500366 buffer - The buffer the certificate request is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900367:return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500368";
369
370static PyObject *
371crypto_load_certificate_request(PyObject *spam, PyObject *args)
372{
373 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
374 int type, len;
375 char *buffer;
376 BIO *bio;
377 X509_REQ *req;
378
379 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
380 return NULL;
381
382 bio = BIO_new_mem_buf(buffer, len);
383 switch (type)
384 {
385 case X509_FILETYPE_PEM:
386 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
387 break;
388
389 case X509_FILETYPE_ASN1:
390 req = d2i_X509_REQ_bio(bio, NULL);
391 break;
392
393 default:
394 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
395 BIO_free(bio);
396 return NULL;
397 }
398 BIO_free(bio);
399
400 if (req == NULL)
401 {
Rick Deand369c932009-07-08 11:48:33 -0500402 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500403 return NULL;
404 }
405
406 return (PyObject *)crypto_X509Req_New(req, 1);
407}
408
409static char crypto_dump_certificate_request_doc[] = "\n\
410Dump a certificate request to a buffer\n\
411\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900412:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500413 req - The certificate request to dump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900414:return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500415";
416
417static PyObject *
418crypto_dump_certificate_request(PyObject *spam, PyObject *args)
419{
420 int type, ret, buf_len;
421 char *temp;
422 PyObject *buffer;
423 BIO *bio;
424 crypto_X509ReqObj *req;
425
426 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
427 &crypto_X509Req_Type, &req))
428 return NULL;
429
430 bio = BIO_new(BIO_s_mem());
431 switch (type)
432 {
433 case X509_FILETYPE_PEM:
434 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
435 break;
436
437 case X509_FILETYPE_ASN1:
438 ret = i2d_X509_REQ_bio(bio, req->x509_req);
439 break;
440
Rick Dean5b7b6372009-04-01 11:34:06 -0500441 case X509_FILETYPE_TEXT:
442 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
443 break;
444
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500445 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500446 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500447 BIO_free(bio);
448 return NULL;
449 }
450
451 if (ret == 0)
452 {
453 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500454 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500455 return NULL;
456 }
457
458 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400459 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500460 BIO_free(bio);
461
462 return buffer;
463}
464
Rick Dean536ba022009-07-24 23:57:27 -0500465static char crypto_load_crl_doc[] = "\n\
466Load a certificate revocation list from a buffer\n\
467\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900468:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
469:param buffer: The buffer the CRL is stored in\n\
Rick Dean536ba022009-07-24 23:57:27 -0500470\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900471:return: The PKey object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500472";
473
474static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400475crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500476 int type, len;
477 char *buffer;
478 BIO *bio;
479 X509_CRL *crl;
480
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400481 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500482 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400483 }
Rick Dean536ba022009-07-24 23:57:27 -0500484
485 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400486 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500487 case X509_FILETYPE_PEM:
488 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
489 break;
490
491 case X509_FILETYPE_ASN1:
492 crl = d2i_X509_CRL_bio(bio, NULL);
493 break;
494
495 default:
496 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
497 BIO_free(bio);
498 return NULL;
499 }
500 BIO_free(bio);
501
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400502 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500503 exception_from_error_queue(crypto_Error);
504 return NULL;
505 }
506
507 return (PyObject *)crypto_CRL_New(crl);
508}
509
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500510static char crypto_load_pkcs7_data_doc[] = "\n\
511Load pkcs7 data from a buffer\n\
512\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900513:param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500514 buffer - The buffer with the pkcs7 data.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900515:return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500516";
517
518static PyObject *
519crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
520{
521 int type, len;
522 char *buffer;
523 BIO *bio;
524 PKCS7 *pkcs7 = NULL;
525
526 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
527 return NULL;
528
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100529 /*
530 * Try to read the pkcs7 data from the bio
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500531 */
532 bio = BIO_new_mem_buf(buffer, len);
533 switch (type)
534 {
535 case X509_FILETYPE_PEM:
536 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
537 break;
538
539 case X509_FILETYPE_ASN1:
540 pkcs7 = d2i_PKCS7_bio(bio, NULL);
541 break;
542
543 default:
544 PyErr_SetString(PyExc_ValueError,
545 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
546 return NULL;
547 }
548 BIO_free(bio);
549
550 /*
551 * Check if we got a PKCS7 structure
552 */
553 if (pkcs7 == NULL)
554 {
Rick Deand369c932009-07-08 11:48:33 -0500555 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500556 return NULL;
557 }
558
559 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
560}
561
562static char crypto_load_pkcs12_doc[] = "\n\
563Load a PKCS12 object from a buffer\n\
564\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900565:param buffer: The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400566 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900567:returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500568";
569
570static PyObject *
571crypto_load_pkcs12(PyObject *spam, PyObject *args)
572{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500573 int len;
574 char *buffer, *passphrase = NULL;
575 BIO *bio;
576 PKCS12 *p12;
577
578 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
579 return NULL;
580
581 bio = BIO_new_mem_buf(buffer, len);
582 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
583 {
584 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500585 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500586 return NULL;
587 }
588 BIO_free(bio);
589
590 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
591}
592
593
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500594static char crypto_X509_verify_cert_error_string_doc[] = "\n\
595Get X509 verify certificate error string.\n\
596\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900597:param errnum: The error number.\n\
598:return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500599";
600
601static PyObject *
602crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
603{
604 int errnum;
605 const char *str;
606
607 if (!PyArg_ParseTuple(args, "i", &errnum))
608 return NULL;
609
610 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400611 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500612}
613
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400614static char crypto_exception_from_error_queue_doc[] = "\n\
615Raise an exception from the current OpenSSL error queue.\n\
616";
617
618static PyObject *
619crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
620 exception_from_error_queue(crypto_Error);
621 return NULL;
622}
623
James Yonan7c2e5d32010-02-27 05:45:50 -0700624static char crypto_sign_doc[] = "\n\
625Sign data with a digest\n\
626\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900627:param pkey: Pkey to sign with\n\
628:param data: data to be signed\n\
629:param digest: message digest to use\n\
630:return: signature\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700631";
632
633static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400634crypto_sign(PyObject *spam, PyObject *args) {
635 PyObject *buffer;
636 crypto_PKeyObj *pkey;
637 char *data = NULL;
David Brodsky5c019772010-12-07 20:08:50 +0100638 int data_len;
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400639 char *digest_name;
640 int err;
641 unsigned int sig_len;
642 const EVP_MD *digest;
643 EVP_MD_CTX md_ctx;
644 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700645
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400646 if (!PyArg_ParseTuple(
David Brodsky5c019772010-12-07 20:08:50 +0100647 args, "O!" BYTESTRING_FMT "#s:sign", &crypto_PKey_Type,
648 &pkey, &data, &data_len, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400649 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700650 }
651
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400652 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
653 PyErr_SetString(PyExc_ValueError, "No such digest method");
654 return NULL;
655 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700656
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400657 EVP_SignInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100658 EVP_SignUpdate(&md_ctx, data, data_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400659 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400660 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700661
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400662 if (err != 1) {
663 exception_from_error_queue(crypto_Error);
664 return NULL;
665 }
666
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400667 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400668 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700669}
670
671static char crypto_verify_doc[] = "\n\
672Verify a signature\n\
673\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900674:param cert: signing certificate (X509 object)\n\
675:param signature: signature returned by sign function\n\
676:param data: data to be verified\n\
677:param digest: message digest to use\n\
678:return: None if the signature is correct, raise exception otherwise\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700679";
680
681static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400682crypto_verify(PyObject *spam, PyObject *args) {
683 crypto_X509Obj *cert;
684 unsigned char *signature;
685 int sig_len;
686 char *data, *digest_name;
David Brodsky5c019772010-12-07 20:08:50 +0100687 int data_len;
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400688 int err;
689 const EVP_MD *digest;
690 EVP_MD_CTX md_ctx;
691 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700692
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400693#ifdef PY3
David Brodsky5c019772010-12-07 20:08:50 +0100694 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 -0400695#else
David Brodsky5c019772010-12-07 20:08:50 +0100696 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 -0400697#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400698 return NULL;
699 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700700
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400701 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
702 PyErr_SetString(PyExc_ValueError, "No such digest method");
703 return NULL;
704 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700705
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400706 pkey = X509_get_pubkey(cert->x509);
707 if (pkey == NULL) {
708 PyErr_SetString(PyExc_ValueError, "No public key");
709 return NULL;
710 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700711
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400712 EVP_VerifyInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100713 EVP_VerifyUpdate(&md_ctx, data, data_len);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400714 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
715 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700716
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400717 if (err != 1) {
718 exception_from_error_queue(crypto_Error);
719 return NULL;
720 }
721
722 Py_INCREF(Py_None);
723 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700724}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400725
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500726/* Methods in the OpenSSL.crypto module (i.e. none) */
727static PyMethodDef crypto_methods[] = {
728 /* Module functions */
729 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
730 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
731 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
732 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
733 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
734 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500735 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500736 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
737 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700738 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
739 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500740 { "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 -0400741 { "_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 -0500742 { NULL, NULL }
743};
744
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400745
746#ifdef WITH_THREAD
747
748#include <pythread.h>
749
750/**
751 * This array will store all of the mutexes available to OpenSSL.
752 */
753static PyThread_type_lock *mutex_buf = NULL;
754
755
756/**
757 * Callback function supplied to OpenSSL to acquire or release a lock.
758 *
759 */
760static void locking_function(int mode, int n, const char * file, int line) {
761 if (mode & CRYPTO_LOCK) {
762 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
763 } else {
764 PyThread_release_lock(mutex_buf[n]);
765 }
766}
767
768
769/**
770 * Initialize OpenSSL for use from multiple threads.
771 *
772 * Returns: 0 if initialization fails, 1 otherwise.
773 */
774static int init_openssl_threads(void) {
775 int i;
776
777 mutex_buf = (PyThread_type_lock *)malloc(
778 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
779 if (!mutex_buf) {
780 return 0;
781 }
782 for (i = 0; i < CRYPTO_num_locks(); ++i) {
783 mutex_buf[i] = PyThread_allocate_lock();
784 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500785 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400786 CRYPTO_set_locking_callback(locking_function);
787 return 1;
788}
789
790/* /\** */
791/* * Clean up after OpenSSL thread initialization. */
792/* *\/ */
793/* static int deinit_openssl_threads() { */
794/* int i; */
795
796/* if (!mutex_buf) { */
797/* return 0; */
798/* } */
799/* CRYPTO_set_id_callback(NULL); */
800/* CRYPTO_set_locking_callback(NULL); */
801/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
802/* PyThread_free_lock(mutex_buf[i]); */
803/* } */
804/* free(mutex_buf); */
805/* mutex_buf = NULL; */
806/* return 1; */
807/* } */
808
809#endif
810
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400811#ifdef PY3
812static struct PyModuleDef cryptomodule = {
813 PyModuleDef_HEAD_INIT,
814 "crypto",
815 crypto_doc,
816 -1,
817 crypto_methods
818};
819#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400820
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500821/*
822 * Initialize crypto sub module
823 *
824 * Arguments: None
825 * Returns: None
826 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400827PyOpenSSL_MODINIT(crypto) {
828#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500829 static void *crypto_API[crypto_API_pointers];
830 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400831#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400832 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500833
834 ERR_load_crypto_strings();
835 OpenSSL_add_all_algorithms();
836
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400837#ifdef PY3
838 module = PyModule_Create(&cryptomodule);
839#else
840 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
841#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500842
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400843 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400844 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400845 }
846
847#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500848 /* Initialize the C API pointer array */
849 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
850 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
851 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
852 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
853 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
854 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
855 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
856 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
857 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500858 if (c_api_object != NULL) {
859 /* PyModule_AddObject steals a reference.
860 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400861 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500862 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500863 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400864#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500865
866 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
867 if (crypto_Error == NULL)
868 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500869
870 /* PyModule_AddObject steals a reference.
871 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400872 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500873 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
874 goto error;
875
876 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
877 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500878 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500879
880 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
881 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
882
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400883#ifdef WITH_THREAD
884 if (!init_openssl_threads())
885 goto error;
886#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400887 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500888 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400889 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500890 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400891 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500892 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400893 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500894 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400895 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500896 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400897 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500898 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400899 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500900 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400901 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500902 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400903 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500904 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500905 if (!init_crypto_crl(module))
906 goto error;
907 if (!init_crypto_revoked(module))
908 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400909
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400910 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400911
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500912error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400913 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500914 ;
915}