blob: 87f3e75b536238e3101b1a82768aad8e6db907c8 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * crypto.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
James Yonan7c2e5d32010-02-27 05:45:50 -07005 * Copyright (C) Keyphrene 2004, All rights reserved
Jean-Paul Calderone88f38b22009-07-16 16:25:19 -04006 * Copyright (C) Jean-Paul Calderone 2008-2009, All rights reserved
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 *
8 * Main file of crypto sub module.
9 * See the file RATIONALE for a short explanation of why this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
Rick Dean623ee362009-07-17 12:22:16 -050016#include "pkcs12.h"
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017
18static char crypto_doc[] = "\n\
19Main file of crypto sub module.\n\
20See the file RATIONALE for a short explanation of why this module was written.\n\
21";
22
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050023void **ssl_API;
24
25PyObject *crypto_Error;
26
27static int
28global_passphrase_callback(char *buf, int len, int rwflag, void *cb_arg)
29{
30 PyObject *func, *argv, *ret;
31 int nchars;
32
33 func = (PyObject *)cb_arg;
34 argv = Py_BuildValue("(i)", rwflag);
35 ret = PyEval_CallObject(func, argv);
36 Py_DECREF(argv);
37 if (ret == NULL)
38 return 0;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040039 if (!PyBytes_Check(ret))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050040 {
41 PyErr_SetString(PyExc_ValueError, "String expected");
42 return 0;
43 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040044 nchars = PyBytes_Size(ret);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050045 if (nchars > len)
46 nchars = len;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040047 strncpy(buf, PyBytes_AsString(ret), nchars);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050048 return nchars;
49}
50
51static char crypto_load_privatekey_doc[] = "\n\
52Load a private key from a buffer\n\
53\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040054@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
55@param buffer: The buffer the key is stored in\n\
56@param passphrase: (optional) if encrypted PEM format, this can be\n\
57 either the passphrase to use, or a callback for\n\
58 providing the passphrase.\n\
59\n\
60@return: The PKey object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050061";
62
63static PyObject *
64crypto_load_privatekey(PyObject *spam, PyObject *args)
65{
66 crypto_PKeyObj *crypto_PKey_New(EVP_PKEY *, int);
67 int type, len;
68 char *buffer;
69 PyObject *pw = NULL;
70 pem_password_cb *cb = NULL;
71 void *cb_arg = NULL;
72 BIO *bio;
73 EVP_PKEY *pkey;
74
75 if (!PyArg_ParseTuple(args, "is#|O:load_privatekey", &type, &buffer, &len, &pw))
76 return NULL;
77
78 if (pw != NULL)
79 {
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040080 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050081 {
82 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -040083 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050084 }
85 else if (PyCallable_Check(pw))
86 {
87 cb = global_passphrase_callback;
88 cb_arg = pw;
89 }
90 else
91 {
92 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
93 return NULL;
94 }
95 }
96
97 bio = BIO_new_mem_buf(buffer, len);
98 switch (type)
99 {
100 case X509_FILETYPE_PEM:
101 pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, cb_arg);
102 break;
103
104 case X509_FILETYPE_ASN1:
105 pkey = d2i_PrivateKey_bio(bio, NULL);
106 break;
107
108 default:
109 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
110 BIO_free(bio);
111 return NULL;
112 }
113 BIO_free(bio);
114
115 if (pkey == NULL)
116 {
Rick Deand369c932009-07-08 11:48:33 -0500117 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500118 return NULL;
119 }
120
121 return (PyObject *)crypto_PKey_New(pkey, 1);
122}
123
124static char crypto_dump_privatekey_doc[] = "\n\
125Dump a private key to a buffer\n\
126\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400127@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
128@param pkey: The PKey to dump\n\
129@param cipher: (optional) if encrypted PEM format, the cipher to\n\
130 use\n\
131@param passphrase - (optional) if encrypted PEM format, this can be either\n\
132 the passphrase to use, or a callback for providing the\n\
133 passphrase.\n\
134@return: The buffer with the dumped key in\n\
135@rtype: C{str}\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500136";
137
138static PyObject *
139crypto_dump_privatekey(PyObject *spam, PyObject *args)
140{
141 int type, ret, buf_len;
142 char *temp;
143 PyObject *buffer;
144 char *cipher_name = NULL;
145 const EVP_CIPHER *cipher = NULL;
146 PyObject *pw = NULL;
147 pem_password_cb *cb = NULL;
148 void *cb_arg = NULL;
149 BIO *bio;
Rick Dean5b7b6372009-04-01 11:34:06 -0500150 RSA *rsa;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500151 crypto_PKeyObj *pkey;
152
153 if (!PyArg_ParseTuple(args, "iO!|sO:dump_privatekey", &type,
154 &crypto_PKey_Type, &pkey, &cipher_name, &pw))
155 return NULL;
156
157 if (cipher_name != NULL && pw == NULL)
158 {
159 PyErr_SetString(PyExc_ValueError, "Illegal number of arguments");
160 return NULL;
161 }
162 if (cipher_name != NULL)
163 {
164 cipher = EVP_get_cipherbyname(cipher_name);
165 if (cipher == NULL)
166 {
167 PyErr_SetString(PyExc_ValueError, "Invalid cipher name");
168 return NULL;
169 }
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400170 if (PyBytes_Check(pw))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500171 {
172 cb = NULL;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400173 cb_arg = PyBytes_AsString(pw);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500174 }
175 else if (PyCallable_Check(pw))
176 {
177 cb = global_passphrase_callback;
178 cb_arg = pw;
179 }
180 else
181 {
182 PyErr_SetString(PyExc_TypeError, "Last argument must be string or callable");
183 return NULL;
184 }
185 }
186
187 bio = BIO_new(BIO_s_mem());
188 switch (type)
189 {
190 case X509_FILETYPE_PEM:
191 ret = PEM_write_bio_PrivateKey(bio, pkey->pkey, cipher, NULL, 0, cb, cb_arg);
192 if (PyErr_Occurred())
193 {
194 BIO_free(bio);
195 return NULL;
196 }
197 break;
198
199 case X509_FILETYPE_ASN1:
200 ret = i2d_PrivateKey_bio(bio, pkey->pkey);
201 break;
202
Rick Dean5b7b6372009-04-01 11:34:06 -0500203 case X509_FILETYPE_TEXT:
204 rsa = EVP_PKEY_get1_RSA(pkey->pkey);
205 ret = RSA_print(bio, rsa, 0);
206 RSA_free(rsa);
207 break;
208
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500209 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500210 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500211 BIO_free(bio);
212 return NULL;
213 }
214
215 if (ret == 0)
216 {
217 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500218 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500219 return NULL;
220 }
221
222 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400223 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500224 BIO_free(bio);
225
226 return buffer;
227}
228
229static char crypto_load_certificate_doc[] = "\n\
230Load a certificate from a buffer\n\
231\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400232@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500233 buffer - The buffer the certificate is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400234@return: The X509 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500235";
236
237static PyObject *
238crypto_load_certificate(PyObject *spam, PyObject *args)
239{
240 crypto_X509Obj *crypto_X509_New(X509 *, int);
241 int type, len;
242 char *buffer;
243 BIO *bio;
244 X509 *cert;
245
246 if (!PyArg_ParseTuple(args, "is#:load_certificate", &type, &buffer, &len))
247 return NULL;
248
249 bio = BIO_new_mem_buf(buffer, len);
250 switch (type)
251 {
252 case X509_FILETYPE_PEM:
253 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
254 break;
255
256 case X509_FILETYPE_ASN1:
257 cert = d2i_X509_bio(bio, NULL);
258 break;
259
260 default:
261 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
262 BIO_free(bio);
263 return NULL;
264 }
265 BIO_free(bio);
266
267 if (cert == NULL)
268 {
Rick Deand369c932009-07-08 11:48:33 -0500269 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500270 return NULL;
271 }
272
273 return (PyObject *)crypto_X509_New(cert, 1);
274}
275
276static char crypto_dump_certificate_doc[] = "\n\
277Dump a certificate to a buffer\n\
278\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400279@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
280@param cert: The certificate to dump\n\
281@return: The buffer with the dumped certificate in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500282";
283
284static PyObject *
285crypto_dump_certificate(PyObject *spam, PyObject *args)
286{
287 int type, ret, buf_len;
288 char *temp;
289 PyObject *buffer;
290 BIO *bio;
291 crypto_X509Obj *cert;
292
293 if (!PyArg_ParseTuple(args, "iO!:dump_certificate", &type,
294 &crypto_X509_Type, &cert))
295 return NULL;
296
297 bio = BIO_new(BIO_s_mem());
298 switch (type)
299 {
300 case X509_FILETYPE_PEM:
301 ret = PEM_write_bio_X509(bio, cert->x509);
302 break;
303
304 case X509_FILETYPE_ASN1:
305 ret = i2d_X509_bio(bio, cert->x509);
306 break;
307
Rick Dean5b7b6372009-04-01 11:34:06 -0500308 case X509_FILETYPE_TEXT:
309 ret = X509_print_ex(bio, cert->x509, 0, 0);
310 break;
311
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500312 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500313 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500314 BIO_free(bio);
315 return NULL;
316 }
317
318 if (ret == 0)
319 {
320 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500321 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500322 return NULL;
323 }
324
325 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400326 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500327 BIO_free(bio);
328
329 return buffer;
330}
331
332static char crypto_load_certificate_request_doc[] = "\n\
333Load a certificate request from a buffer\n\
334\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400335@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500336 buffer - The buffer the certificate request is stored in\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400337@return: The X509Req object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500338";
339
340static PyObject *
341crypto_load_certificate_request(PyObject *spam, PyObject *args)
342{
343 crypto_X509ReqObj *crypto_X509Req_New(X509_REQ *, int);
344 int type, len;
345 char *buffer;
346 BIO *bio;
347 X509_REQ *req;
348
349 if (!PyArg_ParseTuple(args, "is#:load_certificate_request", &type, &buffer, &len))
350 return NULL;
351
352 bio = BIO_new_mem_buf(buffer, len);
353 switch (type)
354 {
355 case X509_FILETYPE_PEM:
356 req = PEM_read_bio_X509_REQ(bio, NULL, NULL, NULL);
357 break;
358
359 case X509_FILETYPE_ASN1:
360 req = d2i_X509_REQ_bio(bio, NULL);
361 break;
362
363 default:
364 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
365 BIO_free(bio);
366 return NULL;
367 }
368 BIO_free(bio);
369
370 if (req == NULL)
371 {
Rick Deand369c932009-07-08 11:48:33 -0500372 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500373 return NULL;
374 }
375
376 return (PyObject *)crypto_X509Req_New(req, 1);
377}
378
379static char crypto_dump_certificate_request_doc[] = "\n\
380Dump a certificate request to a buffer\n\
381\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400382@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500383 req - The certificate request to dump\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400384@return: The buffer with the dumped certificate request in\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500385";
386
387static PyObject *
388crypto_dump_certificate_request(PyObject *spam, PyObject *args)
389{
390 int type, ret, buf_len;
391 char *temp;
392 PyObject *buffer;
393 BIO *bio;
394 crypto_X509ReqObj *req;
395
396 if (!PyArg_ParseTuple(args, "iO!:dump_certificate_request", &type,
397 &crypto_X509Req_Type, &req))
398 return NULL;
399
400 bio = BIO_new(BIO_s_mem());
401 switch (type)
402 {
403 case X509_FILETYPE_PEM:
404 ret = PEM_write_bio_X509_REQ(bio, req->x509_req);
405 break;
406
407 case X509_FILETYPE_ASN1:
408 ret = i2d_X509_REQ_bio(bio, req->x509_req);
409 break;
410
Rick Dean5b7b6372009-04-01 11:34:06 -0500411 case X509_FILETYPE_TEXT:
412 ret = X509_REQ_print_ex(bio, req->x509_req, 0, 0);
413 break;
414
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500415 default:
Rick Dean5b7b6372009-04-01 11:34:06 -0500416 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or FILETYPE_TEXT");
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500417 BIO_free(bio);
418 return NULL;
419 }
420
421 if (ret == 0)
422 {
423 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500424 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500425 return NULL;
426 }
427
428 buf_len = BIO_get_mem_data(bio, &temp);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400429 buffer = PyBytes_FromStringAndSize(temp, buf_len);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500430 BIO_free(bio);
431
432 return buffer;
433}
434
Rick Dean536ba022009-07-24 23:57:27 -0500435static char crypto_load_crl_doc[] = "\n\
436Load a certificate revocation list from a buffer\n\
437\n\
438@param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1)\n\
439@param buffer: The buffer the CRL is stored in\n\
440\n\
441@return: The PKey object\n\
442";
443
444static PyObject *
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400445crypto_load_crl(PyObject *spam, PyObject *args) {
Rick Dean536ba022009-07-24 23:57:27 -0500446 int type, len;
447 char *buffer;
448 BIO *bio;
449 X509_CRL *crl;
450
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400451 if (!PyArg_ParseTuple(args, "is#:load_crl", &type, &buffer, &len)) {
Rick Dean536ba022009-07-24 23:57:27 -0500452 return NULL;
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400453 }
Rick Dean536ba022009-07-24 23:57:27 -0500454
455 bio = BIO_new_mem_buf(buffer, len);
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400456 switch (type) {
Rick Dean536ba022009-07-24 23:57:27 -0500457 case X509_FILETYPE_PEM:
458 crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
459 break;
460
461 case X509_FILETYPE_ASN1:
462 crl = d2i_X509_CRL_bio(bio, NULL);
463 break;
464
465 default:
466 PyErr_SetString(PyExc_ValueError, "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
467 BIO_free(bio);
468 return NULL;
469 }
470 BIO_free(bio);
471
Jean-Paul Calderone03ae4d32010-05-24 18:04:59 -0400472 if (crl == NULL) {
Rick Dean536ba022009-07-24 23:57:27 -0500473 exception_from_error_queue(crypto_Error);
474 return NULL;
475 }
476
477 return (PyObject *)crypto_CRL_New(crl);
478}
479
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500480static char crypto_load_pkcs7_data_doc[] = "\n\
481Load pkcs7 data from a buffer\n\
482\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400483@param type: The file type (one of FILETYPE_PEM or FILETYPE_ASN1)\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500484 buffer - The buffer with the pkcs7 data.\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400485@return: The PKCS7 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500486";
487
488static PyObject *
489crypto_load_pkcs7_data(PyObject *spam, PyObject *args)
490{
491 int type, len;
492 char *buffer;
493 BIO *bio;
494 PKCS7 *pkcs7 = NULL;
495
496 if (!PyArg_ParseTuple(args, "is#:load_pkcs7_data", &type, &buffer, &len))
497 return NULL;
498
499 /*
500 * Try to read the pkcs7 data from the bio
501 */
502 bio = BIO_new_mem_buf(buffer, len);
503 switch (type)
504 {
505 case X509_FILETYPE_PEM:
506 pkcs7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
507 break;
508
509 case X509_FILETYPE_ASN1:
510 pkcs7 = d2i_PKCS7_bio(bio, NULL);
511 break;
512
513 default:
514 PyErr_SetString(PyExc_ValueError,
515 "type argument must be FILETYPE_PEM or FILETYPE_ASN1");
516 return NULL;
517 }
518 BIO_free(bio);
519
520 /*
521 * Check if we got a PKCS7 structure
522 */
523 if (pkcs7 == NULL)
524 {
Rick Deand369c932009-07-08 11:48:33 -0500525 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500526 return NULL;
527 }
528
529 return (PyObject *)crypto_PKCS7_New(pkcs7, 1);
530}
531
532static char crypto_load_pkcs12_doc[] = "\n\
533Load a PKCS12 object from a buffer\n\
534\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400535@param buffer: The buffer the certificate is stored in\n\
536 passphrase (Optional) - The password to decrypt the PKCS12 lump\n\
537@returns: The PKCS12 object\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500538";
539
540static PyObject *
541crypto_load_pkcs12(PyObject *spam, PyObject *args)
542{
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500543 int len;
544 char *buffer, *passphrase = NULL;
545 BIO *bio;
546 PKCS12 *p12;
547
548 if (!PyArg_ParseTuple(args, "s#|s:load_pkcs12", &buffer, &len, &passphrase))
549 return NULL;
550
551 bio = BIO_new_mem_buf(buffer, len);
552 if ((p12 = d2i_PKCS12_bio(bio, NULL)) == NULL)
553 {
554 BIO_free(bio);
Rick Deand369c932009-07-08 11:48:33 -0500555 exception_from_error_queue(crypto_Error);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500556 return NULL;
557 }
558 BIO_free(bio);
559
560 return (PyObject *)crypto_PKCS12_New(p12, passphrase);
561}
562
563
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500564static char crypto_X509_verify_cert_error_string_doc[] = "\n\
565Get X509 verify certificate error string.\n\
566\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -0400567@param errnum: The error number.\n\
568@return: Error string as a Python string\n\
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500569";
570
571static PyObject *
572crypto_X509_verify_cert_error_string(PyObject *spam, PyObject *args)
573{
574 int errnum;
575 const char *str;
576
577 if (!PyArg_ParseTuple(args, "i", &errnum))
578 return NULL;
579
580 str = X509_verify_cert_error_string(errnum);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400581 return PyText_FromString(str);
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500582}
583
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400584static char crypto_exception_from_error_queue_doc[] = "\n\
585Raise an exception from the current OpenSSL error queue.\n\
586";
587
588static PyObject *
589crypto_exception_from_error_queue(PyObject *spam, PyObject *eggs) {
590 exception_from_error_queue(crypto_Error);
591 return NULL;
592}
593
James Yonan7c2e5d32010-02-27 05:45:50 -0700594static char crypto_sign_doc[] = "\n\
595Sign data with a digest\n\
596\n\
597@param pkey: Pkey to sign with\n\
598@param data: data to be signed\n\
599@param digest: message digest to use\n\
600@return: signature\n\
601";
602
603static PyObject *
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400604crypto_sign(PyObject *spam, PyObject *args) {
605 PyObject *buffer;
606 crypto_PKeyObj *pkey;
607 char *data = NULL;
608 char *digest_name;
609 int err;
610 unsigned int sig_len;
611 const EVP_MD *digest;
612 EVP_MD_CTX md_ctx;
613 unsigned char sig_buf[512];
James Yonan7c2e5d32010-02-27 05:45:50 -0700614
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400615 if (!PyArg_ParseTuple(args, "O!ss:sign", &crypto_PKey_Type,
616 &pkey, &data, &digest_name)) {
617 return NULL;
James Yonan7c2e5d32010-02-27 05:45:50 -0700618 }
619
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400620 if ((digest = EVP_get_digestbyname(digest_name)) == NULL) {
621 PyErr_SetString(PyExc_ValueError, "No such digest method");
622 return NULL;
623 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700624
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400625 EVP_SignInit(&md_ctx, digest);
626 EVP_SignUpdate(&md_ctx, data, strlen(data));
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400627 sig_len = sizeof(sig_buf);
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400628 err = EVP_SignFinal(&md_ctx, sig_buf, &sig_len, pkey->pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700629
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400630 if (err != 1) {
631 exception_from_error_queue(crypto_Error);
632 return NULL;
633 }
634
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400635 buffer = PyBytes_FromStringAndSize((char*)sig_buf, sig_len);
Jean-Paul Calderone8b37f0a2010-06-22 09:43:42 -0400636 return buffer;
James Yonan7c2e5d32010-02-27 05:45:50 -0700637}
638
639static char crypto_verify_doc[] = "\n\
640Verify a signature\n\
641\n\
642@param cert: signing certificate (X509 object)\n\
643@param signature: signature returned by sign function\n\
644@param data: data to be verified\n\
645@param digest: message digest to use\n\
646@return: None if the signature is correct, raise exception otherwise\n\
647";
648
649static PyObject *
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400650crypto_verify(PyObject *spam, PyObject *args) {
651 crypto_X509Obj *cert;
652 unsigned char *signature;
653 int sig_len;
654 char *data, *digest_name;
655 int err;
656 const EVP_MD *digest;
657 EVP_MD_CTX md_ctx;
658 EVP_PKEY *pkey;
James Yonan7c2e5d32010-02-27 05:45:50 -0700659
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400660 if (!PyArg_ParseTuple(args, "O!t#ss:verify", &crypto_X509_Type, &cert, &signature, &sig_len,
661 &data, &digest_name)) {
662 return NULL;
663 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700664
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400665 if ((digest = EVP_get_digestbyname(digest_name)) == NULL){
666 PyErr_SetString(PyExc_ValueError, "No such digest method");
667 return NULL;
668 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700669
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400670 pkey = X509_get_pubkey(cert->x509);
671 if (pkey == NULL) {
672 PyErr_SetString(PyExc_ValueError, "No public key");
673 return NULL;
674 }
James Yonan7c2e5d32010-02-27 05:45:50 -0700675
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400676 EVP_VerifyInit(&md_ctx, digest);
677 EVP_VerifyUpdate(&md_ctx, data, strlen((char*)data));
678 err = EVP_VerifyFinal(&md_ctx, signature, sig_len, pkey);
679 EVP_PKEY_free(pkey);
James Yonan7c2e5d32010-02-27 05:45:50 -0700680
Jean-Paul Calderoneb1fac9f2010-06-22 09:44:33 -0400681 if (err != 1) {
682 exception_from_error_queue(crypto_Error);
683 return NULL;
684 }
685
686 Py_INCREF(Py_None);
687 return Py_None;
James Yonan7c2e5d32010-02-27 05:45:50 -0700688}
Jean-Paul Calderone1206daf2009-07-16 16:07:42 -0400689
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500690/* Methods in the OpenSSL.crypto module (i.e. none) */
691static PyMethodDef crypto_methods[] = {
692 /* Module functions */
693 { "load_privatekey", (PyCFunction)crypto_load_privatekey, METH_VARARGS, crypto_load_privatekey_doc },
694 { "dump_privatekey", (PyCFunction)crypto_dump_privatekey, METH_VARARGS, crypto_dump_privatekey_doc },
695 { "load_certificate", (PyCFunction)crypto_load_certificate, METH_VARARGS, crypto_load_certificate_doc },
696 { "dump_certificate", (PyCFunction)crypto_dump_certificate, METH_VARARGS, crypto_dump_certificate_doc },
697 { "load_certificate_request", (PyCFunction)crypto_load_certificate_request, METH_VARARGS, crypto_load_certificate_request_doc },
698 { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
Rick Dean536ba022009-07-24 23:57:27 -0500699 { "load_crl", (PyCFunction)crypto_load_crl, METH_VARARGS, crypto_load_crl_doc },
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500700 { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
701 { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
James Yonan7c2e5d32010-02-27 05:45:50 -0700702 { "sign", (PyCFunction)crypto_sign, METH_VARARGS, crypto_sign_doc },
703 { "verify", (PyCFunction)crypto_verify, METH_VARARGS, crypto_verify_doc },
Jean-Paul Calderone7df40db2008-03-03 15:12:42 -0500704 { "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 -0400705 { "_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 -0500706 { NULL, NULL }
707};
708
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400709
710#ifdef WITH_THREAD
711
712#include <pythread.h>
713
714/**
715 * This array will store all of the mutexes available to OpenSSL.
716 */
717static PyThread_type_lock *mutex_buf = NULL;
718
719
720/**
721 * Callback function supplied to OpenSSL to acquire or release a lock.
722 *
723 */
724static void locking_function(int mode, int n, const char * file, int line) {
725 if (mode & CRYPTO_LOCK) {
726 PyThread_acquire_lock(mutex_buf[n], WAIT_LOCK);
727 } else {
728 PyThread_release_lock(mutex_buf[n]);
729 }
730}
731
732
733/**
734 * Initialize OpenSSL for use from multiple threads.
735 *
736 * Returns: 0 if initialization fails, 1 otherwise.
737 */
738static int init_openssl_threads(void) {
739 int i;
740
741 mutex_buf = (PyThread_type_lock *)malloc(
742 CRYPTO_num_locks() * sizeof(PyThread_type_lock));
743 if (!mutex_buf) {
744 return 0;
745 }
746 for (i = 0; i < CRYPTO_num_locks(); ++i) {
747 mutex_buf[i] = PyThread_allocate_lock();
748 }
Jean-Paul Calderone28ebb302008-12-29 16:25:30 -0500749 CRYPTO_set_id_callback((unsigned long (*)(void))PyThread_get_thread_ident);
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400750 CRYPTO_set_locking_callback(locking_function);
751 return 1;
752}
753
754/* /\** */
755/* * Clean up after OpenSSL thread initialization. */
756/* *\/ */
757/* static int deinit_openssl_threads() { */
758/* int i; */
759
760/* if (!mutex_buf) { */
761/* return 0; */
762/* } */
763/* CRYPTO_set_id_callback(NULL); */
764/* CRYPTO_set_locking_callback(NULL); */
765/* for (i = 0; i < CRYPTO_num_locks(); i++) { */
766/* PyThread_free_lock(mutex_buf[i]); */
767/* } */
768/* free(mutex_buf); */
769/* mutex_buf = NULL; */
770/* return 1; */
771/* } */
772
773#endif
774
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400775#ifdef PY3
776static struct PyModuleDef cryptomodule = {
777 PyModuleDef_HEAD_INIT,
778 "crypto",
779 crypto_doc,
780 -1,
781 crypto_methods
782};
783#endif
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400784
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500785/*
786 * Initialize crypto sub module
787 *
788 * Arguments: None
789 * Returns: None
790 */
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400791PyOpenSSL_MODINIT(crypto) {
792#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500793 static void *crypto_API[crypto_API_pointers];
794 PyObject *c_api_object;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400795#endif
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400796 PyObject *module;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500797
798 ERR_load_crypto_strings();
799 OpenSSL_add_all_algorithms();
800
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400801#ifdef PY3
802 module = PyModule_Create(&cryptomodule);
803#else
804 module = Py_InitModule3("crypto", crypto_methods, crypto_doc);
805#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500806
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400807 if (module == NULL) {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400808 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400809 }
810
811#ifndef PY3
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500812 /* Initialize the C API pointer array */
813 crypto_API[crypto_X509_New_NUM] = (void *)crypto_X509_New;
814 crypto_API[crypto_X509Name_New_NUM] = (void *)crypto_X509Name_New;
815 crypto_API[crypto_X509Req_New_NUM] = (void *)crypto_X509Req_New;
816 crypto_API[crypto_X509Store_New_NUM] = (void *)crypto_X509Store_New;
817 crypto_API[crypto_PKey_New_NUM] = (void *)crypto_PKey_New;
818 crypto_API[crypto_X509Extension_New_NUM] = (void *)crypto_X509Extension_New;
819 crypto_API[crypto_PKCS7_New_NUM] = (void *)crypto_PKCS7_New;
820 crypto_API[crypto_NetscapeSPKI_New_NUM] = (void *)crypto_NetscapeSPKI_New;
821 c_api_object = PyCObject_FromVoidPtr((void *)crypto_API, NULL);
822 if (c_api_object != NULL)
823 PyModule_AddObject(module, "_C_API", c_api_object);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400824#endif
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500825
826 crypto_Error = PyErr_NewException("OpenSSL.crypto.Error", NULL, NULL);
827 if (crypto_Error == NULL)
828 goto error;
829 if (PyModule_AddObject(module, "Error", crypto_Error) != 0)
830 goto error;
831
832 PyModule_AddIntConstant(module, "FILETYPE_PEM", X509_FILETYPE_PEM);
833 PyModule_AddIntConstant(module, "FILETYPE_ASN1", X509_FILETYPE_ASN1);
Rick Dean5b7b6372009-04-01 11:34:06 -0500834 PyModule_AddIntConstant(module, "FILETYPE_TEXT", X509_FILETYPE_TEXT);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500835
836 PyModule_AddIntConstant(module, "TYPE_RSA", crypto_TYPE_RSA);
837 PyModule_AddIntConstant(module, "TYPE_DSA", crypto_TYPE_DSA);
838
Jean-Paul Calderoneaea5d902008-04-26 19:53:39 -0400839#ifdef WITH_THREAD
840 if (!init_openssl_threads())
841 goto error;
842#endif
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400843 if (!init_crypto_x509(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500844 goto error;
Jean-Paul Calderone2cd7a922009-06-27 11:02:46 -0400845 if (!init_crypto_x509name(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500846 goto error;
Jean-Paul Calderone0cdb7bd2009-07-04 10:21:07 -0400847 if (!init_crypto_x509store(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500848 goto error;
Jean-Paul Calderonef1592522009-06-27 11:10:43 -0400849 if (!init_crypto_x509req(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500850 goto error;
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400851 if (!init_crypto_pkey(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500852 goto error;
Jean-Paul Calderone51e90662009-06-27 11:17:28 -0400853 if (!init_crypto_x509extension(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500854 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400855 if (!init_crypto_pkcs7(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500856 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400857 if (!init_crypto_pkcs12(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500858 goto error;
Jean-Paul Calderonedc138fa2009-06-27 14:32:07 -0400859 if (!init_crypto_netscape_spki(module))
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500860 goto error;
Rick Dean536ba022009-07-24 23:57:27 -0500861 if (!init_crypto_crl(module))
862 goto error;
863 if (!init_crypto_revoked(module))
864 goto error;
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400865
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400866 PyOpenSSL_MODRETURN(module);
Jean-Paul Calderoneef853eb2010-08-10 19:47:06 -0400867
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500868error:
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400869 PyOpenSSL_MODRETURN(NULL);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500870 ;
871}