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