Initial import to Tizen
[profile/ivi/python-pyOpenSSL.git] / OpenSSL / crypto / pkey.c
1 /*
2  * pkey.c
3  *
4  * Copyright (C) AB Strakt
5  * Copyright (C) Jean-Paul Calderone
6  * See LICENSE for details.
7  *
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
16 /*
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() \
24 do {                                    \
25     exception_from_error_queue(crypto_Error); \
26     return NULL;                        \
27 } while (0)
28     
29
30 static char crypto_PKey_generate_key_doc[] = "\n\
31 Generate a key of a given type, with a given number of a bits\n\
32 \n\
33 @param type: The key type (TYPE_RSA or TYPE_DSA)\n\
34 @param bits: The number of bits\n\
35 @return: None\n\
36 ";
37
38 static PyObject *
39 crypto_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:
51             if (bits <= 0) {
52                 PyErr_SetString(PyExc_ValueError, "Invalid number of bits");
53                 return NULL;
54             }
55             if ((rsa = RSA_generate_key(bits, 0x10001, NULL, NULL)) == NULL)
56                 FAIL();
57             if (!EVP_PKEY_assign_RSA(self->pkey, rsa))
58                 FAIL();
59             break;
60
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();
68             break;
69
70         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;
78 }
79
80 static char crypto_PKey_bits_doc[] = "\n\
81 Returns the number of bits of the key\n\
82 \n\
83 @return: The number of bits of the key.\n\
84 ";
85
86 static PyObject *
87 crypto_PKey_bits(crypto_PKeyObj *self, PyObject *args)
88 {
89     if (!PyArg_ParseTuple(args, ":bits"))
90         return NULL;
91
92     return PyLong_FromLong(EVP_PKEY_bits(self->pkey));
93 }
94
95 static char crypto_PKey_type_doc[] = "\n\
96 Returns the type of the key\n\
97 \n\
98 @return: The type of the key.\n\
99 ";
100
101 static PyObject *
102 crypto_PKey_type(crypto_PKeyObj *self, PyObject *args)
103 {
104     if (!PyArg_ParseTuple(args, ":type"))
105         return NULL;
106
107     return PyLong_FromLong(self->pkey->type);
108 }
109
110
111 /*
112  * ADD_METHOD(name) expands to a correct PyMethodDef declaration
113  *   {  'name', (PyCFunction)crypto_PKey_name, METH_VARARGS }
114  * for convenience
115  */
116 #define ADD_METHOD(name)        \
117     { #name, (PyCFunction)crypto_PKey_##name, METH_VARARGS, crypto_PKey_##name##_doc }
118 static PyMethodDef crypto_PKey_methods[] =
119 {
120     ADD_METHOD(generate_key),
121     ADD_METHOD(bits),
122     ADD_METHOD(type),
123     { NULL, NULL }
124 };
125 #undef ADD_METHOD
126
127
128 /*
129  * Constructor for PKey objects, never called by Python code directly
130  *
131  * Arguments: pkey    - A "real" EVP_PKEY object
132  *            dealloc - Boolean value to specify whether the destructor should
133  *                      free the "real" EVP_PKEY object
134  * Returns:   The newly created PKey object
135  */
136 crypto_PKeyObj *
137 crypto_PKey_New(EVP_PKEY *pkey, int dealloc)
138 {
139     crypto_PKeyObj *self;
140
141     self = PyObject_New(crypto_PKeyObj, &crypto_PKey_Type);
142
143     if (self == NULL)
144         return NULL;
145
146     self->pkey = pkey;
147     self->dealloc = dealloc;
148     self->only_public = 0;
149
150     /*
151      * Heuristic.  Most call-sites pass an initialized EVP_PKEY.  Not
152      * necessarily the case that they will, though.  That's part of why this is
153      * a hack. -exarkun
154      */
155     self->initialized = 1;
156
157     return self;
158 }
159
160 static char crypto_PKey_doc[] = "\n\
161 PKey() -> PKey instance\n\
162 \n\
163 Create a new PKey object.\n\
164 \n\
165 @return: The PKey object\n\
166 ";
167 static PyObject*
168 crypto_PKey_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
169     crypto_PKeyObj *self;
170
171     if (!PyArg_ParseTuple(args, ":PKey")) {
172         return NULL;
173     }
174
175     self = crypto_PKey_New(EVP_PKEY_new(), 1);
176     if (self) {
177         self->initialized = 0;
178     }
179
180     return (PyObject *)self;
181 }
182
183
184 /*
185  * Deallocate the memory used by the PKey object
186  *
187  * Arguments: self - The PKey object
188  * Returns:   None
189  */
190 static void
191 crypto_PKey_dealloc(crypto_PKeyObj *self)
192 {
193     /* Sometimes we don't have to dealloc the "real" EVP_PKEY pointer ourselves */
194     if (self->dealloc)
195         EVP_PKEY_free(self->pkey);
196
197     PyObject_Del(self);
198 }
199
200 PyTypeObject crypto_PKey_Type = {
201     PyOpenSSL_HEAD_INIT(&PyType_Type, 0)
202     "OpenSSL.crypto.PKey",
203     sizeof(crypto_PKeyObj),
204     0,
205     (destructor)crypto_PKey_dealloc,
206     NULL, /* print */
207     NULL, /* getattr */
208     NULL, /* setattr */
209     NULL, /* compare */
210     NULL, /* repr */
211     NULL, /* as_number */
212     NULL, /* as_sequence */
213     NULL, /* as_mapping */
214     NULL, /* hash */
215     NULL, /* call */
216     NULL, /* str */
217     NULL, /* getattro */
218     NULL, /* setattro */
219     NULL, /* as_buffer */
220     Py_TPFLAGS_DEFAULT,
221     crypto_PKey_doc, /* doc */
222     NULL, /* traverse */
223     NULL, /* clear */
224     NULL, /* tp_richcompare */
225     0, /* tp_weaklistoffset */
226     NULL, /* tp_iter */
227     NULL, /* tp_iternext */
228     crypto_PKey_methods, /* tp_methods */
229     NULL, /* tp_members */
230     NULL, /* tp_getset */
231     NULL, /* tp_base */
232     NULL, /* tp_dict */
233     NULL, /* tp_descr_get */
234     NULL, /* tp_descr_set */
235     0, /* tp_dictoffset */
236     NULL, /* tp_init */
237     NULL, /* tp_alloc */
238     crypto_PKey_new, /* tp_new */
239 };
240
241
242 /*
243  * Initialize the PKey part of the crypto sub module
244  *
245  * Arguments: module - The crypto module
246  * Returns:   None
247  */
248 int
249 init_crypto_pkey(PyObject *module)
250 {
251     if (PyType_Ready(&crypto_PKey_Type) < 0) {
252         return 0;
253     }
254
255     if (PyModule_AddObject(module, "PKey", (PyObject *)&crypto_PKey_Type) != 0) {
256         return 0;
257     }
258
259     if (PyModule_AddObject(module, "PKeyType", (PyObject *)&crypto_PKey_Type) != 0) {
260         return 0;
261     }
262
263     return 1;
264 }
265