blob: 7d5c6a896fad8d348b0852360d8f224e6c32d1fa [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\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040033@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 }
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050055 if ((rsa = RSA_generate_key(bits, 0x10001, NULL, NULL)) == NULL)
56 FAIL();
57 if (!EVP_PKEY_assign_RSA(self->pkey, rsa))
58 FAIL();
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040059 break;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050060
61 case crypto_TYPE_DSA:
62 if ((dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL)) == NULL)
63 FAIL();
64 if (!DSA_generate_key(dsa))
65 FAIL();
66 if (!EVP_PKEY_assign_DSA(self->pkey, dsa))
67 FAIL();
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040068 break;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050069
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -040070 default:
71 PyErr_SetString(crypto_Error, "No such key type");
72 return NULL;
73
74 }
75 self->initialized = 1;
76 Py_INCREF(Py_None);
77 return Py_None;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050078}
79
80static char crypto_PKey_bits_doc[] = "\n\
81Returns the number of bits of the key\n\
82\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040083@return: The number of bits of the key.\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050084";
85
86static PyObject *
87crypto_PKey_bits(crypto_PKeyObj *self, PyObject *args)
88{
89 if (!PyArg_ParseTuple(args, ":bits"))
90 return NULL;
91
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -040092 return PyLong_FromLong(EVP_PKEY_bits(self->pkey));
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050093}
94
95static char crypto_PKey_type_doc[] = "\n\
96Returns the type of the key\n\
97\n\
Jean-Paul Calderone54bcc832009-05-27 14:06:48 -040098@return: The type of the key.\n\
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050099";
100
101static PyObject *
102crypto_PKey_type(crypto_PKeyObj *self, PyObject *args)
103{
104 if (!PyArg_ParseTuple(args, ":type"))
105 return NULL;
106
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400107 return PyLong_FromLong(self->pkey->type);
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500108}
109
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400110static char crypto_PKey_check_doc[] = "\n\
111Check the consistency of an RSA private key.\n\
112\n\
113Arguments: self - The PKey object\n\
114 args - The Python argument tuple, should be empty\n\
115Returns: True if key is consistent. False if not.\n\
116";
117
118static PyObject *
119crypto_PKey_check(crypto_PKeyObj *self, PyObject *args)
120{
121 int r;
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400122
123 if (!PyArg_ParseTuple(args, ":check"))
124 return NULL;
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400125
Jean-Paul Calderonede207e72009-05-13 14:19:05 -0400126 if(self->pkey->type == EVP_PKEY_RSA) {
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400127 RSA *rsa;
Jean-Paul Calderonede207e72009-05-13 14:19:05 -0400128 rsa = EVP_PKEY_get1_RSA(self->pkey);
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400129 r = RSA_check_key(rsa);
130 if (r == 1)
Jean-Paul Calderone49f93ab2009-05-13 14:20:00 -0400131 return PyBool_FromLong(1L);
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400132 else
Jean-Paul Calderone49f93ab2009-05-13 14:20:00 -0400133 return PyBool_FromLong(0L);
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400134 } else {
135 PyErr_SetString( PyExc_TypeError, "key type unsupported");
136 return NULL;
137 }
138}
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500139
140/*
141 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
142 * { 'name', (PyCFunction)crypto_PKey_name, METH_VARARGS }
143 * for convenience
144 */
145#define ADD_METHOD(name) \
146 { #name, (PyCFunction)crypto_PKey_##name, METH_VARARGS, crypto_PKey_##name##_doc }
147static PyMethodDef crypto_PKey_methods[] =
148{
149 ADD_METHOD(generate_key),
150 ADD_METHOD(bits),
151 ADD_METHOD(type),
Jean-Paul Calderone8e6ce972009-05-13 12:32:49 -0400152 ADD_METHOD(check),
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500153 { NULL, NULL }
154};
155#undef ADD_METHOD
156
157
158/*
159 * Constructor for PKey objects, never called by Python code directly
160 *
161 * Arguments: pkey - A "real" EVP_PKEY object
162 * dealloc - Boolean value to specify whether the destructor should
163 * free the "real" EVP_PKEY object
164 * Returns: The newly created PKey object
165 */
166crypto_PKeyObj *
167crypto_PKey_New(EVP_PKEY *pkey, int dealloc)
168{
169 crypto_PKeyObj *self;
170
171 self = PyObject_New(crypto_PKeyObj, &crypto_PKey_Type);
172
173 if (self == NULL)
174 return NULL;
175
176 self->pkey = pkey;
177 self->dealloc = dealloc;
Jean-Paul Calderoneac0d95f2008-03-10 00:00:42 -0400178 self->only_public = 0;
179
180 /*
181 * Heuristic. Most call-sites pass an initialized EVP_PKEY. Not
182 * necessarily the case that they will, though. That's part of why this is
183 * a hack. -exarkun
184 */
185 self->initialized = 1;
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500186
187 return self;
188}
189
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400190static char crypto_PKey_doc[] = "\n\
191PKey() -> PKey instance\n\
192\n\
193Create a new PKey object.\n\
194\n\
195@return: The PKey object\n\
196";
197static PyObject*
198crypto_PKey_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
199 crypto_PKeyObj *self;
200
201 if (!PyArg_ParseTuple(args, ":PKey")) {
202 return NULL;
203 }
204
205 self = crypto_PKey_New(EVP_PKEY_new(), 1);
206 if (self) {
207 self->initialized = 0;
208 }
209
210 return (PyObject *)self;
211}
212
213
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500214/*
215 * Deallocate the memory used by the PKey object
216 *
217 * Arguments: self - The PKey object
218 * Returns: None
219 */
220static void
221crypto_PKey_dealloc(crypto_PKeyObj *self)
222{
223 /* Sometimes we don't have to dealloc the "real" EVP_PKEY pointer ourselves */
224 if (self->dealloc)
225 EVP_PKEY_free(self->pkey);
226
227 PyObject_Del(self);
228}
229
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500230PyTypeObject crypto_PKey_Type = {
Jean-Paul Calderone3fe7f672010-08-11 23:55:10 -0400231 PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400232 "OpenSSL.crypto.PKey",
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500233 sizeof(crypto_PKeyObj),
234 0,
235 (destructor)crypto_PKey_dealloc,
236 NULL, /* print */
Jean-Paul Calderone2f6c66f2010-08-11 19:53:43 -0400237 NULL, /* getattr */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500238 NULL, /* setattr */
239 NULL, /* compare */
240 NULL, /* repr */
241 NULL, /* as_number */
242 NULL, /* as_sequence */
243 NULL, /* as_mapping */
244 NULL, /* hash */
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400245 NULL, /* call */
246 NULL, /* str */
247 NULL, /* getattro */
248 NULL, /* setattro */
249 NULL, /* as_buffer */
Jean-Paul Calderone09654fe2009-06-27 10:54:48 -0400250 Py_TPFLAGS_DEFAULT,
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400251 crypto_PKey_doc, /* doc */
252 NULL, /* traverse */
253 NULL, /* clear */
254 NULL, /* tp_richcompare */
255 0, /* tp_weaklistoffset */
256 NULL, /* tp_iter */
257 NULL, /* tp_iternext */
258 crypto_PKey_methods, /* tp_methods */
259 NULL, /* tp_members */
260 NULL, /* tp_getset */
261 NULL, /* tp_base */
262 NULL, /* tp_dict */
263 NULL, /* tp_descr_get */
264 NULL, /* tp_descr_set */
265 0, /* tp_dictoffset */
266 NULL, /* tp_init */
267 NULL, /* tp_alloc */
268 crypto_PKey_new, /* tp_new */
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500269};
270
271
272/*
273 * Initialize the PKey part of the crypto sub module
274 *
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400275 * Arguments: module - The crypto module
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500276 * Returns: None
277 */
278int
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400279init_crypto_pkey(PyObject *module)
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500280{
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400281 if (PyType_Ready(&crypto_PKey_Type) < 0) {
282 return 0;
283 }
284
Jean-Paul Calderone86ad7112010-05-11 16:08:45 -0400285 /* PyModule_AddObject steals a reference.
286 */
287 Py_INCREF((PyObject *)&crypto_PKey_Type);
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400288 if (PyModule_AddObject(module, "PKey", (PyObject *)&crypto_PKey_Type) != 0) {
289 return 0;
290 }
291
Jean-Paul Calderoneaed23582011-03-12 22:45:02 -0500292 /* PyModule_AddObject steals a reference.
293 */
294 Py_INCREF((PyObject *)&crypto_PKey_Type);
Jean-Paul Calderone2e1da572009-06-27 10:44:00 -0400295 if (PyModule_AddObject(module, "PKeyType", (PyObject *)&crypto_PKey_Type) != 0) {
296 return 0;
297 }
298
Jean-Paul Calderone897bc252008-02-18 20:50:23 -0500299 return 1;
300}
301