blob: 8bea656319bc69a6ec5e367b997cc7e1b321b4f6 [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);
48 ret = PyEval_CallObject(func, argv);
49 Py_DECREF(argv);
50 if (ret == NULL)
51 return 0;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040052 if (!PyBytes_Check(ret))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050053 {
54 PyErr_SetString(PyExc_ValueError, "String expected");
55 return 0;
56 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040057 nchars = PyBytes_Size(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050058 if (nchars > len)
59 nchars = len;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040060 strncpy(buf, PyBytes_AsString(ret), nchars);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061 return nchars;
62}
63
64static char crypto_load_privatekey_doc[] = "\n\
65Load a private key from a buffer\n\
66\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040067@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
68@param buffer: The buffer the key is stored in\n\
69@param passphrase: (optional) if encrypted PEM format, this can be\n\
70 either the passphrase to use, or a callback for\n\
71 providing the passphrase.\n\
72\n\
73@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050074";
75
76static PyObject *
77crypto_load_privatekey(PyObject *spam, PyObject *args)
78{
79 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
80 int type, len;
81 char *buffer;
82 PyObject *pw = NULL;
83 pem_password_cb *cb = NULL;
84 void *cb_arg = NULL;
85 BIO *bio;
86 EVP_PKEY *pkey;
87
88 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
89 return NULL;
90
91 if (pw != NULL)
92 {
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040093 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050094 {
95 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040096 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050097 }
98 else if (PyCallable_Check(pw))
99 {
100 cb = global_passphrase_callback;
101 cb_arg = pw;
102 }
103 else
104 {
105 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
106 return NULL;
107 }
108 }
109
110 bio = BIO_new_mem_buf(buffer, len);
111 switch (type)
112 {
113 case X509_FILETYPE_PEM:
114 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
115 break;
116
117 case X509_FILETYPE_ASN1:
118 pkey = d2i_PrivateKey_bio(bio, NULL);
119 break;
120
121 default:
122 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
123 BIO_free(bio);
124 return NULL;
125 }
126 BIO_free(bio);
127
128 if (pkey == NULL)
129 {
Rick Deand369c932009-07-08 11:48:33 -0500130 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500131 return NULL;
132 }
133
134 return (PyObject *)crypto_PKey_New(pkey, 1);
135}
136
137static char crypto_dump_privatekey_doc[] = "\n\
138Dump a private key to a buffer\n\
139\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400140@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
141@param pkey: The PKey to dump\n\
142@param cipher: (optional) if encrypted PEM format, the cipher to\n\
143 use\n\
144@param passphrase - (optional) if encrypted PEM format, this can be either\n\
145 the passphrase to use, or a callback for providing the\n\
146 passphrase.\n\
147@return: The buffer with the dumped key in\n\
148@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500149";
150
151static PyObject *
152crypto_dump_privatekey(PyObject *spam, PyObject *args)
153{
154 int type, ret, buf_len;
155 char *temp;
156 PyObject *buffer;
157 char *cipher_name = NULL;
158 const EVP_CIPHER *cipher = NULL;
159 PyObject *pw = NULL;
160 pem_password_cb *cb = NULL;
161 void *cb_arg = NULL;
162 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500163 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500164 crypto_PKeyObj *pkey;
165
166 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
167 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
168 return NULL;
169
170 if (cipher_name != NULL && pw == NULL)
171 {
172 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
173 return NULL;
174 }
175 if (cipher_name != NULL)
176 {
177 cipher = EVP_get_cipherbyname(cipher_name);
178 if (cipher == NULL)
179 {
180 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
181 return NULL;
182 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400183 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500184 {
185 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400186 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500187 }
188 else if (PyCallable_Check(pw))
189 {
190 cb = global_passphrase_callback;
191 cb_arg = pw;
192 }
193 else
194 {
195 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
196 return NULL;
197 }
198 }
199
200 bio = BIO_new(BIO_s_mem());
201 switch (type)
202 {
203 case X509_FILETYPE_PEM:
204 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
205 if (PyErr_Occurred())
206 {
207 BIO_free(bio);
208 return NULL;
209 }
210 break;
211
212 case X509_FILETYPE_ASN1:
213 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
214 break;
215
Rick Dean5b7b6372009-04-01 11:34:06 -0500216 case X509_FILETYPE_TEXT:
217 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
218 ret = RSA_print(bio, rsa, 0);
219 RSA_free(rsa);
220 break;
221
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500222 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500223 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500224 BIO_free(bio);
225 return NULL;
226 }
227
228 if (ret == 0)
229 {
230 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500231 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500232 return NULL;
233 }
234
235 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400236 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500237 BIO_free(bio);
238
239 return buffer;
240}
241
242static char crypto_load_certificate_doc[] = "\n\
243Load a certificate from a buffer\n\
244\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400245@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500246 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400247@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500248";
249
250static PyObject *
251crypto_load_certificate(PyObject *spam, PyObject *args)
252{
253 crypto_X509Obj *crypto_X509_New(X509 *, int);
254 int type, len;
255 char *buffer;
256 BIO *bio;
257 X509 *cert;
258
259 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
260 return NULL;
261
262 bio = BIO_new_mem_buf(buffer, len);
263 switch (type)
264 {
265 case X509_FILETYPE_PEM:
266 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
267 break;
268
269 case X509_FILETYPE_ASN1:
270 cert = d2i_X509_bio(bio, NULL);
271 break;
272
273 default:
274 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
275 BIO_free(bio);
276 return NULL;
277 }
278 BIO_free(bio);
279
280 if (cert == NULL)
281 {
Rick Deand369c932009-07-08 11:48:33 -0500282 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500283 return NULL;
284 }
285
286 return (PyObject *)crypto_X509_New(cert, 1);
287}
288
289static char crypto_dump_certificate_doc[] = "\n\
290Dump a certificate to a buffer\n\
291\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400292@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
293@param cert: The certificate to dump\n\
294@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500295";
296
297static PyObject *
298crypto_dump_certificate(PyObject *spam, PyObject *args)
299{
300 int type, ret, buf_len;
301 char *temp;
302 PyObject *buffer;
303 BIO *bio;
304 crypto_X509Obj *cert;
305
306 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
307 &crypto_X509_Type, &cert))
308 return NULL;
309
310 bio = BIO_new(BIO_s_mem());
311 switch (type)
312 {
313 case X509_FILETYPE_PEM:
314 ret = PEM_write_bio_X509(bio, cert->x509);
315 break;
316
317 case X509_FILETYPE_ASN1:
318 ret = i2d_X509_bio(bio, cert->x509);
319 break;
320
Rick Dean5b7b6372009-04-01 11:34:06 -0500321 case X509_FILETYPE_TEXT:
322 ret = X509_print_ex(bio, cert->x509, 0, 0);
323 break;
324
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500325 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500326 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500327 BIO_free(bio);
328 return NULL;
329 }
330
331 if (ret == 0)
332 {
333 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500334 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500335 return NULL;
336 }
337
338 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400339 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500340 BIO_free(bio);
341
342 return buffer;
343}
344
345static char crypto_load_certificate_request_doc[] = "\n\
346Load a certificate request from a buffer\n\
347\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400348@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500349 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400350@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500351";
352
353static PyObject *
354crypto_load_certificate_request(PyObject *spam, PyObject *args)
355{
356 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
357 int type, len;
358 char *buffer;
359 BIO *bio;
360 X509_REQ *req;
361
362 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
363 return NULL;
364
365 bio = BIO_new_mem_buf(buffer, len);
366 switch (type)
367 {
368 case X509_FILETYPE_PEM:
369 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
370 break;
371
372 case X509_FILETYPE_ASN1:
373 req = d2i_X509_REQ_bio(bio, NULL);
374 break;
375
376 default:
377 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
378 BIO_free(bio);
379 return NULL;
380 }
381 BIO_free(bio);
382
383 if (req == NULL)
384 {
Rick Deand369c932009-07-08 11:48:33 -0500385 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500386 return NULL;
387 }
388
389 return (PyObject *)crypto_X509Req_New(req, 1);
390}
391
392static char crypto_dump_certificate_request_doc[] = "\n\
393Dump a certificate request to a buffer\n\
394\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400395@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500396 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400397@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500398";
399
400static PyObject *
401crypto_dump_certificate_request(PyObject *spam, PyObject *args)
402{
403 int type, ret, buf_len;
404 char *temp;
405 PyObject *buffer;
406 BIO *bio;
407 crypto_X509ReqObj *req;
408
409 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
410 &crypto_X509Req_Type, &req))
411 return NULL;
412
413 bio = BIO_new(BIO_s_mem());
414 switch (type)
415 {
416 case X509_FILETYPE_PEM:
417 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
418 break;
419
420 case X509_FILETYPE_ASN1:
421 ret = i2d_X509_REQ_bio(bio, req->x509_req);
422 break;
423
Rick Dean5b7b6372009-04-01 11:34:06 -0500424 case X509_FILETYPE_TEXT:
425 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
426 break;
427
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500428 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500429 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500430 BIO_free(bio);
431 return NULL;
432 }
433
434 if (ret == 0)
435 {
436 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500437 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500438 return NULL;
439 }
440
441 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400442 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500443 BIO_free(bio);
444
445 return buffer;
446}
447
Rick Dean536ba022009-07-24 23:57:27 -0500448static char crypto_load_crl_doc[] = "\n\
449Load a certificate revocation list from a buffer\n\
450\n\
451@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
452@param buffer: The buffer the CRL is stored in\n\
453\n\
454@return: The PKey object\n\
455";
456
457static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400458crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500459 int type, len;
460 char *buffer;
461 BIO *bio;
462 X509_CRL *crl;
463
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400464 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500465 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400466 }
Rick Dean536ba022009-07-24 23:57:27 -0500467
468 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400469 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500470 case X509_FILETYPE_PEM:
471 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
472 break;
473
474 case X509_FILETYPE_ASN1:
475 crl = d2i_X509_CRL_bio(bio, NULL);
476 break;
477
478 default:
479 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
480 BIO_free(bio);
481 return NULL;
482 }
483 BIO_free(bio);
484
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400485 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500486 exception_from_error_queue(crypto_Error);
487 return NULL;
488 }
489
490 return (PyObject *)crypto_CRL_New(crl);
491}
492
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500493static char crypto_load_pkcs7_data_doc[] = "\n\
494Load pkcs7 data from a buffer\n\
495\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400496@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500497 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400498@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500499";
500
501static PyObject *
502crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
503{
504 int type, len;
505 char *buffer;
506 BIO *bio;
507 PKCS7 *pkcs7 = NULL;
508
509 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
510 return NULL;
511
512 /*
513 * Try to read the pkcs7 data from the bio
514 */
515 bio = BIO_new_mem_buf(buffer, len);
516 switch (type)
517 {
518 case X509_FILETYPE_PEM:
519 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
520 break;
521
522 case X509_FILETYPE_ASN1:
523 pkcs7 = d2i_PKCS7_bio(bio, NULL);
524 break;
525
526 default:
527 PyErr_SetString(PyExc_ValueError,
528 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
529 return NULL;
530 }
531 BIO_free(bio);
532
533 /*
534 * Check if we got a PKCS7 structure
535 */
536 if (pkcs7 == NULL)
537 {
Rick Deand369c932009-07-08 11:48:33 -0500538 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500539 return NULL;
540 }
541
542 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
543}
544
545static char crypto_load_pkcs12_doc[] = "\n\
546Load a PKCS12 object from a buffer\n\
547\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400548@param buffer: The buffer the certificate is stored in\n\
549 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
550@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500551";
552
553static PyObject *
554crypto_load_pkcs12(PyObject *spam, PyObject *args)
555{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500556 int len;
557 char *buffer, *passphrase = NULL;
558 BIO *bio;
559 PKCS12 *p12;
560
561 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
562 return NULL;
563
564 bio = BIO_new_mem_buf(buffer, len);
565 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
566 {
567 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500568 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500569 return NULL;
570 }
571 BIO_free(bio);
572
573 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
574}
575
576
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500577static char crypto_X509_verify_cert_error_string_doc[] = "\n\
578Get X509 verify certificate error string.\n\
579\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400580@param errnum: The error number.\n\
581@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500582";
583
584static PyObject *
585crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
586{
587 int errnum;
588 const char *str;
589
590 if (!PyArg_ParseTuple(args, "i", &errnum))
591 return NULL;
592
593 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400594 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500595}
596
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400597static char crypto_exception_from_error_queue_doc[] = "\n\
598Raise an exception from the current OpenSSL error queue.\n\
599";
600
601static PyObject *
602crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
603 exception_from_error_queue(crypto_Error);
604 return NULL;
605}
606
James Yonan7c2e5d32010-02-27 05:45:50 -0700607static char crypto_sign_doc[] = "\n\
608Sign data with a digest\n\
609\n\
610@param pkey: Pkey to sign with\n\
611@param data: data to be signed\n\
612@param digest: message digest to use\n\
613@return: signature\n\
614";
615
616static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400617crypto_sign(PyObject *spam, PyObject *args) {
618 PyObject *buffer;
619 crypto_PKeyObj *pkey;
620 char *data = NULL;
621 char *digest_name;
622 int err;
623 unsigned int sig_len;
624 const EVP_MD *digest;
625 EVP_MD_CTX md_ctx;
626 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700627
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400628 if (!PyArg_ParseTuple(
Jean-Paul Calderone5d441aa2010-10-02 18:34:52 -0400629 args, "O!" BYTESTRING_FMT "s:sign", &crypto_PKey_Type,
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400630 &pkey, &data, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400631 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700632 }
633
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400634 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
635 PyErr_SetString(PyExc_ValueError, "No such digest method");
636 return NULL;
637 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700638
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400639 EVP_SignInit(&md_ctx, digest);
640 EVP_SignUpdate(&md_ctx, data, strlen(data));
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400641 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400642 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700643
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400644 if (err != 1) {
645 exception_from_error_queue(crypto_Error);
646 return NULL;
647 }
648
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400649 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400650 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700651}
652
653static char crypto_verify_doc[] = "\n\
654Verify a signature\n\
655\n\
656@param cert: signing certificate (X509 object)\n\
657@param signature: signature returned by sign function\n\
658@param data: data to be verified\n\
659@param digest: message digest to use\n\
660@return: None if the signature is correct, raise exception otherwise\n\
661";
662
663static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400664crypto_verify(PyObject *spam, PyObject *args) {
665 crypto_X509Obj *cert;
666 unsigned char *signature;
667 int sig_len;
668 char *data, *digest_name;
669 int err;
670 const EVP_MD *digest;
671 EVP_MD_CTX md_ctx;
672 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700673
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400674#ifdef PY3
Jean-Paul Calderone5d441aa2010-10-02 18:34:52 -0400675 if (!PyArg_ParseTuple(args, "O!" BYTESTRING_FMT "#" BYTESTRING_FMT "s:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400676#else
677 if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len, &data, &digest_name)) {
678#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400679 return NULL;
680 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700681
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400682 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
683 PyErr_SetString(PyExc_ValueError, "No such digest method");
684 return NULL;
685 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700686
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400687 pkey = X509_get_pubkey(cert->x509);
688 if (pkey == NULL) {
689 PyErr_SetString(PyExc_ValueError, "No public key");
690 return NULL;
691 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700692
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400693 EVP_VerifyInit(&md_ctx, digest);
694 EVP_VerifyUpdate(&md_ctx, data, strlen((char*)data));
695 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
696 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700697
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400698 if (err != 1) {
699 exception_from_error_queue(crypto_Error);
700 return NULL;
701 }
702
703 Py_INCREF(Py_None);
704 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700705}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400706
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500707/* Methods in the OpenSSL.crypto module (i.e. none) */
708static PyMethodDef crypto_methods[] = {
709 /* Module functions */
710 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
711 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
712 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
713 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
714 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
715 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500716 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500717 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
718 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700719 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
720 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500721 { "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 -0400722 { "_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 -0500723 { NULL, NULL }
724};
725
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400726
727#ifdef WITH_THREAD
728
729#include <pythread.h>
730
731/**
732 * This array will store all of the mutexes available to OpenSSL.
733 */
734static PyThread_type_lock *mutex_buf = NULL;
735
736
737/**
738 * Callback function supplied to OpenSSL to acquire or release a lock.
739 *
740 */
741static void locking_function(int mode, int n, const char * file, int line) {
742 if (mode & CRYPTO_LOCK) {
743 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
744 } else {
745 PyThread_release_lock(mutex_buf[n]);
746 }
747}
748
749
750/**
751 * Initialize OpenSSL for use from multiple threads.
752 *
753 * Returns: 0 if initialization fails, 1 otherwise.
754 */
755static int init_openssl_threads(void) {
756 int i;
757
758 mutex_buf = (PyThread_type_lock *)malloc(
759 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
760 if (!mutex_buf) {
761 return 0;
762 }
763 for (i = 0; i < CRYPTO_num_locks(); ++i) {
764 mutex_buf[i] = PyThread_allocate_lock();
765 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500766 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400767 CRYPTO_set_locking_callback(locking_function);
768 return 1;
769}
770
771/* /\** */
772/* * Clean up after OpenSSL thread initialization. */
773/* *\/ */
774/* static int deinit_openssl_threads() { */
775/* int i; */
776
777/* if (!mutex_buf) { */
778/* return 0; */
779/* } */
780/* CRYPTO_set_id_callback(NULL); */
781/* CRYPTO_set_locking_callback(NULL); */
782/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
783/* PyThread_free_lock(mutex_buf[i]); */
784/* } */
785/* free(mutex_buf); */
786/* mutex_buf = NULL; */
787/* return 1; */
788/* } */
789
790#endif
791
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400792#ifdef PY3
793static struct PyModuleDef cryptomodule = {
794 PyModuleDef_HEAD_INIT,
795 "crypto",
796 crypto_doc,
797 -1,
798 crypto_methods
799};
800#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400801
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500802/*
803 * Initialize crypto sub module
804 *
805 * Arguments: None
806 * Returns: None
807 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400808PyOpenSSL_MODINIT(crypto) {
809#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500810 static void *crypto_API[crypto_API_pointers];
811 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400812#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400813 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500814
815 ERR_load_crypto_strings();
816 OpenSSL_add_all_algorithms();
817
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400818#ifdef PY3
819 module = PyModule_Create(&cryptomodule);
820#else
821 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
822#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500823
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400824 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400825 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400826 }
827
828#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500829 /* Initialize the C API pointer array */
830 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
831 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
832 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
833 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
834 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
835 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
836 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
837 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
838 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500839 if (c_api_object != NULL) {
840 /* PyModule_AddObject steals a reference.
841 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400842 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500843 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500844 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400845#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500846
847 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
848 if (crypto_Error == NULL)
849 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500850
851 /* PyModule_AddObject steals a reference.
852 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400853 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500854 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
855 goto error;
856
857 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
858 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500859 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500860
861 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
862 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
863
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400864#ifdef WITH_THREAD
865 if (!init_openssl_threads())
866 goto error;
867#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400868 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500869 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400870 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500871 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400872 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500873 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400874 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500875 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400876 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500877 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400878 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500879 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400880 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500881 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400882 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500883 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400884 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500885 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500886 if (!init_crypto_crl(module))
887 goto error;
888 if (!init_crypto_revoked(module))
889 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400890
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400891 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400892
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500893error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400894 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500895 ;
896}