blob: 69312db5941e38f6f81733c5252cec45a107ab9c [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * pkey.c
3 *
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05004 * Copyright (C) AB Strakt
5 * Copyright (C) Jean-Paul Calderone
6 * See LICENSE for details.
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05007 *
8 * Public/rivate key handling code, mostly thin wrappers around OpenSSL.
9 * See the file RATIONALE for a short explanation of why this module was written.
10 *
11 */
12#include <Python.h>
13#define crypto_MODULE
14#include "crypto.h"
15
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050016/*
17 * This is done every time something fails, so turning it into a macro is
18 * really nice.
19 *
20 * Arguments: None
21 * Returns: Doesn't return
22 */
23#define FAIL() \
24do { \
Rick Deand369c932009-07-08 11:48:33 -050025 exception_from_error_queue(crypto_Error); \
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050026 return NULL; \
27} while (0)
28
29
30static char crypto_PKey_generate_key_doc[] = "\n\
31Generate a key of a given type, with a given number of a bits\n\
32\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090033:param type: The key type (TYPE_RSA or TYPE_DSA)\n\
34:param bits: The number of bits\n\
35:return: None\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050036";
37
38static PyObject *
39crypto_PKey_generate_key(crypto_PKeyObj *self, PyObject *args)
40{
41 int type, bits;
42 RSA *rsa;
43 DSA *dsa;
44
45 if (!PyArg_ParseTuple(args, "ii:generate_key", &type, &bits))
46 return NULL;
47
48 switch (type)
49 {
50 case crypto_TYPE_RSA:
Jean-Paul Calderoneab82db72008-03-06 00:09:31 -050051 if (bits <= 0) {
52 PyErr_SetString(PyExc_ValueError, "Invalid number of bits");
53 return NULL;
54 }
INADA Naoki43e66542011-08-21 20:32:42 +090055 Py_BEGIN_ALLOW_THREADS;
56 rsa = RSA_generate_key(bits, 0x10001, NULL, NULL);
57 Py_END_ALLOW_THREADS;
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040058 if (rsa == NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050059 FAIL();
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040060 }
61 if (!EVP_PKEY_assign_RSA(self->pkey, rsa)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050062 FAIL();
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040063 }
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040064 break;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050065
66 case crypto_TYPE_DSA:
INADA Naoki43e66542011-08-21 20:32:42 +090067 Py_BEGIN_ALLOW_THREADS;
68 dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040069 Py_END_ALLOW_THREADS;
INADA Naokie4582b02011-08-26 01:17:51 +090070 if (dsa == NULL) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050071 FAIL();
INADA Naokie4582b02011-08-26 01:17:51 +090072 }
73 if (!DSA_generate_key(dsa)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050074 FAIL();
INADA Naokie4582b02011-08-26 01:17:51 +090075 }
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040076 if (!EVP_PKEY_assign_DSA(self->pkey, dsa)) {
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050077 FAIL();
Jean-Paul Calderonecf141b12012-04-03 14:50:30 -040078 }
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040079 break;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050080
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040081 default:
82 PyErr_SetString(crypto_Error, "No such key type");
83 return NULL;
84
85 }
86 self->initialized = 1;
87 Py_INCREF(Py_None);
88 return Py_None;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050089}
90
91static char crypto_PKey_bits_doc[] = "\n\
92Returns the number of bits of the key\n\
93\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +090094:return: The number of bits of the key.\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050095";
96
97static PyObject *
98crypto_PKey_bits(crypto_PKeyObj *self, PyObject *args)
99{
100 if (!PyArg_ParseTuple(args, ":bits"))
101 return NULL;
102
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400103 return PyLong_FromLong(EVP_PKEY_bits(self->pkey));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500104}
105
106static char crypto_PKey_type_doc[] = "\n\
107Returns the type of the key\n\
108\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900109:return: The type of the key.\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500110";
111
112static PyObject *
113crypto_PKey_type(crypto_PKeyObj *self, PyObject *args)
114{
115 if (!PyArg_ParseTuple(args, ":type"))
116 return NULL;
117
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400118 return PyLong_FromLong(self->pkey->type);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500119}
120
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400121static char crypto_PKey_check_doc[] = "\n\
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400122";
123
124static PyObject *
Jean-Paul Calderonefd0b8d62011-06-12 18:05:50 -0400125crypto_PKey_check(crypto_PKeyObj *self, PyObject *args) {
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400126 int r;
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400127
Jean-Paul Calderonefd0b8d62011-06-12 18:05:50 -0400128 if (!PyArg_ParseTuple(args, ":check")) {
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400129 return NULL;
Jean-Paul Calderonefd0b8d62011-06-12 18:05:50 -0400130 }
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400131
Anthony Uke334f712011-10-31 14:40:16 +0100132 if (self->only_public) {
133 PyErr_SetString(PyExc_TypeError, "public key only");
134 return NULL;
Jean-Paul Calderone02d01972011-10-31 10:39:29 -0400135 }
Anthony Uke334f712011-10-31 14:40:16 +0100136
Jean-Paul Calderone7d748542011-06-12 18:10:01 -0400137 if (self->pkey->type == EVP_PKEY_RSA) {
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400138 RSA *rsa;
Jean-Paul Calderonede207e72009-05-13 14:19:05 -0400139 rsa = EVP_PKEY_get1_RSA(self->pkey);
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400140 r = RSA_check_key(rsa);
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400141 if (r == 1) {
Jean-Paul Calderone49f93ab2009-05-13 14:20:00 -0400142 return PyBool_FromLong(1L);
Jean-Paul Calderoned338e4e2009-05-13 15:45:07 -0400143 } else {
144 FAIL();
145 }
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400146 } else {
Jean-Paul Calderonefd0b8d62011-06-12 18:05:50 -0400147 PyErr_SetString(PyExc_TypeError, "key type unsupported");
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400148 return NULL;
149 }
150}
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500151
152/*
153 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
154 * { 'name', (PyCFunction)crypto_PKey_name, METH_VARARGS }
155 * for convenience
156 */
157#define ADD_METHOD(name) \
158 { #name, (PyCFunction)crypto_PKey_##name, METH_VARARGS, crypto_PKey_##name##_doc }
159static PyMethodDef crypto_PKey_methods[] =
160{
161 ADD_METHOD(generate_key),
162 ADD_METHOD(bits),
163 ADD_METHOD(type),
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400164 ADD_METHOD(check),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500165 { NULL, NULL }
166};
167#undef ADD_METHOD
168
169
170/*
171 * Constructor for PKey objects, never called by Python code directly
172 *
173 * Arguments: pkey - A "real" EVP_PKEY object
174 * dealloc - Boolean value to specify whether the destructor should
175 * free the "real" EVP_PKEY object
176 * Returns: The newly created PKey object
177 */
178crypto_PKeyObj *
179crypto_PKey_New(EVP_PKEY *pkey, int dealloc)
180{
181 crypto_PKeyObj *self;
182
183 self = PyObject_New(crypto_PKeyObj, &crypto_PKey_Type);
184
185 if (self == NULL)
186 return NULL;
187
188 self->pkey = pkey;
189 self->dealloc = dealloc;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400190 self->only_public = 0;
191
192 /*
193 * Heuristic. Most call-sites pass an initialized EVP_PKEY. Not
194 * necessarily the case that they will, though. That's part of why this is
195 * a hack. -exarkun
196 */
197 self->initialized = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500198
199 return self;
200}
201
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400202static char crypto_PKey_doc[] = "\n\
203PKey() -> PKey instance\n\
204\n\
205Create a new PKey object.\n\
206\n\
Jonathan Ballet78b92a22011-07-16 08:07:26 +0900207:return: The PKey object\n\
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400208";
209static PyObject*
210crypto_PKey_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
211 crypto_PKeyObj *self;
212
213 if (!PyArg_ParseTuple(args, ":PKey")) {
214 return NULL;
215 }
216
217 self = crypto_PKey_New(EVP_PKEY_new(), 1);
218 if (self) {
219 self->initialized = 0;
220 }
221
222 return (PyObject *)self;
223}
224
225
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500226/*
227 * Deallocate the memory used by the PKey object
228 *
229 * Arguments: self - The PKey object
230 * Returns: None
231 */
232static void
233crypto_PKey_dealloc(crypto_PKeyObj *self)
234{
235 /* Sometimes we don't have to dealloc the "real" EVP_PKEY pointer ourselves */
236 if (self->dealloc)
237 EVP_PKEY_free(self->pkey);
238
239 PyObject_Del(self);
240}
241
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500242PyTypeObject crypto_PKey_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400243 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400244 "OpenSSL.crypto.PKey",
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500245 sizeof(crypto_PKeyObj),
246 0,
247 (destructor)crypto_PKey_dealloc,
248 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400249 NULL, /* getattr */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500250 NULL, /* setattr */
251 NULL, /* compare */
252 NULL, /* repr */
253 NULL, /* as_number */
254 NULL, /* as_sequence */
255 NULL, /* as_mapping */
256 NULL, /* hash */
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400257 NULL, /* call */
258 NULL, /* str */
259 NULL, /* getattro */
260 NULL, /* setattro */
261 NULL, /* as_buffer */
Jean-Paul Calderone09654fe2009-06-27 10:54:48 -0400262 Py_TPFLAGS_DEFAULT,
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400263 crypto_PKey_doc, /* doc */
264 NULL, /* traverse */
265 NULL, /* clear */
266 NULL, /* tp_richcompare */
267 0, /* tp_weaklistoffset */
268 NULL, /* tp_iter */
269 NULL, /* tp_iternext */
270 crypto_PKey_methods, /* tp_methods */
271 NULL, /* tp_members */
272 NULL, /* tp_getset */
273 NULL, /* tp_base */
274 NULL, /* tp_dict */
275 NULL, /* tp_descr_get */
276 NULL, /* tp_descr_set */
277 0, /* tp_dictoffset */
278 NULL, /* tp_init */
279 NULL, /* tp_alloc */
280 crypto_PKey_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500281};
282
283
284/*
285 * Initialize the PKey part of the crypto sub module
286 *
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400287 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500288 * Returns: None
289 */
290int
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400291init_crypto_pkey(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500292{
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400293 if (PyType_Ready(&crypto_PKey_Type) < 0) {
294 return 0;
295 }
296
Jean-Paul Calderone86ad7112010-05-11 16:08:45 -0400297 /* PyModule_AddObject steals a reference.
298 */
299 Py_INCREF((PyObject *)&crypto_PKey_Type);
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400300 if (PyModule_AddObject(module, "PKey", (PyObject *)&crypto_PKey_Type) != 0) {
301 return 0;
302 }
303
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500304 /* PyModule_AddObject steals a reference.
305 */
306 Py_INCREF((PyObject *)&crypto_PKey_Type);
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400307 if (PyModule_AddObject(module, "PKeyType", (PyObject *)&crypto_PKey_Type) != 0) {
308 return 0;
309 }
310
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500311 return 1;
312}
313