/* * pkcs12.c * * Copyright (C) AB Strakt 2001, All rights reserved * * Certificate transport (PKCS12) handling code, * mostly thin wrappers around OpenSSL. * See the file RATIONALE for a short explanation of why * this module was written. * * Reviewed 2001-07-23 */ #include #define crypto_MODULE #include "crypto.h" static char *CVSid = "@(#) $Id: pkcs12.c,v 1.2 2004/09/23 14:25:28 murata Exp $"; /* * PKCS12 is a standard exchange format for digital certificates. * See e.g. the OpenSSL homepage http://www.openssl.org/ for more information */ static void crypto_PKCS12_dealloc(crypto_PKCS12Obj *self); static char crypto_PKCS12_get_certificate_doc[] = "\n\ Return certificate portion of the PKCS12 structure\n\ \n\ Arguments: self - The PKCS12 object\n\ args - The Python argument tuple, should be empty\n\ Returns: X509 object containing the certificate\n\ "; static PyObject * crypto_PKCS12_get_certificate(crypto_PKCS12Obj *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":get_certificate")) return NULL; Py_INCREF(self->cert); return self->cert; } static char crypto_PKCS12_get_privatekey_doc[] = "\n\ Return private key portion of the PKCS12 structure\n\ \n\ Arguments: self - The PKCS12 object\n\ args - The Python argument tuple, should be empty\n\ Returns: PKey object containing the private key\n\ "; static PyObject * crypto_PKCS12_get_privatekey(crypto_PKCS12Obj *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":get_privatekey")) return NULL; Py_INCREF(self->key); return self->key; } static char crypto_PKCS12_get_ca_certificates_doc[] = "\n\ Return CA certificates within of the PKCS12 object\n\ \n\ Arguments: self - The PKCS12 object\n\ args - The Python argument tuple, should be empty\n\ Returns: A newly created tuple containing the CA certificates in the chain,\n\ if any are present, or None if no CA certificates are present.\n\ "; static PyObject * crypto_PKCS12_get_ca_certificates(crypto_PKCS12Obj *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":get_ca_certificates")) return NULL; Py_INCREF(self->cacerts); return self->cacerts; } /* * ADD_METHOD(name) expands to a correct PyMethodDef declaration * { 'name', (PyCFunction)crypto_PKCS12_name, METH_VARARGS, crypto_PKCS12_name_doc } * for convenience */ #define ADD_METHOD(name) \ { #name, (PyCFunction)crypto_PKCS12_##name, METH_VARARGS, crypto_PKCS12_##name##_doc } static PyMethodDef crypto_PKCS12_methods[] = { ADD_METHOD(get_certificate), ADD_METHOD(get_privatekey), ADD_METHOD(get_ca_certificates), { NULL, NULL } }; #undef ADD_METHOD /* * Constructor for PKCS12 objects, never called by Python code directly. * The strategy for this object is to create all the Python objects * corresponding to the cert/key/CA certs right away * * Arguments: p12 - A "real" PKCS12 object * passphrase - Passphrase to use when decrypting the PKCS12 object * Returns: The newly created PKCS12 object */ crypto_PKCS12Obj * crypto_PKCS12_New(PKCS12 *p12, char *passphrase) { crypto_PKCS12Obj *self; PyObject *cacertobj = NULL; X509 *cert = NULL; EVP_PKEY *pkey = NULL; STACK_OF(X509) *cacerts = NULL; int i, cacert_count = 0; /* allocate space for the CA cert stack */ cacerts = sk_X509_new_null(); /* parse the PKCS12 lump */ if (!(cacerts && PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts))) { exception_from_error_queue(); return NULL; } if (!(self = PyObject_New(crypto_PKCS12Obj, &crypto_PKCS12_Type))) return NULL; self->cert = NULL; self->key = NULL; Py_INCREF(Py_None); self->cacerts = Py_None; if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL) goto error; if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL) goto error; /* Make a tuple for the CA certs */ cacert_count = sk_X509_num(cacerts); if (cacert_count > 0) { Py_DECREF(self->cacerts); if ((self->cacerts = PyTuple_New(cacert_count)) == NULL) goto error; for (i = 0; i < cacert_count; i++) { cert = sk_X509_value(cacerts, i); if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL) goto error; PyTuple_SET_ITEM(self->cacerts, i, cacertobj); } } sk_X509_free(cacerts); /* don't free the certs, just the stack */ return self; error: crypto_PKCS12_dealloc(self); return NULL; } /* * Deallocate the memory used by the PKCS12 object * * Arguments: self - The PKCS12 object * Returns: None */ static void crypto_PKCS12_dealloc(crypto_PKCS12Obj *self) { Py_XDECREF(self->cert); Py_XDECREF(self->key); Py_XDECREF(self->cacerts); PyObject_Del(self); } /* * Find attribute * * Arguments: self - The PKCS12 object * name - The attribute name * Returns: A Python object for the attribute, or NULL if something went * wrong */ static PyObject * crypto_PKCS12_getattr(crypto_PKCS12Obj *self, char *name) { return Py_FindMethod(crypto_PKCS12_methods, (PyObject *)self, name); } PyTypeObject crypto_PKCS12_Type = { PyObject_HEAD_INIT(NULL) 0, "PKCS12", sizeof(crypto_PKCS12Obj), 0, (destructor)crypto_PKCS12_dealloc, NULL, /* print */ (getattrfunc)crypto_PKCS12_getattr, NULL, /* setattr */ NULL, /* compare */ NULL, /* repr */ NULL, /* as_number */ NULL, /* as_sequence */ NULL, /* as_mapping */ NULL /* hash */ }; /* * Initialize the PKCS12 part of the crypto sub module * * Arguments: dict - The crypto module dictionary * Returns: None */ int init_crypto_pkcs12(PyObject *dict) { crypto_PKCS12_Type.ob_type = &PyType_Type; Py_INCREF(&crypto_PKCS12_Type); PyDict_SetItemString(dict, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type); return 1; }