blob: 421eabc5a7f68758efd05061631f8543cd6e8cd7 [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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090067: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\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040070 either the passphrase to use, or a callback for\n\
71 providing the passphrase.\n\
72\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090073: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900140: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\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400143 use\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900144:param passphrase - (optional) if encrypted PEM format, this can be either\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400145 the passphrase to use, or a callback for providing the\n\
146 passphrase.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900147: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900245: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900247: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900292: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900348: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900350: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900395: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900397: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900451:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
452:param buffer: The buffer the CRL is stored in\n\
Rick Dean536ba022009-07-24 23:57:27 -0500453\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900454:return: The PKey object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500455";
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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900496: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900498: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900548:param buffer: The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400549 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900550: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900580: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\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900610: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\
James Yonan7c2e5d32010-02-27 05:45:50 -0700614";
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;
David Brodsky5c019772010-12-07 20:08:50 +0100621 int data_len;
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400622 char *digest_name;
623 int err;
624 unsigned int sig_len;
625 const EVP_MD *digest;
626 EVP_MD_CTX md_ctx;
627 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700628
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400629 if (!PyArg_ParseTuple(
David Brodsky5c019772010-12-07 20:08:50 +0100630 args, "O!" BYTESTRING_FMT "#s:sign", &crypto_PKey_Type,
631 &pkey, &data, &data_len, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400632 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700633 }
634
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400635 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
636 PyErr_SetString(PyExc_ValueError, "No such digest method");
637 return NULL;
638 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700639
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400640 EVP_SignInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100641 EVP_SignUpdate(&md_ctx, data, data_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400642 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400643 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700644
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400645 if (err != 1) {
646 exception_from_error_queue(crypto_Error);
647 return NULL;
648 }
649
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400650 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400651 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700652}
653
654static char crypto_verify_doc[] = "\n\
655Verify a signature\n\
656\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900657:param cert: signing certificate (X509 object)\n\
658:param signature: signature returned by sign function\n\
659:param data: data to be verified\n\
660:param digest: message digest to use\n\
661:return: None if the signature is correct, raise exception otherwise\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700662";
663
664static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400665crypto_verify(PyObject *spam, PyObject *args) {
666 crypto_X509Obj *cert;
667 unsigned char *signature;
668 int sig_len;
669 char *data, *digest_name;
David Brodsky5c019772010-12-07 20:08:50 +0100670 int data_len;
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400671 int err;
672 const EVP_MD *digest;
673 EVP_MD_CTX md_ctx;
674 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700675
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400676#ifdef PY3
David Brodsky5c019772010-12-07 20:08:50 +0100677 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 -0400678#else
David Brodsky5c019772010-12-07 20:08:50 +0100679 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 -0400680#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400681 return NULL;
682 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700683
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400684 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
685 PyErr_SetString(PyExc_ValueError, "No such digest method");
686 return NULL;
687 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700688
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400689 pkey = X509_get_pubkey(cert->x509);
690 if (pkey == NULL) {
691 PyErr_SetString(PyExc_ValueError, "No public key");
692 return NULL;
693 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700694
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400695 EVP_VerifyInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100696 EVP_VerifyUpdate(&md_ctx, data, data_len);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400697 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
698 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700699
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400700 if (err != 1) {
701 exception_from_error_queue(crypto_Error);
702 return NULL;
703 }
704
705 Py_INCREF(Py_None);
706 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700707}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400708
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500709/* Methods in the OpenSSL.crypto module (i.e. none) */
710static PyMethodDef crypto_methods[] = {
711 /* Module functions */
712 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
713 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
714 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
715 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
716 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
717 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500718 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500719 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
720 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700721 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
722 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500723 { "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 -0400724 { "_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 -0500725 { NULL, NULL }
726};
727
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400728
729#ifdef WITH_THREAD
730
731#include <pythread.h>
732
733/**
734 * This array will store all of the mutexes available to OpenSSL.
735 */
736static PyThread_type_lock *mutex_buf = NULL;
737
738
739/**
740 * Callback function supplied to OpenSSL to acquire or release a lock.
741 *
742 */
743static void locking_function(int mode, int n, const char * file, int line) {
744 if (mode & CRYPTO_LOCK) {
745 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
746 } else {
747 PyThread_release_lock(mutex_buf[n]);
748 }
749}
750
751
752/**
753 * Initialize OpenSSL for use from multiple threads.
754 *
755 * Returns: 0 if initialization fails, 1 otherwise.
756 */
757static int init_openssl_threads(void) {
758 int i;
759
760 mutex_buf = (PyThread_type_lock *)malloc(
761 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
762 if (!mutex_buf) {
763 return 0;
764 }
765 for (i = 0; i < CRYPTO_num_locks(); ++i) {
766 mutex_buf[i] = PyThread_allocate_lock();
767 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500768 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400769 CRYPTO_set_locking_callback(locking_function);
770 return 1;
771}
772
773/* /\** */
774/* * Clean up after OpenSSL thread initialization. */
775/* *\/ */
776/* static int deinit_openssl_threads() { */
777/* int i; */
778
779/* if (!mutex_buf) { */
780/* return 0; */
781/* } */
782/* CRYPTO_set_id_callback(NULL); */
783/* CRYPTO_set_locking_callback(NULL); */
784/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
785/* PyThread_free_lock(mutex_buf[i]); */
786/* } */
787/* free(mutex_buf); */
788/* mutex_buf = NULL; */
789/* return 1; */
790/* } */
791
792#endif
793
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400794#ifdef PY3
795static struct PyModuleDef cryptomodule = {
796 PyModuleDef_HEAD_INIT,
797 "crypto",
798 crypto_doc,
799 -1,
800 crypto_methods
801};
802#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400803
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500804/*
805 * Initialize crypto sub module
806 *
807 * Arguments: None
808 * Returns: None
809 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400810PyOpenSSL_MODINIT(crypto) {
811#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500812 static void *crypto_API[crypto_API_pointers];
813 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400814#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400815 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500816
817 ERR_load_crypto_strings();
818 OpenSSL_add_all_algorithms();
819
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400820#ifdef PY3
821 module = PyModule_Create(&cryptomodule);
822#else
823 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
824#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500825
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400826 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400827 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400828 }
829
830#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500831 /* Initialize the C API pointer array */
832 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
833 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
834 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
835 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
836 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
837 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
838 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
839 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
840 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500841 if (c_api_object != NULL) {
842 /* PyModule_AddObject steals a reference.
843 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400844 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500845 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500846 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400847#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500848
849 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
850 if (crypto_Error == NULL)
851 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500852
853 /* PyModule_AddObject steals a reference.
854 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400855 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500856 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
857 goto error;
858
859 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
860 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500861 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500862
863 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
864 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
865
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400866#ifdef WITH_THREAD
867 if (!init_openssl_threads())
868 goto error;
869#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400870 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500871 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400872 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500873 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400874 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500875 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400876 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500877 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400878 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500879 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400880 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500881 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400882 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500883 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400884 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500885 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400886 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500887 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500888 if (!init_crypto_crl(module))
889 goto error;
890 if (!init_crypto_revoked(module))
891 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400892
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400893 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400894
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500895error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400896 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500897 ;
898}