blob: adbd0dc267409ed3ceedd084eb4196124c6a99b4 [file] [log] [blame]
Jean-Paul Calderone897bc252008-02-18 20:50:23 -05001/*
2 * pkcs12.c
3 *
4 * Copyright (C) AB Strakt 2001, All rights reserved
5 *
6 * Certificate transport (PKCS12) handling code,
7 * mostly thin wrappers around OpenSSL.
8 * See the file RATIONALE for a short explanation of why
9 * this module was written.
10 *
11 * Reviewed 2001-07-23
12 */
13#include <Python.h>
14#define crypto_MODULE
15#include "crypto.h"
16
Jean-Paul Calderone897bc252008-02-18 20:50:23 -050017/*
18 * PKCS12 is a standard exchange format for digital certificates.
19 * See e.g. the OpenSSL homepage http://www.openssl.org/ for more information
20 */
21
22static void crypto_PKCS12_dealloc(crypto_PKCS12Obj *self);
23
24static char crypto_PKCS12_get_certificate_doc[] = "\n\
25Return certificate portion of the PKCS12 structure\n\
26\n\
27Arguments: self - The PKCS12 object\n\
28 args - The Python argument tuple, should be empty\n\
29Returns: X509 object containing the certificate\n\
30";
31static PyObject *
32crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args)
33{
34 if (!PyArg_ParseTuple(args, ":get_certificate"))
35 return NULL;
36
37 Py_INCREF(self->cert);
38 return self->cert;
39}
40
41static char crypto_PKCS12_get_privatekey_doc[] = "\n\
42Return private key portion of the PKCS12 structure\n\
43\n\
44Arguments: self - The PKCS12 object\n\
45 args - The Python argument tuple, should be empty\n\
46Returns: PKey object containing the private key\n\
47";
48static PyObject *
49crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args)
50{
51 if (!PyArg_ParseTuple(args, ":get_privatekey"))
52 return NULL;
53
54 Py_INCREF(self->key);
55 return self->key;
56}
57
58static char crypto_PKCS12_get_ca_certificates_doc[] = "\n\
59Return CA certificates within of the PKCS12 object\n\
60\n\
61Arguments: self - The PKCS12 object\n\
62 args - The Python argument tuple, should be empty\n\
63Returns: A newly created tuple containing the CA certificates in the chain,\n\
64 if any are present, or None if no CA certificates are present.\n\
65";
66static PyObject *
67crypto_PKCS12_get_ca_certificates(crypto_PKCS12Obj *self, PyObject *args)
68{
69 if (!PyArg_ParseTuple(args, ":get_ca_certificates"))
70 return NULL;
71
72 Py_INCREF(self->cacerts);
73 return self->cacerts;
74}
75
76/*
77 * ADD_METHOD(name) expands to a correct PyMethodDef declaration
78 * { 'name', (PyCFunction)crypto_PKCS12_name, METH_VARARGS, crypto_PKCS12_name_doc }
79 * for convenience
80 */
81#define ADD_METHOD(name) \
82 { #name, (PyCFunction)crypto_PKCS12_##name, METH_VARARGS, crypto_PKCS12_##name##_doc }
83static PyMethodDef crypto_PKCS12_methods[] =
84{
85 ADD_METHOD(get_certificate),
86 ADD_METHOD(get_privatekey),
87 ADD_METHOD(get_ca_certificates),
88 { NULL, NULL }
89};
90#undef ADD_METHOD
91
92/*
93 * Constructor for PKCS12 objects, never called by Python code directly.
94 * The strategy for this object is to create all the Python objects
95 * corresponding to the cert/key/CA certs right away
96 *
97 * Arguments: p12 - A "real" PKCS12 object
98 * passphrase - Passphrase to use when decrypting the PKCS12 object
99 * Returns: The newly created PKCS12 object
100 */
101crypto_PKCS12Obj *
102crypto_PKCS12_New(PKCS12 *p12, char *passphrase)
103{
104 crypto_PKCS12Obj *self;
105 PyObject *cacertobj = NULL;
106
107 X509 *cert = NULL;
108 EVP_PKEY *pkey = NULL;
109 STACK_OF(X509) *cacerts = NULL;
110
111 int i, cacert_count = 0;
112
113 /* allocate space for the CA cert stack */
114 cacerts = sk_X509_new_null();
115
116 /* parse the PKCS12 lump */
117 if (!(cacerts && PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts)))
118 {
119 exception_from_error_queue();
120 return NULL;
121 }
122
123 if (!(self = PyObject_GC_New(crypto_PKCS12Obj, &crypto_PKCS12_Type)))
124 return NULL;
125
126 self->cert = NULL;
127 self->key = NULL;
128 Py_INCREF(Py_None);
129 self->cacerts = Py_None;
130
131 if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
132 goto error;
133
134 if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL)
135 goto error;
136
137 /* Make a tuple for the CA certs */
138 cacert_count = sk_X509_num(cacerts);
139 if (cacert_count > 0)
140 {
141 Py_DECREF(self->cacerts);
142 if ((self->cacerts = PyTuple_New(cacert_count)) == NULL)
143 goto error;
144
145 for (i = 0; i < cacert_count; i++)
146 {
147 cert = sk_X509_value(cacerts, i);
148 if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL)
149 goto error;
150 PyTuple_SET_ITEM(self->cacerts, i, cacertobj);
151 }
152 }
153
154 sk_X509_free(cacerts); /* don't free the certs, just the stack */
155 PyObject_GC_Track(self);
156
157 return self;
158error:
159 crypto_PKCS12_dealloc(self);
160 return NULL;
161}
162
163/*
164 * Find attribute
165 *
166 * Arguments: self - The PKCS12 object
167 * name - The attribute name
168 * Returns: A Python object for the attribute, or NULL if something went
169 * wrong
170 */
171static PyObject *
172crypto_PKCS12_getattr(crypto_PKCS12Obj *self, char *name)
173{
174 return Py_FindMethod(crypto_PKCS12_methods, (PyObject *)self, name);
175}
176
177/*
178 * Call the visitproc on all contained objects.
179 *
180 * Arguments: self - The PKCS12 object
181 * visit - Function to call
182 * arg - Extra argument to visit
183 * Returns: 0 if all goes well, otherwise the return code from the first
184 * call that gave non-zero result.
185 */
186static int
187crypto_PKCS12_traverse(crypto_PKCS12Obj *self, visitproc visit, void *arg)
188{
189 int ret = 0;
190
191 if (ret == 0 && self->cert != NULL)
192 ret = visit(self->cert, arg);
193 if (ret == 0 && self->key != NULL)
194 ret = visit(self->key, arg);
195 if (ret == 0 && self->cacerts != NULL)
196 ret = visit(self->cacerts, arg);
197 return ret;
198}
199
200/*
201 * Decref all contained objects and zero the pointers.
202 *
203 * Arguments: self - The PKCS12 object
204 * Returns: Always 0.
205 */
206static int
207crypto_PKCS12_clear(crypto_PKCS12Obj *self)
208{
209 Py_XDECREF(self->cert);
210 self->cert = NULL;
211 Py_XDECREF(self->key);
212 self->key = NULL;
213 Py_XDECREF(self->cacerts);
214 self->cacerts = NULL;
215 return 0;
216}
217
218/*
219 * Deallocate the memory used by the PKCS12 object
220 *
221 * Arguments: self - The PKCS12 object
222 * Returns: None
223 */
224static void
225crypto_PKCS12_dealloc(crypto_PKCS12Obj *self)
226{
227 PyObject_GC_UnTrack(self);
228 crypto_PKCS12_clear(self);
229 PyObject_GC_Del(self);
230}
231
232PyTypeObject crypto_PKCS12_Type = {
233 PyObject_HEAD_INIT(NULL)
234 0,
235 "PKCS12",
236 sizeof(crypto_PKCS12Obj),
237 0,
238 (destructor)crypto_PKCS12_dealloc,
239 NULL, /* print */
240 (getattrfunc)crypto_PKCS12_getattr,
241 NULL, /* setattr */
242 NULL, /* compare */
243 NULL, /* repr */
244 NULL, /* as_number */
245 NULL, /* as_sequence */
246 NULL, /* as_mapping */
247 NULL, /* hash */
248 NULL, /* call */
249 NULL, /* str */
250 NULL, /* getattro */
251 NULL, /* setattro */
252 NULL, /* as_buffer */
253 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
254 NULL, /* doc */
255 (traverseproc)crypto_PKCS12_traverse,
256 (inquiry)crypto_PKCS12_clear,
257};
258
259/*
260 * Initialize the PKCS12 part of the crypto sub module
261 *
262 * Arguments: dict - The crypto module dictionary
263 * Returns: None
264 */
265int
266init_crypto_pkcs12(PyObject *dict)
267{
268 crypto_PKCS12_Type.ob_type = &PyType_Type;
269 Py_INCREF(&crypto_PKCS12_Type);
270 PyDict_SetItemString(dict, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type);
271 return 1;
272}
273