blob: ad35ce986960a2dd6febae7ec5f3403821625435 [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);
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +010053 if (ret == NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050054 return 0;
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +010055 }
56 if (!PyBytes_Check(ret)) {
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
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100138 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey",
139 &type, &buffer, &len, &pw)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500140 return NULL;
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100141 }
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100142 if (!setup_callback(type, pw, &cb, &cb_arg)) {
143 return NULL;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500144 }
145
146 bio = BIO_new_mem_buf(buffer, len);
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100147 if (bio == NULL) {
148 exception_from_error_queue(crypto_Error);
149 return NULL;
150 }
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100151 switch (type) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500152 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
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100167 if (pkey == NULL) {
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100168 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500169 }
170
171 return (PyObject *)crypto_PKey_New(pkey, 1);
172}
173
174static char crypto_dump_privatekey_doc[] = "\n\
175Dump a private key to a buffer\n\
176\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900177:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
178:param pkey: The PKey to dump\n\
179:param cipher: (optional) if encrypted PEM format, the cipher to\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400180 use\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900181:param passphrase: (optional) if encrypted PEM format, this can be either\n\
182 the passphrase to use, or a callback for providing the\n\
183 passphrase.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900184:return: The buffer with the dumped key in\n\
Jonathan Ballet648875f2011-07-16 14:14:58 +0900185:rtype: :py:data:`str`\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500186";
187
188static PyObject *
189crypto_dump_privatekey(PyObject *spam, PyObject *args)
190{
191 int type, ret, buf_len;
192 char *temp;
193 PyObject *buffer;
194 char *cipher_name = NULL;
195 const EVP_CIPHER *cipher = NULL;
196 PyObject *pw = NULL;
197 pem_password_cb *cb = NULL;
198 void *cb_arg = NULL;
199 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500200 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500201 crypto_PKeyObj *pkey;
202
203 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100204 &crypto_PKey_Type, &pkey, &cipher_name, &pw)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500205 return NULL;
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100206 }
207 if (cipher_name != NULL && pw == NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500208 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
209 return NULL;
210 }
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100211 if (cipher_name != NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500212 cipher = EVP_get_cipherbyname(cipher_name);
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100213 if (cipher == NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500214 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
215 return NULL;
216 }
Ziga Seilnacht376cf972009-12-22 16:04:10 +0100217 if (!setup_callback(type, pw, &cb, &cb_arg)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500218 return NULL;
219 }
220 }
221
222 bio = BIO_new(BIO_s_mem());
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100223 if (bio == NULL) {
224 exception_from_error_queue(crypto_Error);
225 return NULL;
226 }
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100227 switch (type) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500228 case X509_FILETYPE_PEM:
229 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500230 break;
231
232 case X509_FILETYPE_ASN1:
233 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
234 break;
235
Rick Dean5b7b6372009-04-01 11:34:06 -0500236 case X509_FILETYPE_TEXT:
237 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
Ziga Seilnachtcd48be92009-12-22 16:54:20 +0100238 if (rsa == NULL) {
239 ret = 0;
240 break;
241 }
Rick Dean5b7b6372009-04-01 11:34:06 -0500242 ret = RSA_print(bio, rsa, 0);
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100243 RSA_free(rsa);
Rick Dean5b7b6372009-04-01 11:34:06 -0500244 break;
245
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500246 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500247 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500248 BIO_free(bio);
249 return NULL;
250 }
251
Ziga Seilnacht1a71a4a2009-12-22 17:02:04 +0100252 if (ret == 0) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500253 BIO_free(bio);
Ziga Seilnacht6b90a402009-12-22 14:33:47 +0100254 return raise_current_error();
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500255 }
256
257 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400258 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500259 BIO_free(bio);
260
261 return buffer;
262}
263
264static char crypto_load_certificate_doc[] = "\n\
265Load a certificate from a buffer\n\
266\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900267:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500268 buffer - The buffer the certificate is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900269:return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500270";
271
272static PyObject *
273crypto_load_certificate(PyObject *spam, PyObject *args)
274{
275 crypto_X509Obj *crypto_X509_New(X509 *, int);
276 int type, len;
277 char *buffer;
278 BIO *bio;
279 X509 *cert;
280
281 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
282 return NULL;
283
284 bio = BIO_new_mem_buf(buffer, len);
285 switch (type)
286 {
287 case X509_FILETYPE_PEM:
288 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
289 break;
290
291 case X509_FILETYPE_ASN1:
292 cert = d2i_X509_bio(bio, NULL);
293 break;
294
295 default:
296 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
297 BIO_free(bio);
298 return NULL;
299 }
300 BIO_free(bio);
301
302 if (cert == NULL)
303 {
Rick Deand369c932009-07-08 11:48:33 -0500304 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500305 return NULL;
306 }
307
308 return (PyObject *)crypto_X509_New(cert, 1);
309}
310
311static char crypto_dump_certificate_doc[] = "\n\
312Dump a certificate to a buffer\n\
313\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900314:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
315:param cert: The certificate to dump\n\
316:return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500317";
318
319static PyObject *
320crypto_dump_certificate(PyObject *spam, PyObject *args)
321{
322 int type, ret, buf_len;
323 char *temp;
324 PyObject *buffer;
325 BIO *bio;
326 crypto_X509Obj *cert;
327
328 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
329 &crypto_X509_Type, &cert))
330 return NULL;
331
332 bio = BIO_new(BIO_s_mem());
333 switch (type)
334 {
335 case X509_FILETYPE_PEM:
336 ret = PEM_write_bio_X509(bio, cert->x509);
337 break;
338
339 case X509_FILETYPE_ASN1:
340 ret = i2d_X509_bio(bio, cert->x509);
341 break;
342
Rick Dean5b7b6372009-04-01 11:34:06 -0500343 case X509_FILETYPE_TEXT:
344 ret = X509_print_ex(bio, cert->x509, 0, 0);
345 break;
346
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500347 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500348 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500349 BIO_free(bio);
350 return NULL;
351 }
352
353 if (ret == 0)
354 {
355 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500356 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500357 return NULL;
358 }
359
360 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400361 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500362 BIO_free(bio);
363
364 return buffer;
365}
366
367static char crypto_load_certificate_request_doc[] = "\n\
368Load a certificate request from a buffer\n\
369\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900370:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500371 buffer - The buffer the certificate request is stored in\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900372:return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500373";
374
375static PyObject *
376crypto_load_certificate_request(PyObject *spam, PyObject *args)
377{
378 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
379 int type, len;
380 char *buffer;
381 BIO *bio;
382 X509_REQ *req;
383
384 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
385 return NULL;
386
387 bio = BIO_new_mem_buf(buffer, len);
388 switch (type)
389 {
390 case X509_FILETYPE_PEM:
391 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
392 break;
393
394 case X509_FILETYPE_ASN1:
395 req = d2i_X509_REQ_bio(bio, NULL);
396 break;
397
398 default:
399 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
400 BIO_free(bio);
401 return NULL;
402 }
403 BIO_free(bio);
404
405 if (req == NULL)
406 {
Rick Deand369c932009-07-08 11:48:33 -0500407 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500408 return NULL;
409 }
410
411 return (PyObject *)crypto_X509Req_New(req, 1);
412}
413
414static char crypto_dump_certificate_request_doc[] = "\n\
415Dump a certificate request to a buffer\n\
416\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900417:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500418 req - The certificate request to dump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900419:return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500420";
421
422static PyObject *
423crypto_dump_certificate_request(PyObject *spam, PyObject *args)
424{
425 int type, ret, buf_len;
426 char *temp;
427 PyObject *buffer;
428 BIO *bio;
429 crypto_X509ReqObj *req;
430
431 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
432 &crypto_X509Req_Type, &req))
433 return NULL;
434
435 bio = BIO_new(BIO_s_mem());
436 switch (type)
437 {
438 case X509_FILETYPE_PEM:
439 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
440 break;
441
442 case X509_FILETYPE_ASN1:
443 ret = i2d_X509_REQ_bio(bio, req->x509_req);
444 break;
445
Rick Dean5b7b6372009-04-01 11:34:06 -0500446 case X509_FILETYPE_TEXT:
447 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
448 break;
449
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500450 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500451 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500452 BIO_free(bio);
453 return NULL;
454 }
455
456 if (ret == 0)
457 {
458 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500459 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500460 return NULL;
461 }
462
463 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400464 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500465 BIO_free(bio);
466
467 return buffer;
468}
469
Rick Dean536ba022009-07-24 23:57:27 -0500470static char crypto_load_crl_doc[] = "\n\
471Load a certificate revocation list from a buffer\n\
472\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900473:param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
474:param buffer: The buffer the CRL is stored in\n\
Rick Dean536ba022009-07-24 23:57:27 -0500475\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900476:return: The PKey object\n\
Rick Dean536ba022009-07-24 23:57:27 -0500477";
478
479static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400480crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500481 int type, len;
482 char *buffer;
483 BIO *bio;
484 X509_CRL *crl;
485
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400486 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500487 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400488 }
Rick Dean536ba022009-07-24 23:57:27 -0500489
490 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400491 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500492 case X509_FILETYPE_PEM:
493 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
494 break;
495
496 case X509_FILETYPE_ASN1:
497 crl = d2i_X509_CRL_bio(bio, NULL);
498 break;
499
500 default:
501 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
502 BIO_free(bio);
503 return NULL;
504 }
505 BIO_free(bio);
506
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400507 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500508 exception_from_error_queue(crypto_Error);
509 return NULL;
510 }
511
512 return (PyObject *)crypto_CRL_New(crl);
513}
514
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500515static char crypto_load_pkcs7_data_doc[] = "\n\
516Load pkcs7 data from a buffer\n\
517\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900518:param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500519 buffer - The buffer with the pkcs7 data.\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900520:return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500521";
522
523static PyObject *
524crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
525{
526 int type, len;
527 char *buffer;
528 BIO *bio;
529 PKCS7 *pkcs7 = NULL;
530
531 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
532 return NULL;
533
Ziga Seilnachtcccb6962009-12-22 14:06:31 +0100534 /*
535 * Try to read the pkcs7 data from the bio
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500536 */
537 bio = BIO_new_mem_buf(buffer, len);
538 switch (type)
539 {
540 case X509_FILETYPE_PEM:
541 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
542 break;
543
544 case X509_FILETYPE_ASN1:
545 pkcs7 = d2i_PKCS7_bio(bio, NULL);
546 break;
547
548 default:
549 PyErr_SetString(PyExc_ValueError,
550 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
551 return NULL;
552 }
553 BIO_free(bio);
554
555 /*
556 * Check if we got a PKCS7 structure
557 */
558 if (pkcs7 == NULL)
559 {
Rick Deand369c932009-07-08 11:48:33 -0500560 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500561 return NULL;
562 }
563
564 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
565}
566
567static char crypto_load_pkcs12_doc[] = "\n\
568Load a PKCS12 object from a buffer\n\
569\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900570:param buffer: The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400571 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900572:returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500573";
574
575static PyObject *
576crypto_load_pkcs12(PyObject *spam, PyObject *args)
577{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500578 int len;
579 char *buffer, *passphrase = NULL;
580 BIO *bio;
581 PKCS12 *p12;
582
583 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
584 return NULL;
585
586 bio = BIO_new_mem_buf(buffer, len);
587 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
588 {
589 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500590 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500591 return NULL;
592 }
593 BIO_free(bio);
594
595 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
596}
597
598
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500599static char crypto_X509_verify_cert_error_string_doc[] = "\n\
600Get X509 verify certificate error string.\n\
601\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900602:param errnum: The error number.\n\
603:return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500604";
605
606static PyObject *
607crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
608{
609 int errnum;
610 const char *str;
611
612 if (!PyArg_ParseTuple(args, "i", &errnum))
613 return NULL;
614
615 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400616 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500617}
618
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400619static char crypto_exception_from_error_queue_doc[] = "\n\
620Raise an exception from the current OpenSSL error queue.\n\
621";
622
623static PyObject *
624crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
625 exception_from_error_queue(crypto_Error);
626 return NULL;
627}
628
James Yonan7c2e5d32010-02-27 05:45:50 -0700629static char crypto_sign_doc[] = "\n\
630Sign data with a digest\n\
631\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900632:param pkey: Pkey to sign with\n\
633:param data: data to be signed\n\
634:param digest: message digest to use\n\
635:return: signature\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700636";
637
638static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400639crypto_sign(PyObject *spam, PyObject *args) {
640 PyObject *buffer;
641 crypto_PKeyObj *pkey;
642 char *data = NULL;
David Brodsky5c019772010-12-07 20:08:50 +0100643 int data_len;
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400644 char *digest_name;
645 int err;
646 unsigned int sig_len;
647 const EVP_MD *digest;
648 EVP_MD_CTX md_ctx;
649 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700650
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400651 if (!PyArg_ParseTuple(
David Brodsky5c019772010-12-07 20:08:50 +0100652 args, "O!" BYTESTRING_FMT "#s:sign", &crypto_PKey_Type,
653 &pkey, &data, &data_len, &digest_name)) {
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400654 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700655 }
656
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400657 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
658 PyErr_SetString(PyExc_ValueError, "No such digest method");
659 return NULL;
660 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700661
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400662 EVP_SignInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100663 EVP_SignUpdate(&md_ctx, data, data_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400664 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400665 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700666
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400667 if (err != 1) {
668 exception_from_error_queue(crypto_Error);
669 return NULL;
670 }
671
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400672 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400673 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700674}
675
676static char crypto_verify_doc[] = "\n\
677Verify a signature\n\
678\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900679:param cert: signing certificate (X509 object)\n\
680:param signature: signature returned by sign function\n\
681:param data: data to be verified\n\
682:param digest: message digest to use\n\
683:return: None if the signature is correct, raise exception otherwise\n\
James Yonan7c2e5d32010-02-27 05:45:50 -0700684";
685
686static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400687crypto_verify(PyObject *spam, PyObject *args) {
688 crypto_X509Obj *cert;
689 unsigned char *signature;
690 int sig_len;
691 char *data, *digest_name;
David Brodsky5c019772010-12-07 20:08:50 +0100692 int data_len;
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400693 int err;
694 const EVP_MD *digest;
695 EVP_MD_CTX md_ctx;
696 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700697
Jean-Paul Calderone7b643a92010-08-28 14:40:58 -0400698#ifdef PY3
David Brodsky5c019772010-12-07 20:08:50 +0100699 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 -0400700#else
David Brodsky5c019772010-12-07 20:08:50 +0100701 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 -0400702#endif
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400703 return NULL;
704 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700705
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400706 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
707 PyErr_SetString(PyExc_ValueError, "No such digest method");
708 return NULL;
709 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700710
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400711 pkey = X509_get_pubkey(cert->x509);
712 if (pkey == NULL) {
713 PyErr_SetString(PyExc_ValueError, "No public key");
714 return NULL;
715 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700716
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400717 EVP_VerifyInit(&md_ctx, digest);
David Brodsky5c019772010-12-07 20:08:50 +0100718 EVP_VerifyUpdate(&md_ctx, data, data_len);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400719 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
720 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700721
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400722 if (err != 1) {
723 exception_from_error_queue(crypto_Error);
724 return NULL;
725 }
726
727 Py_INCREF(Py_None);
728 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700729}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400730
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500731/* Methods in the OpenSSL.crypto module (i.e. none) */
732static PyMethodDef crypto_methods[] = {
733 /* Module functions */
734 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
735 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
736 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
737 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
738 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
739 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500740 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500741 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
742 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700743 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
744 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500745 { "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 -0400746 { "_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 -0500747 { NULL, NULL }
748};
749
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400750
751#ifdef WITH_THREAD
752
753#include <pythread.h>
754
755/**
756 * This array will store all of the mutexes available to OpenSSL.
757 */
758static PyThread_type_lock *mutex_buf = NULL;
759
760
761/**
762 * Callback function supplied to OpenSSL to acquire or release a lock.
763 *
764 */
765static void locking_function(int mode, int n, const char * file, int line) {
766 if (mode & CRYPTO_LOCK) {
767 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
768 } else {
769 PyThread_release_lock(mutex_buf[n]);
770 }
771}
772
773
774/**
775 * Initialize OpenSSL for use from multiple threads.
776 *
777 * Returns: 0 if initialization fails, 1 otherwise.
778 */
779static int init_openssl_threads(void) {
780 int i;
781
782 mutex_buf = (PyThread_type_lock *)malloc(
783 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
784 if (!mutex_buf) {
785 return 0;
786 }
787 for (i = 0; i < CRYPTO_num_locks(); ++i) {
788 mutex_buf[i] = PyThread_allocate_lock();
789 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500790 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400791 CRYPTO_set_locking_callback(locking_function);
792 return 1;
793}
794
795/* /\** */
796/* * Clean up after OpenSSL thread initialization. */
797/* *\/ */
798/* static int deinit_openssl_threads() { */
799/* int i; */
800
801/* if (!mutex_buf) { */
802/* return 0; */
803/* } */
804/* CRYPTO_set_id_callback(NULL); */
805/* CRYPTO_set_locking_callback(NULL); */
806/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
807/* PyThread_free_lock(mutex_buf[i]); */
808/* } */
809/* free(mutex_buf); */
810/* mutex_buf = NULL; */
811/* return 1; */
812/* } */
813
814#endif
815
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400816#ifdef PY3
817static struct PyModuleDef cryptomodule = {
818 PyModuleDef_HEAD_INIT,
819 "crypto",
820 crypto_doc,
821 -1,
822 crypto_methods
823};
824#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400825
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500826/*
827 * Initialize crypto sub module
828 *
829 * Arguments: None
830 * Returns: None
831 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400832PyOpenSSL_MODINIT(crypto) {
833#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500834 static void *crypto_API[crypto_API_pointers];
835 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400836#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400837 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500838
839 ERR_load_crypto_strings();
840 OpenSSL_add_all_algorithms();
841
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400842#ifdef PY3
843 module = PyModule_Create(&cryptomodule);
844#else
845 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
846#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500847
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400848 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400849 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400850 }
851
852#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500853 /* Initialize the C API pointer array */
854 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
855 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
856 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
857 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
858 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
859 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
860 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
861 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
862 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500863 if (c_api_object != NULL) {
864 /* PyModule_AddObject steals a reference.
865 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400866 Py_INCREF(c_api_object);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500867 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500868 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400869#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500870
871 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
872 if (crypto_Error == NULL)
873 goto error;
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500874
875 /* PyModule_AddObject steals a reference.
876 */
Jean-Paul Calderone026f6642011-04-20 18:59:33 -0400877 Py_INCREF(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500878 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
879 goto error;
880
881 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
882 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500883 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500884
885 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
886 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
887
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400888#ifdef WITH_THREAD
889 if (!init_openssl_threads())
890 goto error;
891#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400892 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500893 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400894 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500895 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400896 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500897 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400898 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500899 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400900 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500901 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400902 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500903 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400904 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500905 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400906 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500907 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400908 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500909 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500910 if (!init_crypto_crl(module))
911 goto error;
912 if (!init_crypto_revoked(module))
913 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400914
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400915 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400916
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500917error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400918 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500919 ;
920}