blob: d642dc6812138b9a0b0d897dc020756465971947 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * crypto.c
3 *
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05004 * Copyright (C) AB Strakt
5 * Copyright (C) Keyphrene
6 * Copyright (C) Jean-Paul Calderone
7 * See LICENSE for details.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05008 *
9 * Main file of crypto sub module.
10 * See the file RATIONALE for a short explanation of why this module was written.
11 *
12 * Reviewed 2001-07-23
13 */
14#include <Python.h>
15#define crypto_MODULE
16#include "crypto.h"
Rick Dean623ee362009-07-17 12:22:16 -050017#include "pkcs12.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050018
19static char crypto_doc[] = "\n\
20Main file of crypto sub module.\n\
21See the file RATIONALE for a short explanation of why this module was written.\n\
22";
23
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050024void **ssl_API;
25
26PyObject *crypto_Error;
27
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -040028int crypto_byte_converter(PyObject *input, void* output) {
29 char **message = output;
30 if (input == Py_None) {
31 *message = NULL;
32 } else if (PyBytes_CheckExact(input)) {
33 *message = PyBytes_AsString(input);
34 } else {
35 return 0;
36 }
37 return 1;
38}
39
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050040static int
41global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
42{
43 PyObject *func, *argv, *ret;
44 int nchars;
45
46 func = (PyObject *)cb_arg;
47 argv = Py_BuildValue("(i)", rwflag);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010048 if (argv == NULL) {
49 return 0;
50 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050051 ret = PyEval_CallObject(func, argv);
52 Py_DECREF(argv);
53 if (ret == NULL)
54 return 0;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040055 if (!PyBytes_Check(ret))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050056 {
Ziga Seilnacht781295a2009-12-22 14:58:01 +010057 Py_DECREF(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050058 PyErr_SetString(PyExc_ValueError, "String expected");
59 return 0;
60 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040061 nchars = PyBytes_Size(ret);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010062 if (nchars > len) {
63 Py_DECREF(ret);
64 PyErr_SetString(PyExc_ValueError,
65 "passphrase returned by callback is too long");
66 return 0;
67 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040068 strncpy(buf, PyBytes_AsString(ret), nchars);
Ziga Seilnacht781295a2009-12-22 14:58:01 +010069 Py_DECREF(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050070 return nchars;
71}
72
Ziga Seilnacht6b90a402009-12-22 14:33:47 +010073static PyObject *
74raise_current_error(void)
75{
76 if (PyErr_Occurred()) {
77 /*
78 * The python exception from callback is more informative than
79 * OpenSSL's error.
80 */
81 flush_error_queue();
82 return NULL;
83 }
84 exception_from_error_queue(crypto_Error);
85 return NULL;
86}
87
Ziga Seilnacht376cf972009-12-22 16:04:10 +010088static int
89setup_callback(int type, PyObject *pw, pem_password_cb **cb, void **cb_arg) {
90 if (pw == NULL) {
91 *cb = NULL;
92 *cb_arg = NULL;
93 return 1;
94 }
95 if (type != X509_FILETYPE_PEM) {
96 PyErr_SetString(PyExc_ValueError,
97 "only FILETYPE_PEM key format supports encryption");
98 return 0;
99 }
100 if (PyBytes_Check(pw)) {
101 *cb = NULL;
102 *cb_arg = PyBytes_AsString(pw);
103 } else if (PyCallable_Check(pw)) {
104 *cb = global_passphrase_callback;
105 *cb_arg = pw;
106 } else {
107 PyErr_SetString(PyExc_TypeError,
108 "Last argument must be string or callable");
109 return 0;
110 }
111 return 1;
112}
113
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500114static char crypto_load_privatekey_doc[] = "\n\
115Load a private key from a buffer\n\
116\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900117:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
118:param buffer: The buffer the key is stored in\n\
119:param passphrase: (optional) if encrypted PEM format, this can be\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400120 either the passphrase to use, or a callback for\n\
121 providing the passphrase.\n\
122\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900123:return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500124";
125
126static PyObject *
127crypto_load_privatekey(PyObject *spam, PyObject *args)
128{
129 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
130 int type, len;
131 char *buffer;
132 PyObject *pw = NULL;
133 pem_password_cb *cb = NULL;
134 void *cb_arg = NULL;
135 BIO *bio;
136 EVP_PKEY *pkey;
137
138 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
139 return NULL;
140
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100141 if (!setup_callback(type, pw, &cb, &cb_arg)) {
142 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500143 }
144
145 bio = BIO_new_mem_buf(buffer, len);
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100146 if (bio == NULL) {
147 exception_from_error_queue(crypto_Error);
148 return NULL;
149 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500150 switch (type)
151 {
152 case X509_FILETYPE_PEM:
153 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
154 break;
155
156 case X509_FILETYPE_ASN1:
157 pkey = d2i_PrivateKey_bio(bio, NULL);
158 break;
159
160 default:
161 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
162 BIO_free(bio);
163 return NULL;
164 }
165 BIO_free(bio);
166
167 if (pkey == NULL)
168 {
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100169 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500170 }
171
172 return (PyObject *)crypto_PKey_New(pkey, 1);
173}
174
175static char crypto_dump_privatekey_doc[] = "\n\
176Dump a private key to a buffer\n\
177\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900178:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
179:param pkey: The PKey to dump\n\
180:param cipher: (optional) if encrypted PEM format, the cipher to\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400181 use\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900182:param passphrase: (optional) if encrypted PEM format, this can be either\n\
183 the passphrase to use, or a callback for providing the\n\
184 passphrase.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900185:return: The buffer with the dumped key in\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900186:rtype: :py:data:`str`\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500187";
188
189static PyObject *
190crypto_dump_privatekey(PyObject *spam, PyObject *args)
191{
192 int type, ret, buf_len;
193 char *temp;
194 PyObject *buffer;
195 char *cipher_name = NULL;
196 const EVP_CIPHER *cipher = NULL;
197 PyObject *pw = NULL;
198 pem_password_cb *cb = NULL;
199 void *cb_arg = NULL;
200 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500201 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500202 crypto_PKeyObj *pkey;
203
204 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
205 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
206 return NULL;
207
208 if (cipher_name != NULL && pw == NULL)
209 {
210 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
211 return NULL;
212 }
213 if (cipher_name != NULL)
214 {
215 cipher = EVP_get_cipherbyname(cipher_name);
216 if (cipher == NULL)
217 {
218 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
219 return NULL;
220 }
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100221 if (!setup_callback(type, pw, &cb, &cb_arg)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500222 return NULL;
223 }
224 }
225
226 bio = BIO_new(BIO_s_mem());
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100227 if (bio == NULL) {
228 exception_from_error_queue(crypto_Error);
229 return NULL;
230 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500231 switch (type)
232 {
233 case X509_FILETYPE_PEM:
234 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500235 break;
236
237 case X509_FILETYPE_ASN1:
238 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
239 break;
240
Rick Dean5b7b6372009-04-01 11:34:06 -0500241 case X509_FILETYPE_TEXT:
242 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100243 if (rsa == NULL) {
244 ret = 0;
245 break;
246 }
Rick Dean5b7b6372009-04-01 11:34:06 -0500247 ret = RSA_print(bio, rsa, 0);
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100248 RSA_free(rsa);
Rick Dean5b7b6372009-04-01 11:34:06 -0500249 break;
250
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500251 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500252 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500253 BIO_free(bio);
254 return NULL;
255 }
256
257 if (ret == 0)
258 {
259 BIO_free(bio);
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100260 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500261 }
262
263 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400264 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500265 BIO_free(bio);
266
267 return buffer;
268}
269
270static char crypto_load_certificate_doc[] = "\n\
271Load a certificate from a buffer\n\
272\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900273:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500274 buffer - The buffer the certificate is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900275:return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500276";
277
278static PyObject *
279crypto_load_certificate(PyObject *spam, PyObject *args)
280{
281 crypto_X509Obj *crypto_X509_New(X509 *, int);
282 int type, len;
283 char *buffer;
284 BIO *bio;
285 X509 *cert;
286
287 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
288 return NULL;
289
290 bio = BIO_new_mem_buf(buffer, len);
291 switch (type)
292 {
293 case X509_FILETYPE_PEM:
294 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
295 break;
296
297 case X509_FILETYPE_ASN1:
298 cert = d2i_X509_bio(bio, NULL);
299 break;
300
301 default:
302 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
303 BIO_free(bio);
304 return NULL;
305 }
306 BIO_free(bio);
307
308 if (cert == NULL)
309 {
Rick Deand369c932009-07-08 11:48:33 -0500310 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500311 return NULL;
312 }
313
314 return (PyObject *)crypto_X509_New(cert, 1);
315}
316
317static char crypto_dump_certificate_doc[] = "\n\
318Dump a certificate to a buffer\n\
319\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900320:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
321:param cert: The certificate to dump\n\
322:return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500323";
324
325static PyObject *
326crypto_dump_certificate(PyObject *spam, PyObject *args)
327{
328 int type, ret, buf_len;
329 char *temp;
330 PyObject *buffer;
331 BIO *bio;
332 crypto_X509Obj *cert;
333
334 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
335 &crypto_X509_Type, &cert))
336 return NULL;
337
338 bio = BIO_new(BIO_s_mem());
339 switch (type)
340 {
341 case X509_FILETYPE_PEM:
342 ret = PEM_write_bio_X509(bio, cert->x509);
343 break;
344
345 case X509_FILETYPE_ASN1:
346 ret = i2d_X509_bio(bio, cert->x509);
347 break;
348
Rick Dean5b7b6372009-04-01 11:34:06 -0500349 case X509_FILETYPE_TEXT:
350 ret = X509_print_ex(bio, cert->x509, 0, 0);
351 break;
352
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500353 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500354 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500355 BIO_free(bio);
356 return NULL;
357 }
358
359 if (ret == 0)
360 {
361 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500362 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500363 return NULL;
364 }
365
366 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400367 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500368 BIO_free(bio);
369
370 return buffer;
371}
372
373static char crypto_load_certificate_request_doc[] = "\n\
374Load a certificate request from a buffer\n\
375\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900376:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500377 buffer - The buffer the certificate request is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900378:return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500379";
380
381static PyObject *
382crypto_load_certificate_request(PyObject *spam, PyObject *args)
383{
384 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
385 int type, len;
386 char *buffer;
387 BIO *bio;
388 X509_REQ *req;
389
390 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
391 return NULL;
392
393 bio = BIO_new_mem_buf(buffer, len);
394 switch (type)
395 {
396 case X509_FILETYPE_PEM:
397 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
398 break;
399
400 case X509_FILETYPE_ASN1:
401 req = d2i_X509_REQ_bio(bio, NULL);
402 break;
403
404 default:
405 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
406 BIO_free(bio);
407 return NULL;
408 }
409 BIO_free(bio);
410
411 if (req == NULL)
412 {
Rick Deand369c932009-07-08 11:48:33 -0500413 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500414 return NULL;
415 }
416
417 return (PyObject *)crypto_X509Req_New(req, 1);
418}
419
420static char crypto_dump_certificate_request_doc[] = "\n\
421Dump a certificate request to a buffer\n\
422\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900423:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500424 req - The certificate request to dump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900425:return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500426";
427
428static PyObject *
429crypto_dump_certificate_request(PyObject *spam, PyObject *args)
430{
431 int type, ret, buf_len;
432 char *temp;
433 PyObject *buffer;
434 BIO *bio;
435 crypto_X509ReqObj *req;
436
437 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
438 &crypto_X509Req_Type, &req))
439 return NULL;
440
441 bio = BIO_new(BIO_s_mem());
442 switch (type)
443 {
444 case X509_FILETYPE_PEM:
445 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
446 break;
447
448 case X509_FILETYPE_ASN1:
449 ret = i2d_X509_REQ_bio(bio, req->x509_req);
450 break;
451
Rick Dean5b7b6372009-04-01 11:34:06 -0500452 case X509_FILETYPE_TEXT:
453 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
454 break;
455
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500456 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500457 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500458 BIO_free(bio);
459 return NULL;
460 }
461
462 if (ret == 0)
463 {
464 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500465 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500466 return NULL;
467 }
468
469 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400470 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500471 BIO_free(bio);
472
473 return buffer;
474}
475
Rick Dean536ba022009-07-24 23:57:27 -0500476static char crypto_load_crl_doc[] = "\n\
477Load a certificate revocation list from a buffer\n\
478\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900479:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
480:param buffer: The buffer the CRL is stored in\n\
Rick Dean536ba022009-07-24 23:57:27 -0500481\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900482:return: The PKey object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500483";
484
485static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400486crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500487 int type, len;
488 char *buffer;
489 BIO *bio;
490 X509_CRL *crl;
491
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400492 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500493 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400494 }
Rick Dean536ba022009-07-24 23:57:27 -0500495
496 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400497 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500498 case X509_FILETYPE_PEM:
499 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
500 break;
501
502 case X509_FILETYPE_ASN1:
503 crl = d2i_X509_CRL_bio(bio, NULL);
504 break;
505
506 default:
507 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
508 BIO_free(bio);
509 return NULL;
510 }
511 BIO_free(bio);
512
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400513 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500514 exception_from_error_queue(crypto_Error);
515 return NULL;
516 }
517
518 return (PyObject *)crypto_CRL_New(crl);
519}
520
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500521static char crypto_load_pkcs7_data_doc[] = "\n\
522Load pkcs7 data from a buffer\n\
523\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900524:param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500525 buffer - The buffer with the pkcs7 data.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900526:return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500527";
528
529static PyObject *
530crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
531{
532 int type, len;
533 char *buffer;
534 BIO *bio;
535 PKCS7 *pkcs7 = NULL;
536
537 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
538 return NULL;
539
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100540 /*
541 * Try to read the pkcs7 data from the bio
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500542 */
543 bio = BIO_new_mem_buf(buffer, len);
544 switch (type)
545 {
546 case X509_FILETYPE_PEM:
547 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
548 break;
549
550 case X509_FILETYPE_ASN1:
551 pkcs7 = d2i_PKCS7_bio(bio, NULL);
552 break;
553
554 default:
555 PyErr_SetString(PyExc_ValueError,
556 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
557 return NULL;
558 }
559 BIO_free(bio);
560
561 /*
562 * Check if we got a PKCS7 structure
563 */
564 if (pkcs7 == NULL)
565 {
Rick Deand369c932009-07-08 11:48:33 -0500566 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500567 return NULL;
568 }
569
570 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
571}
572
573static char crypto_load_pkcs12_doc[] = "\n\
574Load a PKCS12 object from a buffer\n\
575\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900576:param buffer: The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400577 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900578:returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500579";
580
581static PyObject *
582crypto_load_pkcs12(PyObject *spam, PyObject *args)
583{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500584 int len;
585 char *buffer, *passphrase = NULL;
586 BIO *bio;
587 PKCS12 *p12;
588
589 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
590 return NULL;
591
592 bio = BIO_new_mem_buf(buffer, len);
593 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
594 {
595 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500596 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500597 return NULL;
598 }
599 BIO_free(bio);
600
601 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
602}
603
604
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500605static char crypto_X509_verify_cert_error_string_doc[] = "\n\
606Get X509 verify certificate error string.\n\
607\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900608:param errnum: The error number.\n\
609:return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500610";
611
612static PyObject *
613crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
614{
615 int errnum;
616 const char *str;
617
618 if (!PyArg_ParseTuple(args, "i", &errnum))
619 return NULL;
620
621 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400622 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500623}
624
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400625static char crypto_exception_from_error_queue_doc[] = "\n\
626Raise an exception from the current OpenSSL error queue.\n\
627";
628
629static PyObject *
630crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
631 exception_from_error_queue(crypto_Error);
632 return NULL;
633}
634
James Yonan7c2e5d32010-02-27 05:45:50 -0700635static char crypto_sign_doc[] = "\n\
636Sign data with a digest\n\
637\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900638:param pkey: Pkey to sign with\n\
639:param data: data to be signed\n\
640:param digest: message digest to use\n\
641:return: signature\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700642";
643
644static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400645crypto_sign(PyObject *spam, PyObject *args) {
646 PyObject *buffer;
647 crypto_PKeyObj *pkey;
648 char *data = NULL;
David Brodsky5c019772010-12-07 20:08:50 +0100649 int data_len;
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400650 char *digest_name;
651 int err;
652 unsigned int sig_len;
653 const EVP_MD *digest;
654 EVP_MD_CTX md_ctx;
655 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700656
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400657 if (!PyArg_ParseTuple(
David Brodsky5c019772010-12-07 20:08:50 +0100658 args, "O!" BYTESTRING_FMT "#s:sign", &crypto_PKey_Type,
659 &pkey, &data, &data_len, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400660 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700661 }
662
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400663 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
664 PyErr_SetString(PyExc_ValueError, "No such digest method");
665 return NULL;
666 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700667
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400668 EVP_SignInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100669 EVP_SignUpdate(&md_ctx, data, data_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400670 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400671 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700672
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400673 if (err != 1) {
674 exception_from_error_queue(crypto_Error);
675 return NULL;
676 }
677
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400678 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400679 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700680}
681
682static char crypto_verify_doc[] = "\n\
683Verify a signature\n\
684\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900685:param cert: signing certificate (X509 object)\n\
686:param signature: signature returned by sign function\n\
687:param data: data to be verified\n\
688:param digest: message digest to use\n\
689:return: None if the signature is correct, raise exception otherwise\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700690";
691
692static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400693crypto_verify(PyObject *spam, PyObject *args) {
694 crypto_X509Obj *cert;
695 unsigned char *signature;
696 int sig_len;
697 char *data, *digest_name;
David Brodsky5c019772010-12-07 20:08:50 +0100698 int data_len;
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400699 int err;
700 const EVP_MD *digest;
701 EVP_MD_CTX md_ctx;
702 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700703
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400704#ifdef PY3
David Brodsky5c019772010-12-07 20:08:50 +0100705 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 -0400706#else
David Brodsky5c019772010-12-07 20:08:50 +0100707 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 -0400708#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400709 return NULL;
710 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700711
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400712 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
713 PyErr_SetString(PyExc_ValueError, "No such digest method");
714 return NULL;
715 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700716
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400717 pkey = X509_get_pubkey(cert->x509);
718 if (pkey == NULL) {
719 PyErr_SetString(PyExc_ValueError, "No public key");
720 return NULL;
721 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700722
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400723 EVP_VerifyInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100724 EVP_VerifyUpdate(&md_ctx, data, data_len);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400725 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
726 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700727
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400728 if (err != 1) {
729 exception_from_error_queue(crypto_Error);
730 return NULL;
731 }
732
733 Py_INCREF(Py_None);
734 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700735}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400736
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500737/* Methods in the OpenSSL.crypto module (i.e. none) */
738static PyMethodDef crypto_methods[] = {
739 /* Module functions */
740 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
741 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
742 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
743 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
744 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
745 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500746 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500747 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
748 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700749 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
750 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500751 { "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 -0400752 { "_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 -0500753 { NULL, NULL }
754};
755
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400756
757#ifdef WITH_THREAD
758
759#include <pythread.h>
760
761/**
762 * This array will store all of the mutexes available to OpenSSL.
763 */
764static PyThread_type_lock *mutex_buf = NULL;
765
766
767/**
768 * Callback function supplied to OpenSSL to acquire or release a lock.
769 *
770 */
771static void locking_function(int mode, int n, const char * file, int line) {
772 if (mode & CRYPTO_LOCK) {
773 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
774 } else {
775 PyThread_release_lock(mutex_buf[n]);
776 }
777}
778
779
780/**
781 * Initialize OpenSSL for use from multiple threads.
782 *
783 * Returns: 0 if initialization fails, 1 otherwise.
784 */
785static int init_openssl_threads(void) {
786 int i;
787
788 mutex_buf = (PyThread_type_lock *)malloc(
789 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
790 if (!mutex_buf) {
791 return 0;
792 }
793 for (i = 0; i < CRYPTO_num_locks(); ++i) {
794 mutex_buf[i] = PyThread_allocate_lock();
795 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500796 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400797 CRYPTO_set_locking_callback(locking_function);
798 return 1;
799}
800
801/* /\** */
802/* * Clean up after OpenSSL thread initialization. */
803/* *\/ */
804/* static int deinit_openssl_threads() { */
805/* int i; */
806
807/* if (!mutex_buf) { */
808/* return 0; */
809/* } */
810/* CRYPTO_set_id_callback(NULL); */
811/* CRYPTO_set_locking_callback(NULL); */
812/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
813/* PyThread_free_lock(mutex_buf[i]); */
814/* } */
815/* free(mutex_buf); */
816/* mutex_buf = NULL; */
817/* return 1; */
818/* } */
819
820#endif
821
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400822#ifdef PY3
823static struct PyModuleDef cryptomodule = {
824 PyModuleDef_HEAD_INIT,
825 "crypto",
826 crypto_doc,
827 -1,
828 crypto_methods
829};
830#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400831
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500832/*
833 * Initialize crypto sub module
834 *
835 * Arguments: None
836 * Returns: None
837 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400838PyOpenSSL_MODINIT(crypto) {
839#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500840 static void *crypto_API[crypto_API_pointers];
841 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400842#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400843 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500844
845 ERR_load_crypto_strings();
846 OpenSSL_add_all_algorithms();
847
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400848#ifdef PY3
849 module = PyModule_Create(&cryptomodule);
850#else
851 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
852#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500853
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400854 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400855 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400856 }
857
858#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500859 /* Initialize the C API pointer array */
860 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
861 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
862 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
863 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
864 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
865 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
866 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
867 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
868 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500869 if (c_api_object != NULL) {
870 /* PyModule_AddObject steals a reference.
871 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400872 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500873 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500874 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400875#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500876
877 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
878 if (crypto_Error == NULL)
879 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500880
881 /* PyModule_AddObject steals a reference.
882 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400883 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500884 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
885 goto error;
886
887 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
888 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500889 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500890
891 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
892 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
893
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400894#ifdef WITH_THREAD
895 if (!init_openssl_threads())
896 goto error;
897#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400898 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500899 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400900 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500901 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400902 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500903 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400904 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500905 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400906 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500907 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400908 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500909 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400910 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500911 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400912 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500913 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400914 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500915 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500916 if (!init_crypto_crl(module))
917 goto error;
918 if (!init_crypto_revoked(module))
919 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400920
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400921 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400922
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500923error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400924 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500925 ;
926}